我正在使用parser中的玩具golang来学习语言。我添加了一个包含以下案例的语法测试用例:
Valid:
a, ab, aba, ababababababa, ababababab
b, ba, bab, babababababab, bababababa
Invalid:
abb, baa
a
后面跟着b
,反之亦然。
现在我的解析器中的语法看起来像那样(为了简洁,我省略了周围的代码):
"expr": Or(Ref("A"), Ref("B")),
"A": And(
a,
Optional(
And(
b,
Optional(Ref("A"))))),
"B": And(
b,
Optional(Ref("A")))
其中
a - exact match for "a" character
b - exact match for "b" character
"A", "B", "expr" - names of the parts of the grammar that can be referred
later with Ref("A")
And - consume sequence of expressions
Or - consume any of the expressions
Ref - refer to other expression (allows recursion)
Optional - make the expression non-obligatory
我想这不是描述这种语法最简洁的方法。如何使它更紧凑?
相关:
编辑:
BNF answer from Filip可以用我的语法编写:
"expr": Or(Ref("A"), Ref("B")),
"A": Or(And(a, Ref("B")), a),
"B": Or(And(b, Ref("A")), b)
答案 0 :(得分:3)
你拥有的BNF语法是:
expr ::= A | B
A ::= "a" B | "a"
B ::= "b" A | "b"
我认为使用您的语法转换为此:
"expr": Or(Ref("A"), Ref("B")),
"A": And(
a,
Optional(Ref("B"))),
"B": And(
b,
Optional(Ref("A")))
请注意,在非终端("a"
)之前检查终端("b"
,Ref(x)
)非常重要,否则您将获得无限循环。它总是试图查看它是否可以匹配另一个A
或B
到字符串的末尾,然后是另一个,另一个,导致永无止境的递归。