我正在使用ANTLR和以下语法:
grammar QuickBasic;
options
{
language = 'CSharp2';
output = AST;
}
parse
: block EOF
;
block
: (labelStatement | labeledStatement | statement)*
;
labelStatement
: label ':' -> ^(label)
;
labeledStatement
: label statement -> ^(label statement)
;
statement
: assignment
;
assignment
: IDENTIFIER '=' value -> ^('=' IDENTIFIER value)
;
value
: (IDENTIFIER | constant)
;
constant
: (STRING | INTEGER | REAL)
;
label
: (ALPHANUMERIC)+
;
IDENTIFIER
: LETTER (ALPHANUMERIC)*
;
REAL
: (INTEGER '.' NATURAL)
;
INTEGER
: ('-')? NATURAL
;
SPACE
: (' ' | '\t' | '\r' | '\n' | '\u000C') {Skip();}
;
STRING
: '"' ('""' | ~'"')* '"'
;
fragment NATURAL
: (DIGIT)+
;
fragment ALPHANUMERIC
: (DIGIT | LETTER)
;
fragment DIGIT
: '0'..'9'
;
fragment LETTER
: ('a'..'z' | 'A'..'Z')
;
有了这个,我正在尝试解析下面的文件:
PI = 3.141592
CALC:
100 A = 1
接下来发生的是'CALC:'行应该是一个标签,但是它会尝试解析为一个语句,并给出一个错误,指出输入不匹配':'期待'='。
答案 0 :(得分:2)
您的label
规则错误:
label
: (ALPHANUMERIC)+
;
因为ALPHANUMERIC
是片段词法分析器规则,它只能被其他词法分析器规则使用,而不能在解析器规则中使用。您的词法分析器只会生成以下令牌:IDENTIFIER
,INTEGER
,REAL
和STRING
(以及解析器规则中的文字标记,如'.'
等。 ):使这些规则可以在解析器规则中使用。
此外,您应该只创建具有单个唯一根的AST。您正在尝试为labelStatement
和labeledStatement
创建一个根目录,使其无法与其他解析器规则区分开来:制作树步行者(ANTLR的树步行者或您自己的树步行者)当他们遇到这样一个AST的根时出现问题。创建(虚构的)LABEL
和LABELED_STAT
标记要好得多,使它们成为AST的根源:
...
tokens
{
LABEL;
LABELED_STAT;
}
parse
: block EOF
;
...
labelStatement
: label ':' -> ^(LABEL label)
;
labeledStatement
: label statement -> ^(LABELED_STAT label statement)
;
...
label
: IDENTIFIER
| INTEGER
;
这将创建以下AST:
答案 1 :(得分:0)
尝试使用小写skip()而不是Skip()和类似的东西来允许多个空格
SPACE
: (' ' | '\t' | '\u000C' | '\n' | '\r' )+ {skip();}
;