我使用BNF Converter玩了一下,并尝试重新设计部分 Mathematica 语言。我的BNF已经有大约150行并且工作正常,直到我注意到一个非常基本的错误。 Mathematica 中的括号[]
用于两种不同的事情
expr[arg]
调用函数list[[spec]]
访问表达式的元素,例如List
假设我想为一种语言创建解析器,该语言只包含标识符,函数调用,元素访问和表达式序列作为参数。这些表格有效
f[]
f[a]
f[a,b,c]
f[[a]]
f[[a,b]]
f[a,f[b]]
f[[a,f[x]]]
BNFC的直接但明显错误的输入文件可能看起来像
entrypoints Expr ;
TSymbol. Expr1 ::= Ident ;
FunctionCall. Expr ::= Expr "[" [Sequence] "]" ;
Part. Expr ::= Expr "[[" [Sequence] "]]" ;
coercions Expr 1 ;
separator Sequence "," ;
SequenceExpr. Sequence ::= Expr ;
此BNF不适用于第一个代码块的最后两个示例。
问题似乎位于创建的Yylex
词法分析器文件中,该文件分别与]
和]]
匹配。这是错误的,因为可以在最后的示例中看到,它是否为结束]
或]]
取决于上下文。因此,您必须创建一堆大括号以确保正确匹配,或者将其留给解析器。
有人可以告诉我是否可以通过BNFC实现这一目标?
(顺便说一句,其他提示也会感激不尽)
答案 0 :(得分:3)
您的问题是令牌“]]”。如果词法分析器没有收集它 任何对过去的记忆,都可能是错的。所以就是不要这样做!
解析器按定义记住它的左上下文,所以你可以得到 它可以正确地进行支架匹配。
我会用这种方式定义你的语法:
FunctionCall. Expr ::= Expr "[" [Sequence] "]" ;
Part. Expr ::= Expr "[" "[" [Sequence] "]" "]" ;
lexer只检测单个“[”“]”作为标记。
奇怪的变种:
FunctionCall. Expr ::= Expr "[" [Sequence] "]" ;
Part. Expr ::= Expr "[[" [Sequence] "]" "]" ;
lexer也检测到“[[”作为代币,因为它不会被误认为。