2014-10-04 35 views
1

我有这样的语法:解决暧昧输入:输入不匹配

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所以我开到任何东西。)

+1

我想尽管Antlr的语法看起来好像有一大套规则,词法分析仍然是一个独立的任务。因此,了解冒号和等号的解析规则基本上没有关于lexing规则的知识,这些规则决定字符串“target”应该被标记为ID还是TARGET。许多解决方案之一是定义一个包含TARGET和ID的宽​​松标记,然后检查您的操作标记是否包含上下文的任何非法字符。这也允许更好的错误消息(在分配ID中允许“不允许”)。 – 2014-10-05 07:49:40

+0

@RonBurk你能否详细说明我将如何创建这样的设置?或者指出我在哪里可以找到一个例子?无论如何感谢您的有用评论! – 2014-10-08 18:30:59

回答

1

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

1

至于@cantSleepNow暗示,已定义的令牌(TARGET)是另一个令牌(ID)的词汇超集,然后告诉词法分析器只记号化字符串作为目标,如果它不能被标记化作为ID。由于ANTLR lexing规则看起来像ANTLR解析规则,所有这些都变得更加晦涩难懂,尽管它们是非常不同的野兽。

(警告:注销我的头顶未经测试:-)

真实的项目可能会更加复杂,但在您发布的可能简单的例子,你可以推迟区分两解析阶段,而不是在词法分析器区分他们:

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

好像会解决词法问题,并允许你当用户将获取ID错误的语法给出比“语法错误”更智能的错误消息。语法仍然不明确,但也许ANTLR轮盘会在模棱两可的情况下做出你喜欢的选择。当然,明确的语法倾向于使人们发现更具可读性的语言,现在您可以了解为什么典型的makefile语法要求在分配或目标规则之后换行。

+0

感谢您的Makefile参考。我的项目非常接近制作克隆:) – 2014-10-13 19:41:49