解决模糊输入:输入不匹配

时间:2014-10-04 21:16:17

标签: antlr4

我有这个语法:

grammar MkSh;

script
  : (statement
    | targetRule
    )*
  ;

statement
  :  assignment
  ;

assignment
  :  ID '=' STRING
  ;

targetRule
  : TARGET ':' TARGET*
  ;

ID
  :  ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
  ;

WS
  : ( ' '
    | '\t'
    | '\r'
    | '\n'
    ) -> channel(HIDDEN)
  ;

STRING
  : '\"' CHR* '\"'
  ;

fragment
CHR
  : ('a'..'z'|'A'..'Z'|' ')
  ;

TARGET
  :  ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'-'|'/'|'.')+
  ;

和此输入文件:

hello="world"

target: CLASSES

运行我的解析器时,我收到此错误:

line 3:6 mismatched input ':' expecting '='
line 3:15 mismatched input ';' expecting '='

这是因为解析器正在采取" target"作为ID而不是TARGET。我希望解析器根据分隔符选择规则(':' vs' =')。

我怎样才能实现这一目标?

(这是我的第一个Antlr项目,所以我对任何事情都开放。)

2 个答案:

答案 0 :(得分:1)

首先,你需要知道 target 这个词被匹配为 ID 令牌,而不是 TARGET 令牌,因为你已经在 TARGET 之前编写了规则 ID ,它将始终被词法分析器识别为 ID 。请注意, target 这个词完全符合 ID TARGET 词法分析器规则,(我假设您正在编写一个laguage) ,意味着作为关键字的目标也可以用作id。在书中 - “最终的ANTLR参考”中有一个副标题“将关键字作为标识符处理”,可以直接处理这些问题。我建议你看一下。或者如果您更喜欢快速回答,解决方案是使用词法分析器模式。将语法分解为解析器和词法分析器语法也会更好。

答案 1 :(得分:1)

正如@cantSleepNow所暗示的那样,你已经定义了一个令牌(TARGET),它是另一个令牌(ID)的词汇超集,然后告诉词法分析器只将字符串标记为TARGET,如果不能被标记为ID。由于ANTLR lexing规则看起来像ANTLR解析规则,所有这些都变得更加模糊,尽管它们实际上是完全不同的野兽。

(警告:在没有测试的情况下写下我的头顶: - )

您的真实项目可能更复杂,但在您发布的可能简化示例中,您可以推迟将两者区分为解析阶段,而不是在词法分析器中区分它们:

id : TARGET
    { complain if not legal identifier (e.g., contains slashes, etc.) }
    ;
assignment
  :  id '=' STRING
  ;

似乎可以解决lexing问题,并允许您提供比#34;语法错误"更智能的错误消息。当用户获取ID错误的语法时。语法仍然含糊不清,但也许ANTLR轮盘会在模糊的情况下做出你喜欢的选择。当然,明确的语法往往会使人类发现更具可读性的语言,现在你可以看到为什么经典makefile语法需要在赋值或目标规则之后的换行符。