宿迁建设局网站,服装设计软件有哪些软件,wordpress分页显示,pc端网站建设价格明细表ANTLR4入门学习#xff08;四#xff09;一、设计语法1.语法2.ANTLR核心标记3.常见计算机语言模式4.左右递归5.识别常见的语法结构5.1 匹配标识符5.2 匹配数字5.3 匹配字符串常量5.4 匹配注释和空白字符5.5 基础的语法规则5.6 划定词法分析器和语法分析器的界线一、设计语法 …
ANTLR4入门学习四一、设计语法1.语法2.ANTLR核心标记3.常见计算机语言模式4.左右递归5.识别常见的语法结构5.1 匹配标识符5.2 匹配数字5.3 匹配字符串常量5.4 匹配注释和空白字符5.5 基础的语法规则5.6 划定词法分析器和语法分析器的界线一、设计语法
序列一列元素一个数组初始化语句中的值选择在多种可选方案中做出选择例如编程语言中的不同种类的语句词法符号依赖一个词法符号需要和某处的另外一个词法符号配对例如左右括号匹配嵌套结构一种自相似的语言结构例如编程语言中的嵌套算数表达式或者嵌套语句块
1.语法
语法由一个为该语法命名的头部定义和一系列可以相互引用的语言规则组成
grammar MyG;
rule1 : stuff;
rule2 : more stuff;
...必须指明需要的语言规则其中stuff的具体内容以及那条规则是起始规则 一个CSV文件就是一系列以换行符为终止的行。a comma-separated-value[CSV]file is a sequence of rows terminated by newlines.其中is a左侧的单词file就是规则名右侧的全部内容就是规则定义中的stuff。
file : sequence of rows terminated by newlines;降低层次描述起始规则右侧所指定的元素通常是词法符号或者尚未定义的规则。 再降低一层一个行就是一系列由逗号分隔的字段a row is sequence of fields separated by commas。一个字段就是一个数字或者字符串a field is a number or string。
file : sequence of rows terminated by newlines;
row : sequence of fields separated by commas
field : number or string;2.ANTLR核心标记
用法描述x匹配词法符号、规则引用或者子规则xx y … z匹配一列规则元素…|…|…一个具有多个备选分支的子规则x?匹配x或者忽略它x*匹配x零次或多次x匹配x一次或多次r : … ;定义规则rr : … | … | …;定义具有多个备选分支的规则r
3.常见计算机语言模式
模式名描述序列模式它是一个有限长度或者任意长度的序列序列中的元素可以是词法符号或者子规则、序列模式的例子包括变量声明类型后面紧跟着标识符和整数序列范例 x y … z // x后面跟着y , … , z ‘[’ INT ‘]’ // Matlab的整数向量带终止符的序列模式它是一个任意长的、可能为空的序列该序列由一个词法符号分隔开通常是分号或者换行符其中的元素可以是词法符号或子规则范例 (statement ‘;’)* //java的语句集合 (row ‘\n’)* //多行数据带分隔符的序列模式它是一个任意长的、可能为空的序列该序列由一个词法符号分隔开通常是逗号、分号或是句号其中的元素可以是词法符号或子规则范例 expr (‘,’ expr)* // 函数调用时传递的参数 (expr (‘,’ expr)* )? // 函数调用时传递的参数是可选的 ‘/’? name (‘/’ name)* //简化的目录名 stat (‘.’ stat)* //若干个SmallTalk程序设计语言)语句选择模式它是一组备选分支的集合这样的例子包括不同种类的类型、语句、表达式或者XML标签范例 type : ‘int’ | ‘flloat’ ; stat : ifstat | whilestat | ‘return’ expr ‘;’ expr : ‘(’ expr ‘)’ | INT | ID ; tag : ‘’ Name attribute* ‘’ | ‘’ ‘/’ Name ‘’ ;词法符号依赖一个词法符号需要和一个或者多个后续词法符号匹配这样的例子包括配对的圆括号、花括号、方括号和尖括号范例 ‘(’ expr ‘)’ // 嵌套表达式 ID ‘[’ expr ‘]’ // 数组索引表达式 ‘{’ stat* ‘}’ // 花括号包裹的若干个语句 ‘’ ID (‘,’ ID)* ‘’ //泛型声明嵌套模式它是一种自相似的语言结构这样的例子包括表达式、Java的内部类、嵌套的代码块以及嵌套的Python函数定义范例 expr : ‘(’ expr ‘)’ | ID ; classDef : ‘class’ ID ‘{’ (classDef | method | field) ‘}’ ;
4.左右递归
ANTLR4 可以处理直接左递归但是不能处理间接左递归但最好不要使用左递归 ANTLR 由上到下 优先级依次降低
expr : expr ^ assocright expr // ^运算符是右结合的 最好写成 assocright expr ^ expr| expr * expr // 匹配由 * 运算符连接的子表达式| expr expr // 匹配由 运算符连接的子表达式| INT // 匹配简单的整数因子但是ANTLR无法处理间接左递归 error:
expr : expo // 通过expo规则间接左递归调用expr规则| ...;
expo : expr ^ assocright expr;尽管语义等价但是无法将expr规则按上述分解
5.识别常见的语法结构
5.1 匹配标识符
语法伪代码中一个基本的标识符就是一个由大小写字母组成的字符序列可以用(…)表示也可以用正则表示
ID : (A..Z|a..z) ; 匹配1个或者多个大小写字母
ID : [a-z]A-Z] ; 匹配1个或者多个大小写字母ANTLR从文法规则中筛选除所有的字符串常量并将他们和词法规则放在一起。enum’这样的字符串常量被隐式定义为词法规则然后放置在文法规则之后、显示定义的词法规则之前ANTLR词法分析器解决歧义问题的方法是优先使用位置靠前的词法规则。ID规则必须定义在所有的关键字规则之后 。
5.2 匹配数字
匹配整数
INT : 0..9 ; // 匹配1个或多个数字
INT : [0-9] ; // 匹配1个或多个数字匹配浮点数 一个浮点数以一列数字为开头后面跟着一个点然后是可选的小数部分浮点数的另一个格式以点为开头后面是一列数字使用选择模式或序列模式
FLOAT : DIGIT , DIGIT* // 匹配1.39.3.14159| . DIGIT //匹配 .1, .14159;
fragment
DIGIT : [0-9]; // 匹配单个数字fragment 可以告诉ANTLR这条规则本身不是一个语法符号它只会被其他的词法规则使用这意味着我们不能再文法规则中引用DIGIT
5.3 匹配字符串常量
STRING : .*? ; // 匹配...间的任意文本.*是一个循环匹配零个或多个字符组成的任意字符序列可以匹配到文件结束ANTLR通过标准正则表达式的标记后缀提供了对非贪婪匹配子规则的支持获取一些字符直到发现匹配后续子规则的字符为止再保证整个父规则完成匹配的前提下非贪婪的子规则匹配数量最少的字符。
STRING : (ESC|.)*? ;
fragment
ESC : \\ | \\\\ ; // 双字符序列 \ 和 \\其中ANTLR语法本身需要对转义字符\进行转义因此我们需要\来表示单个反斜杠字符 STRING规则中的循环既能通过ESC片段规则(fragment rule)来匹配转义字符序列也能通过通配符来匹配任意单个字符。?运算符会使 (ESC|.)? 循环在看到子后续子规则即一个未转义的双引号时终止。
5.4 匹配注释和空白字符
assign : ID (WS|COMMENT)? (WS|COMMENT)? expr (WS|COMMENT)? ;
LINE_COMMENT : // .*? \r? \n - skip ; // 匹配 // 任意字符序列 \n
COMMENT : /* .*? */ - skip ; // 匹配/* 任意字符序列 */
WS : ( |\t|\r|\n]) - skip ; // 匹配一个或多个空白字符并将它们丢弃
WS : [ \r\t\n] - skip ;skip指令通知词法分析器将它们丢弃即可 词法分析器可以接受许多种位于- 操作符之后的指令skip只是其中之一。
5.5 基础的语法规则
词法符号类型描述及范例标点符号处理运算符和标点符号最容易的方式就是直接在文法规则中引用它们。 call : ID ‘(’ exprList ‘)’ ; 一些开发者更愿意定义类型LP左括号, left parcnthesis的词法符号标签。 call : ID LP exprList RP ; LP : ‘(’ ; RP : ‘)’ ;关键字关键字是保留的标识符我们既可以直接引用它们也可以为它们定义词法符号类型 returnStat : ‘return’ expr ‘;’标识符几乎每种语言中的标识符看上去都差不多它们之间的差异通常在与第一个字符的可选值以及是否允许Unicode字符。 ID ID_LETTER (ID_LETTER | DIGIT) *; // C语言的语法片段 fragment ID_LETTER : ‘a’…‘z’|‘A’…‘Z’|‘…’ ; fragment DIGIT : ‘0’…9’;数字范例 INT : DIGIT; FLOAT : DIGIT ‘.’ DIGIT* | ‘.’ DIGIT;字符串匹配双引号包围的字符串 STRING : ‘’ (ESC |.)*? ‘’ ; fragment ESC : ‘\’ | ‘\\’ ; // 双字符序列 和 |注释匹配并丢弃注释 LINE_COMMENT : ‘//’ .? ‘\r’? ‘\n’ - skip ; // 匹配 “//” 任意字符序列 ‘\n’ COMMENT : /’ .? /’ - skip ; // 匹配/* 任意字符序列 “*/”空白字符WS : [ \r\t\n] - skip ;
5.6 划定词法分析器和语法分析器的界线
在词法分析器中匹配并丢弃任何语法分析器无须知晓的东西。对于编程语言来说要识别并丢弃的就是类似注释和空白字符的东西。由词法分析器来匹配类似标识符、关键字、字符串和数字的常见词法符号。语法分析器的层级更高所以我们不应当让它处理将数字组合成整数这样的事情。将语法分析器无须区分的词法结构归为同一个词法符号类型。将任何语法分析器可以以相同方式处理的实体归为一类。如果语法分析器许哟把一种类型的文本拆开处理那么词法分析器就应该将它的各组成部分作为独立的词法符号输送给语法分析器。语法分析器无须区分特定的词法结构或者无须关心某个词法结构的内容时实际上是我们编写的程序不关心它们。
例如
192.168.209.85 GET /download/foo.html HTTP/1.0 200如果只想要统计总行数可以忽略除换行符之外的一切字符
file : NL ; // 匹配换行符序列的语法分析器
STUFF : ~\n - skip; // 除\n之外的字符全部丢弃
NL : \n ; // 将设定的换行符返回给语法分析器或者其他的调用者从日志文件中提取IP地址的列表
file : row; // 匹配日志文件中的全部行的文法规则
row : IP STRING INT NL ; // 匹配日志文件中的一行记录IP : INT . INT . INT . INT ; // 192.168.209.85
INT : [0-9] ; // 匹配IP地址中的一个字节或者HTTP的状态码
STRING : .*? ; // 匹配HTTP请求的首行
NL : \n ; // 匹配一行记录的终止符
WS : - skip ; // 忽略空格