ANTLR 语法错误取决于定义规则的位置

ANTLR syntax error depending on where a rule is defined

我是解析和 ANTLR 的新手,如果这是一个愚蠢的问题,请提前致歉。我正在尝试使用 ANTLR 来解析逻辑公式(涉及 AND、OR、NOT)。我有以下语法

grammar LTL;

ltl: ltl_or | ltl_and | ltl_not | Atom;

ltl_and: OPEN_CURLY ltl CLOSE_CURLY And OPEN_CURLY ltl CLOSE_CURLY;
ltl_or: OPEN_CURLY ltl CLOSE_CURLY Or OPEN_CURLY ltl CLOSE_CURLY;
ltl_not: Not OPEN_CURLY ltl CLOSE_CURLY;

Or: 'Or' | 'or';
Atom: (~('{' | '}'))+;
And: 'And' | 'and';
Not: 'Not' | 'not';
OPEN_CURLY: '{';
CLOSE_CURLY: '}';

我的测试用例是 {ABCD()}Or{AB CD()},我希望它应该被解析为具有两个原子的有效 Or 公式。上面的语法确实会发生这种情况。但是,如果我交换 Or 规则和 Atom 规则的位置,如下所示:

Atom: (~('{' | '}'))+;
Or: 'Or' | 'or';

我收到错误

line 1:8 no viable alternative at input '{ABCD()}Or'

有人可以指点一下吗?

这是您的语法的重构版本,可以正确处理您提供的输入,并利用其他 ANTLR 习语(希望)使其更易于阅读和维护。 (附有说明进行了哪些更改的注释。)

grammar LTL
    ;

// *almost* always a good idea to have a start rule that 
// consumes everything up to EOF to prevent
// premature termination of parsing input
ltl_start: ltl EOF;

// *IF* you really want to allow a "naked" ATOM 

// ltl_start: (ltl | ATOM) EOF;

// since it seems ltls are always wrapped in curlies, 
// I've refactored them a bit to simplify also
// used labelled alternatives that are generally easier to read 
// Note, you can use literals in your rules that match token rules 
// and ANTLR will match them up I find this frequently makes the
// grammar easier to read.
ltl
    : ltl OR ltl   # ltl_or
    | ltl AND ltl  # ltl_and
    | NOT ltl      # ltl_not
    | '{' ATOM '}' # ltl_atom
    ;

// Symbols
OPEN_CURLY:  '{';
CLOSE_CURLY: '}';

// keywords
OR:  'Or' | 'or';
AND: 'And' | 'and';
NOT: 'Not' | 'not';

// place ATOM *after* keywords to prevent keywords being misidentified as ATOMs
ATOM: ~[{}]+; // Another way of saying "Atom: (~('{' | '}'))+;"

虽然不是真的有必要,但我更喜欢用大写字母命名 Lexer 规则,这样才能真正从解析器规则中脱颖而出(个人品味)

对于 Lexer 规则,有多个 可以 匹配特定字符序列(即歧义)的词法分析器规则是很常见的。完全避免这些将是非常痛苦的,因此 ANTLR 允许它们并使用以下两个规则解决歧义:

  • 如果有多个 Lexer 规则匹配输入,则使用匹配最长字符序列的规则。
  • 如果多个规则匹配相同长度的字符序列,则使用语法中最先出现的 Lexer 规则。