BNFC解析器和类似Mathematica的括号语法

4
我用BNF Converter稍微玩了一下,并尝试重新设计Mathematica语言的部分。我的BNF已经有大约150行,工作正常,直到我注意到一个非常基本的错误。在Mathematica中,方括号[]用于两个不同的事情:
  1. expr[arg] 用于调用函数
  2. 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实现这一点吗?(顺便说一句,其他提示也将不胜感激)

1
@HighPerformanceMark 我这里不是在谈论前端,而是在谈论内核,显然它能够正确解析 f[g[x]]。如果我想使用BNFC创建(至少)一个不完整的Mathematica解析器,我必须找到一个解决方案;无论Wolfram是否存在设计问题。 - halirutan
1个回答

3

你的问题在于标记“]]”。如果词法分析器没有记忆它之前的内容,可能会出现错误。所以不要这样做!

根据定义,解析器会记住它的左侧上下文,因此您可以让它正确地匹配括号。

我会这样定义您的语法:

FunctionCall.   Expr ::= Expr "[" [Sequence] "]" ;
Part.           Expr ::= Expr "[" "[" [Sequence] "]" "]" ;   

通过词法分析器,只检测单个的 "[" "]" 作为标记。

一种奇怪的变体:

FunctionCall.   Expr ::= Expr "[" [Sequence] "]" ;
Part.           Expr ::= Expr "[[" [Sequence] "]" "]" ; 

词法分析器还会将 "[[" 识别为一个标记,因为它不会被误解。


真正愚蠢的事情是,我已经有了这个解决方案,但显然在尝试时没有重新加载类 :-( 好的,这个可行。谢谢。 - halirutan
另外,可以按照以下规则将左括号进行词法分析:如果看到两个左括号,则取两个,否则只取一个(超过两个是错误的情况)。对于右括号,使用解析器的状态来确定要将多少个放入词元中。这样可以保持单括号和双括号的词元不同。我认为这样做是正确的(“:”和“=”都是词元,但您不会单独使用它们来形成“:=”)。 - Daniel Lichtblau
我的天啊,我刚意识到我之前的评论以一个无意的表情符号结束了。我预计这预示着世界末日或者什么的。这是需要小心使用词汇的另一个原因。 - Daniel Lichtblau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接