代码之家  ›  专栏  ›  技术社区  ›  TheWhiteJoker

Antlr-为什么它期望FunctionCall而PrintCommand给出

  •  1
  • TheWhiteJoker  · 技术社区  · 6 年前

    我的Antlr语法需要一个FunctionCall,但在我为Antlr构建的编译器编写的示例代码中,我编写了一个print命令。有人知道为什么以及如何解决这个问题吗?打印命令的名称为: RetroBox.show(); 打印命令应从以下位置识别 blockstatements块语句 blockstatement语句 陈述 localFunctionCall printCommand(打印命令)

    这里是我的中心语法:

    grammar Mars;
    // ******************************LEXER 
    BEGIN*****************************************
    
    // Keywords
    FUNC:                           'func';
    ENTRY:                          'entry';
    VARI:                           'vari';
    VARF:                           'varf';
    VARC:                           'varc';
    VARS:                           'vars';
    LET:                            'let';
    INCREMENTS:                     'increments';
    RETROBOX:                       'retrobox';
    SHOW:                           'show';
    
    // Literals
    
    DECIMAL_LITERAL:    ('0' | [1-9] (Digits? | '_'+ Digits)) [lL]?;
    
    FLOAT_LITERAL:      (Digits '.' Digits? | '.' Digits) ExponentPart? [fFdD]?
             |       Digits (ExponentPart [fFdD]? | [fFdD])
             ;
    
    CHAR_LITERAL:       '\'' (~['\\\r\n] | EscapeSequence) '\'';
    
    STRING_LITERAL:     '"' (~["\\\r\n] | EscapeSequence)* '"';
    
    // Seperators
    
    ORBRACKET:                          '(';
    CRBRACKET:                          ')';
    OEBRACKET:                          '{';
    CEBRACKET:                          '}';
    SEMI:                               ';';
    POINT:                              '.';
    
    // Operators
    
    ASSIGN:             '=';
    
    // Whitespace and comments
    
    WS:                 [ \t\r\n\u000C]+ -> channel(HIDDEN);
    COMMENT:            '/*' .*? '*/'    -> channel(HIDDEN);
    LINE_COMMENT:       '//' ~[\r\n]*    -> channel(HIDDEN);
    
    // Identifiers
    
    IDENTIFIER:         Letter LetterOrDigit*;
    
    // Fragment rules
    
    fragment ExponentPart
        : [eE] [+-]? Digits
        ;  
    
    fragment EscapeSequence
        : '\\' [btnfr"'\\]
        | '\\' ([0-3]? [0-7])? [0-7]
        | '\\' 'u'+ HexDigit HexDigit HexDigit HexDigit
        ;
    
    fragment HexDigits
        : HexDigit ((HexDigit | '_')* HexDigit)?
        ;
    
    fragment HexDigit
        : [0-9a-fA-F]
        ;
    
    fragment Digits
        : [0-9] ([0-9_]* [0-9])?
        ;
    
    fragment LetterOrDigit
        : Letter
        | [0-9]
        ;
    
    fragment Letter
        : [a-zA-Z$_] // these are the "java letters" below 0x7F
        | ~[\u0000-\u007F\uD800-\uDBFF] // covers all characters above 0x7F                 which are not a surrogate
        | [\uD800-\uDBFF] [\uDC00-\uDFFF] // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
        ;
    
    // *******************************LEXER     END****************************************
    
    // *****************************PARSER BEGIN*****************************************
    
    program
        : mainfunction  #Programm
        | /*EMPTY*/              #Garnichts
        ;
    
    mainfunction
        : FUNC VARI ENTRY ORBRACKET CRBRACKET block  #NormaleHauptmethode
        ;
    
    block
        : '{' blockStatement '}'   #CodeBlock
        | /*EMPTY*/                #EmptyCodeBlock
        ;
    
    blockStatement
        : statement* #Befehl
        ;
    
    statement
        : localVariableDeclaration
        | localVariableInitialization
        | localFunctionImplementation
        | localFunctionCall
        ;
    
    expression
        : left=expression op='%'
        | left=expression op=('*' | '/') right=expression
        | left=expression op=('+' | '-') right=expression
        | neg='-' right=expression
        | number
        | IDENTIFIER
        | '(' expression ')'
        ;
    
    number
        : DECIMAL_LITERAL
        | FLOAT_LITERAL
        ;
    
    localFunctionImplementation
        : FUNC primitiveType IDENTIFIER ORBRACKET CRBRACKET block #Methodenimplementierung
        ;
    
    localFunctionCall
        : IDENTIFIER ORBRACKET CRBRACKET SEMI #Methodenaufruf
        | printCommand #RetroBoxShowCommand
        ;
    
    printCommand
        : RETROBOX POINT SHOW ORBRACKET params=primitiveLiteral CRBRACKET SEMI     #PrintCommandWP
        ;
    
    localVariableDeclaration
        : varTypeDek=primitiveType IDENTIFIER SEMI #Variablendeklaration
        ;
    
    localVariableInitialization
        : varTypeIni=primitiveType IDENTIFIER ASSIGN varValue=primitiveLiteral     SEMI #VariableninitKonst
        | varTypeIni=primitiveType IDENTIFIER ASSIGN varValue=expression SEMI #VariableninitExpr
        ;
    
    primitiveLiteral
        : DECIMAL_LITERAL
        | FLOAT_LITERAL
        | STRING_LITERAL
        | CHAR_LITERAL
        ;
    
    primitiveType
        : VARI
        | VARC
        | VARF
        | VARS
        ;
    
    // ******************************PARSER END****************************************
    

    下面是我的示例代码:

    func vari entry()
    {
        RetroBox.show("Hallo"); //Should be recognised as print-command
    }
    

    这里是Antlr打印的AST:

    AST from Compiler

    1 回复  |  直到 6 年前
        1
  •  1
  •   Simon Jenkins    6 年前

    问题是您的RETROBOX关键字是“RETROBOX”,但您的示例代码将其键入为“RETROBOX”。Antlr将“RetroBox”解析为标识符,因此如下“.”是意外的。

    Antlr应发出错误:“第3:12行输入不匹配。”“应为”“(”“”)。

    然后尝试恢复并继续解析。它尝试删除单个标记(只忽略“.”),并发现这是可行的。。。除了它现在匹配的规则是#Methodenaufruf而不是#RetroBoxShowCommand。