antlr - 指定 "appearing in any order but only at most once"的语法规则

标签 antlr context-free-grammar

假设我有三个符号 A、B、C。

在 ANTLR 中,我如何指定在一个句子中,A、B 和 C 最多可以出现一次,并且它们可以以任何顺序出现。 (例如,ABC、BCA 都是合法的)

我试过

(A | B | C)*

知道它只会处理“任何顺序”部分,但想不出一种方法说它最多只能出现一次。

编辑:我试过使用 bool 标志,它有效但看起来太麻烦了 - 必须有一个更简单的方法,是吗?

myrule;
   {
       boolean aSeen = false;
       boolean bSeen = false;
       boolean cSeen = false;
   }
   :

   (   A { if (aSeen) throw RuntimeException("alraedy seen") else aSeen = true; }
   |   B { if (bSeen) throw RuntimeException("alraedy seen") else bSeen = true; }
   |   C { if (cSeen) throw RuntimeException("alraedy seen") else cSeen = true; }
   )*
   ;

最佳答案

既然你提到可能有很多很多排列,我会选择保持语法简单,并在访问者或听众中处理这个问题,例如:

public class ValuesListener : ValuesBaseListener
{
    bool isASeen = false;  // "seen flag here"  

    public override void ExitA(ValuesParser.AContext context)
    {
        if (isASeen) // already parsed this once
            <throw exception to stop and inform user>
        else // first time parsing this, so process and set flag so it won't happen again
        {
            isASeen = true;  // never gets reset during this tree walk
            <perform normal processing here>
        }
    }
}

那么你的语法可以是这样的
myrule: someothertoken myRuleOptions* ;

myRuleOptions
:    A
|    B
|    C
| ...etc. 

我的原因?有一些方法可以使用上面建议的谓词来做到这一点,但是对于在 ANTLR4 中没有经验但在目标语言方面非常有经验的工程师的可读性和可维护性,我会考虑这种方法。在我的环境中,我经常将 ANTLR 项目交给那些只是遵循我建立的模式但并不真正了解 ANTLR 的工程师。这对他们来说更容易遵循。

关于antlr - 指定 "appearing in any order but only at most once"的语法规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45221716/

相关文章:

compiler-construction - 除了 ANTLR,还有哪些工具可以帮助我创建针对 JVM 的小型语言?

antlr - 语义谓词失败但不转到下一个

computer-science - 非正规语言与正规语言的串联总是不正规吗?

python - 上下文无关文法区分整数和浮点常量

c# - 如何为单独的 ANTLR 词法分析器和解析器添加虚构标记?

java - antlr4 中允许空格

code-generation - 从 Antlr 语法生成语法正确的句子

python - NLTK ViterbiParser 无法解析不在 PCFG 规则中的单词

Python 上下文无关语法和 PCFG 生成基准?