ANTLR4解析器规则冲突

时间:2014-07-21 22:07:57

标签: parsing compiler-construction 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; 

除了一个小错误之外,这个语法设法正确地解析文件。它给出了错误:"在输入''"没有可行的替代方案。这是指Type Symbols部分中的第一个事实。它产生以下解析树:

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;

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

我的问题是为什么这会产生影响,我该如何纠正这一点,以便我可以避免这两个错误?我不明白为什么要改变"输入"到" '事实上' "应该在第一部分有所作为。到目前为止,我已经陷入了一个错误或另一个错误的地方,而且我已经对这个问题持续了三天。任何帮助都非常赞赏...

1 个答案:

答案 0 :(得分: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_]*;

还要检查语法中的其他类似情况。

建议:

  • 将所有词法规则放在一个位置,这样您就可以清楚地看到优先级。把最专业的放在第一位,这样他们才能赢得#34;更一般的规则。
  • 不要使用隐式令牌(即'解析器规则中的内容)
  • 最好将解析器和词法分析器语法分成两个文件。这不允许创建隐式令牌。

编辑:

如果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!