2014-07-21 65 views
0

以下是该文件的节选我试图解析:ANTLR4解析器规则冲突

section typeSymbols: 

agent, message, fact, nat, protocol_id, set 

section signature: 

//Super Type Declarations 
message > agent   
message > nat 
message > protocol_id 
... 

//Function Declarations 
pair  : message * message -> message 
crypt : message * message -> message 
inv  : message -> message 
... 

//Predicate Declarations 
iknows : message -> fact 
contains : message * set -> fact 
witness : agent * agent * protocol_id * message -> fact 
... 

和文件的剩余部分解析得很好,只有具有前两节麻烦。所以应该处理这些规则是:

//Start rule, left out the other sections because they work 
program : typesymbolssection signaturesection; 

//The rules below are for handling the Type Symbols section 
typesymbolssection : 'section typeSymbols:' typelist; 

typelist : type (',' type)*; 

type : if_type | if_operator '(' typelist ')' | '{' constantnatlist '}'; 
//only the first alternative should matter here. 
//the rest are only used elsewhere 

if_type : Const_ident; 

Const_ident : [a-z][A-Za-z0-9_]*; 

//The rules below are for handling the Signature Section 
signaturesection : 'section signature:' signaturesection0; 

signaturesection0 : supertypedeclaration* functiondeclaration* predicatedeclaration*; 

supertypedeclaration : if_type '>' if_type; 

functiondeclaration : if_operator ':' typestar '->' type; 

predicatedeclaration : if_operator ':' typestar '->' 'fact'; 

typestar : type | type '*' typestar; 

该语法设法解析大部分正确的文件,除了一个小错误。它给出了错误:“在输入'事实上没有可行的替代方案'”。这是指“类型符号”部分中的第一个事实。它产生如下解析树:

typesymbolssection 
    | 
    |----> "section typeSymbols:" 
    | 
    |----> typelist 
      | 
      |---> type ---> if_type ---> agent 
      |---> type ---> if_type ---> message 
      |---> type ---> fact //Highlighted in red because of parsing error 
      |---> type ---> if_type ---> nat 
      |---> type ---> if_type ---> protocol_id 
      |---> type ---> if_type ---> set 

虽然我知道要修正这个错误,使其正确解析方法之一,此修复程序引入了更大的错误。如果我改变

来自:

predicatedeclaration : if_operator ':' typestar '->' 'fact'; 

到:

predicatedeclaration : if_operator ':' typestar '->' type; 

然后运行没有抛出任何错误,但它并不能正确描述我在做什么,因为那么所有的谓词声明作为函数声明来读取,它错误地认为没有谓词定义(因为此时函数和谓词的定义将是相同的)。是什么使它成为谓词而不是函数是事实。但是,如果我通过在引号中指定它应该转到'fact'来澄清,那么它会在typeSymbols部分中跳转。这对我来说没有意义,因为它们甚至没有关系。它发现它在类型规则中放弃了“事实”输入,而不是像其他的那样将其传递给Const_ident。

我的问题是为什么这有所作为,我该如何纠正这一点,以便我可以避免这两个错误?我不明白为什么从“类型”转换为“'事实'”应该在第一部分中有所作为。到目前为止,我陷入了我有一个错误或另一个错误的地方,而且我已经连续三天对此感到不安。任何帮助大规模赞赏...

回答

1

你有秩序(因此优先)的规则问题。 可匹配的第一个词法分析规则将匹配。

Const_ident : [a-z][A-Za-z0-9_]*; // will match the token 'fact'! 

//... 

predicatedeclaration : if_operator ':' typestar '->' 'fact'; // implicitly creates the token 'fact', which will NEVER match since it's always matched by Const_ident rule! 

尝试是这样的:

predicatedeclaration : if_operator ':' typestar '->' Fact ; 


Fact : 'fact'; // now 'fact' will be a Fact not a Const_ident 
Const_ident : [a-z][A-Za-z0-9_]*; 

检查也为你的语法类似的其他情况。

建议:

  • 把所有词法规则在一个地方,所以你会清楚地看到的优先级。把最专业的,首先,他们会赢得更一般的规则。
  • 不要使用隐式标记(即,解析器规则中的“某事”)
  • 最好甚至将解析器和词法分析器语法分隔为两个文件。这不允许创建隐式令牌。

编辑:

如果fact有时须为Fact,有时,Const_ident“,你可以用下面的办法:

// use parser rules for `Const_ident` now. I.e. in all parser rules only use the parser rule, not the token directly. 
const_ident : Const_ident | Fact; // will match `Const_ident`s and `fact`s 


Fact : 'fact'; 
Const_ident : [a-z][A-Za-z0-9_]*; // don't use this directly in parser rules but `const_ident` instead! 
+0

不幸的是这并没有解决这个问题对我来说。我已经尝试了多个订单中的规则,但仍遇到问题。另外,我相信我在ANTLR4的参考书中读到,词法分析器将会进行第一个最长的生产(意味着它会选择消耗最多的字符,并且,如果配合,将会选择第一个)。问题在于字符串事实在输入中出现两次,我希望每次都以不同的方式对待它。 – user3380049

+0

但是,“事实”总是可以与“Const_ident”相匹配,因此,如果它首先出现,将总是按此规则进行匹配。 – Onur

+0

对不起,我不知道该说什么。我试过了,但没有解决问题。问题是,第一次“事实”出现在输入中,它需要是一个Const_ident,每次都需要成为事实。现在,我的最佳解决方案是通过在输入文件中添加内容来预处理问题,以使函数和谓词以不同方式形成... – user3380049