java - ANTLR 中解析输入时出错

标签 java parsing compiler-construction antlr lexer

所以我在 ANTLR 中编写了以下语法:

grammar PARVA;


prog : lexeme* ;


lexeme :TOK_STRLIT
       | TOK_INTLIT
       | TOK_CHARLIT
       | ID
       | LINE_COMMENT
       | COMMENT
       | TOK_ASSERT
       | TOK_BOOL
       | TOK_BOOLEAN
       | TOK_BREAK
       | TOK_CHAR
       | TOK_CIN
       | TOK_CONST
       | TOK_COUT
       | TOK_DO
       | TOK_ELSE
       | TOK_ENUM
       | TOK_EOF
       | TOK_EOLN
       | TOK_EXIT       
       | TOK_FALSE      
       | TOK_FOR        
       | TOK_GET       
       | TOK_IF        
       | TOK_INLINE   
       | TOK_INT      
       | TOK_MOD      
       | TOK_NEW       
       | TOK_PRINT      
       | TOK_PRINTLN    
       | TOK_RANDOM     
       | TOK_RANDOMSEED 
       | TOK_READ      
       | TOK_RETURN     
       | TOK_STACKDUMP  
       | TOK_TRUE      
       | TOK_VAL       
       | TOK_VOID       
       | TOK_WHILE      
       | TOK_WRITE      
       | TOK_TOUPPER    
       | TOK_TOLOWER   
       | TOK_OP_NOT    
       | TOK_BITOR     
       | TOK_OR       
       | TOK_BITAND   
       | TOK_AND    
       | TOK_OP_REL 
       | TOK_OP_ASSIGN 
       | TOK_OP_ADD 
       | TOK_OP_TIMES
       | TOK_INC
       | TOK_DEC    
       | TOK_COMMA  
       | TOK_COLON  
       | TOK_SEMI   
       | TOK_LSHIFT 
       | TOK_RSHIFT 
       | TOK_LB    
       | TOK_RB   
       | TOK_LC    
       | TOK_RC     
       | TOK_LP   
       | TOK_RP
       | WS
       ;  
Letter     : [a-zA-Z] ;
Digit      : [0-9] ;
Hex_Digit  : [a-fA-F0-9] ;
UNICODE    : 'u' Hex_Digit Hex_Digit Hex_Digit Hex_Digit ;
ESC        : '\\"'
           | '\\\\'
           ;

TOK_STRLIT  : '"' (ESC|.)*? '"' ;
TOK_INTLIT  : [0-9]+ ;
TOK_CHARLIT : '\\'('a' | 'b' | 'f' | 'n' | 'r' | 't' | UNICODE ) | '\'' Letter '\'' | '\'' Digit '\'' ;
ID          : Letter (Letter | Digit | '_' )* ;
WS          : [ \t\r\n]+ -> skip ;



LINE_COMMENT : '//' .*? '\n' -> skip ;
COMMENT      : '/*' .*? '*/' -> skip ;

TOK_ASSERT     : 'assert' ;
TOK_BOOL       : 'bool' ;
TOK_BOOLEAN    : 'boolean' ;
TOK_BREAK      : 'break' ; 
TOK_CHAR       : 'char' ;
TOK_CIN        : 'cin' ;
TOK_CONST      : 'const' ;
TOK_COUT       : 'cout' ;
TOK_DO         : 'do' ;
TOK_ELSE       : 'else' ;
TOK_ENUM       : 'enum' ;
TOK_EOF        : 'eof' ;
TOK_EOLN       : 'eoln' ;
TOK_EXIT       : 'exit' ;
TOK_FALSE      : 'false' ;
TOK_FOR        : 'for' ;
TOK_GET        : 'get' ;
TOK_IF         : 'if' ;
TOK_INLINE     : 'inline' ;
TOK_INT        : 'int' ;
TOK_MOD        : 'mod' ;
TOK_NEW        : 'new' ;
TOK_PRINT      : 'print' ;
TOK_PRINTLN    : 'println' ;
TOK_RANDOM     : 'random' ;
TOK_RANDOMSEED : 'randomseed' ;
TOK_READ       : 'read' ;
TOK_RETURN     : 'return' ;
TOK_STACKDUMP  : 'stackdump' ;
TOK_TRUE       : 'true' ;
TOK_VAL        : 'val' ;
TOK_VOID       : 'void' ;
TOK_WHILE      : 'while' ;
TOK_WRITE      : 'write' ;
TOK_TOUPPER    : 'toUpperCase' ;
TOK_TOLOWER    : 'toLowerCase' ;



TOK_OP_NOT    : '!' ;
TOK_BITOR     : '|' ;
TOK_OR        : '||' ;
TOK_BITAND    : '&' ;
TOK_AND       : '&&' ;
TOK_OP_REL    : '==' 
              | '!='
              | '<'
              | '<='
              | '>'
              | '>=' 
              ;
TOK_OP_ASSIGN : '='
              | '%='
              | '&='
              | '|='
              | '*='
              | '+='
              | '-='
              | '/='
              ;
TOK_OP_ADD    : '+'
              | '-'
              ;
TOK_OP_TIMES  : '*'
              | '/'
              | '%'
              ;
TOK_INC       : '--' ;
TOK_DEC       : '++' ;


TOK_COMMA  : ',' ;
TOK_COLON  : ':' ;
TOK_SEMI   : ';' ;
TOK_LSHIFT : '<<' ;
TOK_RSHIFT : '>>' ;
TOK_LB     : '[' ;
TOK_RB     : ']' ;
TOK_LC     : '{' ;
TOK_RC     : '}' ;
TOK_LP     : '(' ;
TOK_RP     : ')' ;

但是当我提供以下内容作为输入时:

int main(){
   int a;
}

我收到以下错误:

extraneous input 'a' expecting {<EOF>, TOK_STRLIT, TOK_INTLIT, TOK_CHARLIT, ID, WS, LINE_COMMENT, COMMENT, 'assert', 'bool', 'boolean', 'break', 'char',  'cin', 'const', 'cout', 'do', 'else', 'enum', 'eof', 'eoln', 'exit', 'false',  'for', 'get', 'if', 'inline', 'int', 'mod', 'new', 'print', 'println', 'random', 'randomseed', 'read', 'return', 'stackdump', 'true', 'val', 'void', 'while', 'write', 'toUpperCase', 'toLowerCase', '!', '|', '||', '&', '&&', TOK_OP_REL, TOK_OP_ASSIGN, TOK_OP_ADD, TOK_OP_TIMES, '--', '++', ',', ':', ';', '<<', '>>', '[', ']', '{', '}', '(', ')'}

这真的很令人沮丧,我已经尝试了几个小时,但找不到我做错了什么,而且我对 ANTLR 很陌生,可能是什么问题?

最佳答案

正如评论中提到的(以及指定的重复问题),问题是 a 匹配 Letter,而您希望它匹配 ID >。原则上,发生这种情况是因为 Letter 的定义在语法中早于 ID 的定义。因此您可以通过重新排列定义来修复它。

您还需要移动 Hex_Digit 的定义。然后您会发现 UNICODE 匹配一些名称以 u 开头的标识符。

但我认为您永远想要一个 token 来匹配LetterDigitHex_Digit UNICODEESC。这些仅旨在作为出现在其他词汇规则中的命名片段,而不是其本身的标记。 (就我个人而言,我不太喜欢这种风格,尤其是像这些简单的片段,但每个人都有自己的风格。)在这种情况下,您应该将它们显式声明为 fragment ,以便它们不会作为 token 进行匹配:

fragment Letter     : [a-zA-Z] ;
fragment Digit      : [0-9] ;
fragment Hex_Digit  : [a-fA-F0-9] ;
...

然后将它们放在语法中的哪个位置并不重要。

参见https://theantlrguy.atlassian.net/wiki/display/ANTLR4/Lexer+Rules

关于java - ANTLR 中解析输入时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28634928/

相关文章:

java - 用于从 Java 生成 Word 文档的 xsl 样式表

json - 是否有任何预构建的方法可以从 VB6 解析 JSON?

java - 将Java编译成PHP?

c - 为什么结构的大小不等于其各个成员类型的大小之和?

java - SOAP UI HTTP 请求与 Apache CXF

java - 使用不同的构建文件启动 java Eclipse headless 构建

java - 如何编写一个不使用 do 循环来返回整数中存在多少个数字 2 的方法

java - 如何通过命令行参数覆盖属性文件值?

c# - 您将如何处理这个简单的字符串解析问题?

optimization - 如何关闭 gcc 中的特定优化标志