【问题标题】:Parsing DECAF grammar in ANTLR在 ANTLR 中解析 DECAF 语法
【发布时间】:2015-01-14 18:28:54
【问题描述】:

我正在使用 Antlr 创建 DECAF 解析器 语法 DECAF ;

//********* LEXER ******************
LETTER: ('a'..'z'|'A'..'Z') ;
DIGIT : '0'..'9' ;
ID : LETTER( LETTER | DIGIT)* ;
NUM: DIGIT(DIGIT)* ;
COMMENTS: '//' ~('\r' | '\n' )*  -> channel(HIDDEN);
WS : [ \t\r\n\f | ' '| '\r' | '\n' | '\t']+  ->channel(HIDDEN); 

CHAR: (LETTER|DIGIT|' '| '!' | '"' | '#' | '$' | '%' | '&' | '\'' | '(' | ')' | '*' | '+' 

| ',' | '-' | '.' | '/' | ':' | ';' | '<' | '=' | '>' | '?' | '@' | '[' | '\\' | ']' | '^' | '_' | '`'| '{' | '|' | '}' | '~' 
'\t'| '\n' | '\"' | '\'');


// ********** PARSER *****************

program : 'class' 'Program' '{' (declaration)* '}'  ;

declaration: structDeclaration| varDeclaration | methodDeclaration  ;

varDeclaration: varType ID ';' | varType ID '[' NUM ']' ';'  ;

structDeclaration : 'struct' ID '{' (varDeclaration)* '}'  ;

varType: 'int' | 'char' | 'boolean' | 'struct' ID | structDeclaration | 'void'  ;

methodDeclaration : methodType ID '(' (parameter (',' parameter)*)* ')' block  ;

methodType : 'int' | 'char' | 'boolean' | 'void' ;

parameter : parameterType ID | parameterType ID '[' ']' ;

parameterType: 'int' | 'char' | 'boolean'  ;

block : '{' (varDeclaration)* (statement)* '}' ;

statement : 'if' '(' expression ')' block ( 'else' block )? 
           | 'while' '(' expression ')' block
           |'return' expressionA ';' 
           | methodCall ';' 
           | block  
           | location '=' expression 
           | (expression)? ';'  ;

expressionA: expression | ;


location : (ID|ID '[' expression ']') ('.' location)?  ;

expression : location | methodCall | literal | expression op expression | '-' expression | '!' expression | '('expression')'  ;

methodCall :    ID '(' arg1 ')' ;

arg1    :   arg2 | ;

arg2    :   (arg) (',' arg)* ;

arg :   expression;

op: arith_op | rel_op | eq_op | cond_op  ;

arith_op : '+' | '-' | '*' | '/' | '%' ;

rel_op : '<' | '>' | '<=' | '>=' ;

eq_op : '==' | '!=' ;

cond_op : '&&' | '||' ;

literal : int_literal | char_literal | bool_literal ;

int_literal : NUM ;

char_literal : '\'' CHAR '\'' ;

bool_literal : 'true' | 'false' ;

当我给它输入时:

    class Program {

    void main(){

        return 3+5 ;
    }
    }

解析树没有正确构建,因为它没有将 3+5 识别为表达式。我的语法有什么问题导致问题吗?

【问题讨论】:

    标签: antlr grammar


    【解决方案1】:

    Lexer 规则从上到下匹配。当 2 个或更多词法分析器规则匹配相同数量的字符时,第一个定义的将 win。因此,单个数字整数将匹配为 DIGIT 而不是 NUM

    尝试解析以下内容:

    class Program {
        void main(){    
            return 33 + 55 ;
        }
    }
    

    这将被很好地解析。这是因为3355 匹配为NUMs,因为NUM 现在可以匹配2 个字符(DIGIT 只有1 个,所以NUM 胜)。

    要修复它,请将DIGIT 设为片段(以及LETTER):

    fragment LETTER: ('a'..'z'|'A'..'Z') ;
    fragment DIGIT : '0'..'9' ;
    ID : LETTER( LETTER | DIGIT)* ;
    NUM: DIGIT(DIGIT)* ;
    

    Lexer 片段仅供其他词法分析器规则在内部使用,永远不会成为它们自己的标记。

    其他几件事:您的 WS 规则匹配太多(它现在还匹配 |'),应该是:

    WS : [ \t\r\n\f]+  ->channel(HIDDEN);
    

    并且您不应该在解析器中匹配字符文字:在词法分析器中进行:

    CHAR : '\'' ( ~['\r\n\\] | '\\' ['\\] ) '\'';
    

    如果不这样做,将无法正确解析以下内容:

    class Program {
        void main(){
            return '1';
        }
    }
    

    因为1 将被标记为NUM 而不是CHAR

    【讨论】:

    • 非常感谢您的帮助!我不知道片段关键字:)。也感谢 whitspace 的帮助
    猜你喜欢
    • 1970-01-01
    • 2016-11-09
    • 1970-01-01
    • 2021-08-15
    • 2011-01-30
    • 1970-01-01
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多