元语言词汇表空格定义 空格,tab符号和换行符号在ANTLR分隔诸如标识符这样的词汇符号时作为分隔符。在这之外,它们是被忽略的。例如,“FirstName LastName”对ANTLR来说两个标记符而不是一个标记符,空格,然后再接着一个标记符。
注释
ANTLR 接受C语言风格的块注释和C++风格的行注释。在语法类和规则中,Java风格的文档注释也是可以接受的,在需要的时候,这些注释可以被传递给生成的输出文件。例如
/**This grammar recognizes simple expressions
* @author Terence Parr
*/
class ExprParser;
/**Match a factor */
factor : ... ;
字符集
字符常数像Java中那样被确定。它们包含八进制转义字符集(e.g., '\377'),Unicode字符集(e.g., '\uFF00'),和能被Java识别的常用的字符转义('\b', '\r', '\t', '\n', '\f', '\'', '\\')。在词法分析器规则中,单引号代表一个可以在输入字符流中能得到匹配的的字符。在语法分析器中是不被支持单引号的字符的。
文件结束标志 EOF 标记用语法分析器规则中自动生成:
rule : (statement)+ EOF;
你可以在词法分析器规则的动作中检测EOF_CHAR符号:
// make sure nothing but newline or
// EOF is past the #endif
ENDIF
{
boolean eol=false;
}
: "#endif"
( ('\n' | '\r') {eol=true;} )?
{
if (!eol) {
if (LA(1)==EOF_CHAR) {error("EOF");}
else {error("Invalid chars");}
}
}
;
当你将文件结束当一个字符来检测时,它实际上并不是一个字符,而是一个条件。
你可以在你的词法分析器语法中覆盖 CharScanner.uponEOF()函数:
/** This method is called by YourLexer.nextToken()
* when the lexer has
* hit EOF condition. EOF is NOT a character.
* This method is not called if EOF is reached
* during syntactic predicate evaluation or during
* evaluation of normal lexical rules, which
* presumably would be an IOException. This
* traps the "normal" EOF * condition.
*
* uponEOF() is called after the complete evaluation
* of the previous token and only if your parser asks
* for another token beyond that last non-EOF token.
*
* You might want to throw token or char stream
* exceptions like: "Heh, premature eof" or a retry
* stream exception ("I found the end of this file,
* go back to referencing file").
*/
public void uponEOF()
throws TokenStreamException, CharStreamException
{
}
文件结束条件是一个位比特(从2.7.1版本开始)。因为Terence 将-1当作一个字符而不是一个整型数。(-1 是 '\uFFFF'...晕!).
字符串
字符串常数一个由双引号括起来的一系列字符。在字符串中的字符可以是作为字符也同样合法的转义字符(八进制,Unicode等)。当前,ANTLR实际上不允许Unicode出现在字符串常量中(你不得不用转义符)。这是因为在anglr.g文件中设定charVocabulary选项为ascii.
在词法分析器规则中,字符串被解释成可以在输入流中匹配的一系列字符 (例如., "for" 等于 'f' 'o' 'r').
在语法分析器规则中,字符串代表一个个标记(tokens),并且每个独立的字符串被分派一个标记类型。然而,ANTLR不会创建一个词法分析器规则来匹配这些字符串。相反,ANTLR将这些字符串输入到一个于词法分析器关联的字符常量表中。ANTLR将针对字符常量表来产生代码检测每个标记中的文本,在手动关掉语法分析器对该标记的处理之前获得一个匹配时,会改变标记的类型。你也可以执行手动检测――自动代码生成可以通过词法分析器选项控制。
你可能想在你的动作中使用这些字符串常量的标记的类型值,例如在错误处理器的同步部分。对于只由字母字符组成的字符串常量来说,这个字符串常量的值将是一个形如LITERAL_xxx的常量值,这里xxx是这个标记的名字。例如,文字“return”将有一个LITERAL_return值与之关联。你也可以用标记节(tokens section)分派一个特定的标号给这个文字。
标记引用
以大写字符开头的标识符称为标记引用。接下来的字符可以是任何字符,数字或下划线。在语法分析器规则中一个标记引用将导致匹配特定的标记。在词法分析器中的标记引用将导致调用一个词法规则来匹配该标记的字符。换句话说,在词法分析器中的标记引用将对当作一个规则引用。
标记定义
在词法分析器中的标记定义由和语法规则中相同的定义。但是当做标记而不是语法规则。例如,
class MyParser extends Parser;
idList : ( ID )+; // parser rule definition
class MyLexer extends Lexer;
ID : ( 'a'..'z' )+ ; // token definition
规则引用
以小写字母开头的标识符是为ANTLR的语法规则。接下来的字符可以是任意字母,数字或下划线。词法规则不能引用语法规则。
动作.
在尖括号中的字符序列是语义动作(可能是嵌套的)。在字符串和字符中的尖括号不是动作分隔符。
动作参数
在方括号中的字符序列是动作参数(可能是嵌套的)。在字符串和字符中的方括号不是动作分隔符。在[]中的参数是用被生成的语言的语法定义的,并且用逗号分开。
codeBlock
[int scope, String name] // input arguments
returns [int x] // return values
: ... ;
// pass 2 args, get return
testcblock
{int y;}
: y=cblock[1,"John"]
;
许多人喜欢我们用普通的括号来括住参数,但是括号在EBNF中已经被很好的用来定义语法组符号(grammatical grouping symbols)。
符号 下面的表统计了在ANTLR中使用的标点符号和关键字。
符号
描述
(...)
子规则
(...)*
闭包子规则(零和多个)
(...)+
正闭包子规则(一个和多个)
(...)?
可选(零个和一个)
{...}
语义动作
[...]
规则参数
{...}?
语义谓词
(...)=>
语法谓词
|
可选符
..
范围符
~
非
.
通配符
=
赋值
:
标号符, 规则开始
;
规则结束
<...>
元素选项
class
语法类
extends
指定语法基类
returns
指定返回类型
options
options 节
tokens
tokens 节
header
header 节
tokens
token 定义节