java – Antlr无关输入

前端之家收集整理的这篇文章主要介绍了java – Antlr无关输入前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个语法文件BoardFile.g4(只有相关部分):
  1. grammar Board;
  2.  
  3. //Tokens
  4. GADGET : 'squareBumper' | 'circleBumper' | 'triangleBumper' | 'leftFlipper' | 'rightFlipper' | 'absorber' | 'portal' ;
  5. NAME : [A-Za-z_][A-Za-z_0-9]* ;
  6. INT : [0-9]+ ;
  7. FLOAT : '-'?[0-9]+('.'[0-9]+)? ;
  8. COMMENT : '#' ~( '\r' | '\n' )*;
  9. WHITESPACE : [ \t\r\n]+ -> skip ;
  10. KEY : [a-z] | [0-9] | 'shift' | 'ctrl' | 'alt' | 'Meta' | 'space' | 'left' | 'right' | 'up' | 'down' | 'minus' | 'equals' | 'backspace' | 'openbracket' | 'closebracket' | 'backslash' | 'semicolon' | 'quote' | 'enter' | 'comma' | 'period' | 'slash' ;
  11. KEYPRESS : 'keyup' | 'keydown' ;
  12.  
  13. //Rules
  14. file : define+ EOF ;
  15. define : board | ball | gadget | fire | COMMENT | key ;
  16. board : 'board' 'name' '=' name ('gravity' '=' gravity)? ('friction1' '=' friction1)? ('friction2' '=' friction2)? ;
  17. ball : 'ball' 'name' '=' name 'x' '=' xfloat 'y' '=' yfloat 'xVelocity' '=' xvel 'yVelocity' '=' yvel ;
  18. gadget : gadgettype 'name' '=' name 'x' '=' xint 'y' '=' yint ('width' '=' width 'height' '=' height)? ('orientation' '=' orientation)? ('otherBoard' '=' name 'otherPortal' '=' name)? ;
  19. fire : 'fire' 'trigger' '=' trigger 'action' '=' action ;
  20. key : keytype 'key' '=' KEY 'action' '=' name ;
  21.  
  22. name : NAME ;
  23. gadgettype : GADGET ;
  24. keytype : KEYPRESS ;
  25. gravity : FLOAT ;
  26. friction1 : FLOAT ;
  27. friction2 : FLOAT ;
  28. trigger : NAME ;
  29. action : NAME ;
  30. yfloat : FLOAT ;
  31. xfloat : FLOAT ;
  32. yint : INT ;
  33. xint : INT ;
  34. xvel : FLOAT ;
  35. yvel : FLOAT ;
  36. orientation : INT ;
  37. width : INT ;
  38. height : INT ;

这会生成词法分析器和解析器.但是,当我对以下文件使用它时,它会给出以下错误

  1. line 12:0 extraneous input 'keyup' expecting {<EOF>,KEYPRESS}

文件到解析:

board name = keysBoard gravity = 5.0 friction1 = 0.0 friction2 = 0.0

  1. # define a ball
  2. ball name=Ball x=0.5 y=0.5 xVelocity=2.5 yVelocity=2.5
  3.  
  4. # add some flippers
  5. leftFlipper name=FlipL1 x=16 y=2 orientation=0
  6. leftFlipper name=FlipL2 x=16 y=9 orientation=0
  7.  
  8. # add keys. lots of keys.
  9. keyup key=space action=apple
  10. keydown key=a action=ball
  11. keyup key=backslash action=cat
  12. keydown key=period action=dog

我在SO中经历了有关此错误的其他问题,但没有人帮助我.我无法弄清楚出了什么问题.为什么我收到此错误

解决方法

字符串“keyup”被标记为NAME标记:这就是问题所在.

您必须意识到词法分析器独立于解析器运行.如果解析器尝试匹配KEYPRESS令牌,则词法分析器不会“监听”它,而只是按照规则构造一个令牌:

>匹配消耗最多字符的规则
>如果有更多规则匹配相同数量的字符,请选择首先定义的规则

考虑这些规则,以及规则的顺序:

  1. NAME : [A-Za-z_][A-Za-z_0-9]* ;
  2.  
  3. INT : [0-9]+ ;
  4.  
  5. KEY : [a-z] | [0-9] | 'shift' | 'ctrl' | 'alt' | 'Meta' | 'space' | 'left' | 'right' | 'up' | 'down' | 'minus' | 'equals' | 'backspace' | 'openbracket' | 'closebracket' | 'backslash' | 'semicolon' | 'quote' | 'enter' | 'comma' | 'period' | 'slash' ;
  6.  
  7. KEYPRESS : 'keyup' | 'keydown' ;

将在大多数KEY备选项之前创建NAME令牌,并且将创建所有KEYPRESS备选项.

并且由于INT匹配一个或多个数字并且在KEY之前定义并且还具有单个数字替代,因此很明显词法分析器将永远不会产生KEY或KEYPRESS令牌.

如果您将NAME和INT规则移动到KEY和KEYPRESS规则下面,那么大多数令牌将按照您的预期构建,这是我的猜测.

编辑

可能的解决方案如下:

  1. KEY : [a-z] | 'shift' | 'ctrl' | 'alt' | 'Meta' | 'space' | 'left' | 'right' | 'up' | 'down' | 'minus' | 'equals' | 'backspace' | 'openbracket' | 'closebracket' | 'backslash' | 'semicolon' | 'quote' | 'enter' | 'comma' | 'period' | 'slash' ;
  2.  
  3. KEYPRESS : 'keyup' | 'keydown' ;
  4.  
  5. NAME : [A-Za-z_][A-Za-z_0-9]* ;
  6.  
  7. SINGLE_DIGIT : [0-9] ;
  8.  
  9. INT : [0-9]+ ;

即我从KEY中删除了[0-9]替代,并引入了一个SINGLE_DIGIT规则(放在INT规则之前!).

现在创建一些额外的解析器规则:

  1. integer : INT | SINGLE_DIGIT ;
  2.  
  3. key : KEY | SINGLE_DIGIT ;

并将解析器规则中所有出现的INT更改为整数(不要调用您的规则int:它是保留字)并将所有KEY更改为key.

而且你可能也想做类似于NAME和KEY中的[a-z]替代方法(即单个小写字符现在永远不会被标记为NAME,总是作为KEY).

猜你在找的Java相关文章