使用ANTLR的QuickBasic语法

时间:2012-05-29 03:57:31

标签: antlr

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

2 个答案:

答案 0 :(得分:2)

您的label规则错误:

label
    :    (ALPHANUMERIC)+
    ;

因为ALPHANUMERIC是片段词法分析器规则,它只能被其他词法分析器规则使用,而不能在解析器规则中使用。您的词法分析器只会生成以下令牌:IDENTIFIERINTEGERREALSTRING(以及解析器规则中的文字标记,如'.'等。 ):使这些规则可以在解析器规则中使用。

此外,您应该只创建具有单个唯一根的AST。您正在尝试为labelStatementlabeledStatement创建一个根目录,使其无法与其他解析器规则区分开来:制作树步行者(ANTLR的树步行者或您自己的树步行者)当他们遇到这样一个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:

enter image description here

答案 1 :(得分:0)

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

SPACE
    :    (' ' | '\t' | '\u000C' | '\n' | '\r' )+ {skip();} 
    ;