【问题标题】:Antlr left recursive problemAntlr 左递归问题
【发布时间】:2010-01-21 23:09:11
【问题描述】:

我的 Antlr 语法中有一个左递归问题。虽然我认为我理解为什么会出现问题,但我无法想到解决方案。问题在于我的数据类型规则的最后一行。我已经包含了整个语法供您查看:

grammar Test;

options {output=AST;ASTLabelType=CommonTree;}
tokens {FUNCTION; ATTRIBUTES; CHILDREN; COMPOSITE;}

program     :   function ;
function    :   ID (OPEN_BRACKET (attribute (COMMA? attribute)*)? CLOSE_BRACKET)? (OPEN_BRACE function* CLOSE_BRACE)? SEMICOLON? -> ^(FUNCTION ID ^(ATTRIBUTES attribute*) ^(CHILDREN function*)) ;

attribute   :   ID (COLON | EQUALS)  datatype -> ^(ID datatype);

datatype    :   ID      ->  ^(STRING["id"] ID)
            |   NUMBER  ->  ^(STRING["number"] NUMBER)
            |   STRING  ->  ^(STRING["string"] STRING)
            |   BOOLEAN ->  ^(STRING["boolean"] BOOLEAN)
            |   array   ->  ^(STRING["array"] array)
            |   lookup  ->  ^(STRING["lookup"] lookup)
            |   datatype PLUS datatype -> ^(COMPOSITE datatype datatype) ;

array       :   OPEN_BOX (datatype (COMMA datatype)*)? CLOSE_BOX -> datatype* ;
lookup      :   OPEN_BRACE (ID (PERIOD ID)*) CLOSE_BRACE -> ID* ;

NUMBER
    :   ('+' | '-')? (INTEGER | FLOAT)
    ;

STRING
    :  '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
    ;

BOOLEAN
    :   'true' | 'TRUE' | 'false' | 'FALSE'
    ;

ID  :   (LETTER|'_') (LETTER | INTEGER |'_')*
    ;

COMMENT
    :   '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
    |   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
    ;

WHITESPACE  :   (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;} ;

COLON   :   ':' ;
SEMICOLON   :   ';' ;

COMMA   :   ',' ;
PERIOD  :   '.' ;
PLUS    :   '+' ;
EQUALS  :   '=' ;   

OPEN_BRACKET    :   '(' ;
CLOSE_BRACKET   :   ')' ;

OPEN_BRACE  :   '{' ;   
CLOSE_BRACE :   '}' ;

OPEN_BOX    :   '[' ;
CLOSE_BOX   :   ']' ;

fragment
LETTER
    :   'a'..'z' | 'A'..'Z' 
    ;

fragment
INTEGER
    :   '0'..'9'+
    ;

fragment
FLOAT
    :   INTEGER+ '.' INTEGER*
    ;

fragment
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    ;

我正在使用 Antlr 进行开发,它提供了解决此问题的功能 - 但不幸的是它似乎不起作用:s

任何帮助都会很棒。

谢谢。

编辑:

这是我尝试实现/解析的语言示例

<FunctionName> <OptionalAttributes> <OptionalChildFunctions>

例如:

ForEach(in:[1,2,3,4,5] as:"i") {
  Switch(value:{i}) {
    Case(value:3) {
      Print(message:"This is the number 3")
    }

    Default {
       Print(message:"This isn't the number 3")
    }
 }
}

【问题讨论】:

    标签: recursion antlr ll


    【解决方案1】:

    好的,这应该可以解决问题:

    grammar Test;
    
    /************************************** PARSER **************************************/
    program
        :   function EOF 
        ;
    
    function
        :   ID (OPEN_PAREN (attribute (COMMA attribute)*)? CLOSE_PAREN)?
            (OPEN_BRACE function* CLOSE_BRACE)?
            SEMICOLON?
        ;
    
    attribute
        :   ID (COLON | EQUALS)? expression
        ;
    
    expression
        :   atom (PLUS atom)*
        ;
    
    atom
        :   ID
        |   STRING
        |   BOOLEAN
        |   NUMBER
        |   array
        |   lookup
        ;
    
    array
        :   OPEN_BOX (expression (COMMA expression)*)? CLOSE_BOX
        ;
    
    lookup
        :   OPEN_BRACE (ID (PERIOD ID)*) CLOSE_BRACE
        ;
    
    /************************************** LEXER **************************************/
    NUMBER          :   ('+' | '-')? (INTEGER | FLOAT)
                    ;
    
    STRING          :  '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
                    ;
    
    BOOLEAN         :   'true' | 'TRUE' | 'false' | 'FALSE'
                    ;
    
    ID              :   (LETTER|'_') (LETTER | INTEGER |'_')*
                    ;
    
    COMMENT         :   '//' ~('\n'|'\r')* ('\r'? '\n'| EOF) {$channel=HIDDEN;}
                    |   '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
                    ;
    
    WHITESPACE      :   (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;} ;
    
    COLON           :   ':' ;
    SEMICOLON       :   ';' ;
    
    COMMA           :   ',' ;
    PERIOD          :   '.' ;
    PLUS            :   '+' ;
    EQUALS          :   '=' ;   
    
    OPEN_PAREN      :   '(' ;
    CLOSE_PAREN     :   ')' ;
    
    OPEN_BRACE      :   '{' ;   
    CLOSE_BRACE     :   '}' ;
    
    OPEN_BOX        :   '[' ;
    CLOSE_BOX       :   ']' ;
    
    fragment 
    LETTER          :   'a'..'z' | 'A'..'Z' ;
    fragment
    INTEGER         :   '0'..'9'+ ;
    fragment
    FLOAT           :   INTEGER+ '.' INTEGER* ;
    fragment
    ESC_SEQ         :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\') ;
    

    请注意,我已将 OPEN_BRACKETCLOSE_BRACKET 的名称更改为 OPEN_PARENCLOSE_PAREN。圆形的() 是括号,方形的[] 被称为括号(你称为盒子的那些,但称它们为盒子不会伤害IMO)。

    【讨论】:

    • 谢谢巴特。是的,你似乎已经成功了!我应该从这里开始!谢啦!非常感谢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多