1

我正在使用 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:'行应该是一个标签,但它试图解析为一个语句,并给我一个错误,说不匹配的输入':'期待'='。

4

2 回答 2

2

你的label规则是错误的:

label
    :    (ALPHANUMERIC)+
    ;

因为ALPHANUMERIC是一个片段词法分析器规则,它只能被其他词法分析器规则使用,而不能在解析器规则中使用。您的词法分析器将仅生成以下标记:IDENTIFIER、、INTEGER和(REAL以及STRING解析器规则中的文字标记,例如'.'等):使这些成为您可以在解析器规则中使用的唯一词法分析器规则。

此外,您应该只创建具有单个唯一根的 AST。您正在尝试为两者创建一个根,这labelStatement不会labeledStatement使其与其他解析器规则区分开来:使 tree walker(ANTLR 的 tree walker 或您自己的 tree walker)在遇到此类 AST 的根时遇到问题. 更好地创建(想象的)LABELLABELED_STAT令牌并使它们成为您的 AST 的根:

...

tokens 
{
    LABEL;
    LABELED_STAT;
}

parse
    :    block EOF
    ;

...

labelStatement
    :    label ':' -> ^(LABEL label)
    ;

labeledStatement
    :    label statement -> ^(LABELED_STAT label statement)
    ;

...

label
    :    IDENTIFIER
    |    INTEGER
    ;

这将创建以下 AST:

在此处输入图像描述

于 2012-05-29T07:53:09.627 回答
0

尝试使用小写的 skip() 而不是 Skip() 和类似的东西来允许多个空格

SPACE
    :    (' ' | '\t' | '\u000C' | '\n' | '\r' )+ {skip();} 
    ;
于 2012-05-29T05:02:17.117 回答