使用ANTLR的QuickBasic语法

使用ANTLR的QuickBasic语法,antlr,Antlr,我正在使用ANTLR和以下语法: grammar QuickBasic; options { language = 'CSharp2'; output = AST; } parse : block EOF ; block : (labelStatement | labeledStatement | statement)* ; labelStatement : label ':' -> ^(label)

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

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

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

您的
标签
规则错误:

label
    :    (ALPHANUMERIC)+
    ;
因为
字母数字
是一个片段词法规则,所以它只能由其他词法规则使用,而不能在解析器规则中使用。您的lexer将只生成以下标记:
IDENTIFIER
INTEGER
REAL
STRING
(加上解析器规则中的文字标记,如
等):使这些成为您可以在解析器规则中使用的唯一lexer规则

此外,您应该只创建具有唯一根的AST。您正试图为
labelStatement
labeledStatement
创建一个根,这使得它无法与其他解析器规则区分开来:使树漫游者(ANTLR的树漫游者或您自己的树漫游者)在遇到此类AST的根时出现问题。最好创建(虚拟的)
LABEL
LABEL\u STAT
标记,并将它们作为AST的根:

...

tokens 
{
    LABEL;
    LABELED_STAT;
}

parse
    :    block EOF
    ;

...

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

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

...

label
    :    IDENTIFIER
    |    INTEGER
    ;
这将创建以下AST:

我以为“skip()”只是java基类“Lexer”上的一个方法。。。当我使用c#时,方法是“Skip()”。这是正确的吗?不,
Skip()
而不是
Skip()
,并且在
空间中添加
+
规则不会有什么区别。(@JonathasCosta,是的,你是对的)。