Parsing 使用递归下降从该语法生成表达式
我有一个简单的语法。实际上,我使用的语法更复杂,但这是说明我的问题的最小子集Parsing 使用递归下降从该语法生成表达式,parsing,language-agnostic,graph,recursive-descent,Parsing,Language Agnostic,Graph,Recursive Descent,我有一个简单的语法。实际上,我使用的语法更复杂,但这是说明我的问题的最小子集 Expr ::= Value Suffix | "(" Expr ")" Suffix Suffix ::= "->" Expr | "<-" Expr | Expr | epsilon 也就是说,a转到b和(c->(d)(e))的结果,c转到d和e。我试图为这些表达式生成一个抽象语法树,但遇到了困难,因为所有运算符都可以接受任意数量的
Expr ::= Value Suffix
| "(" Expr ")" Suffix
Suffix ::= "->" Expr
| "<-" Expr
| Expr
| epsilon
也就是说,a
转到b
和(c->(d)(e))
的结果,c
转到d
和e
。我试图为这些表达式生成一个抽象语法树,但遇到了困难,因为所有运算符都可以接受任意数量的操作数。我宁愿在递归下降解析方法中保留生成AST的逻辑,因为它避免了重复提取表达式的逻辑。我目前的策略如下:
值
,将其推送到输出:
输出一个分隔符
获取下一个Expr
创建一个链接
节点
将输出中的第一组操作数弹出到链接中
,直到出现分隔符
清除发现的分隔符
将第二组操作数弹出到链接中
,直到出现分隔符
将链接
推到输出
a->b(c->(d)(e))
,输出应为:
A sep_1 B sep_2 C sep_3 D E
将应用于
规则将产生:
A sep_1 B sep_2 (link from C to {D, E})
随后:
(link from A to {B, (link from C to {D, E})})
需要注意的重要一点是,sep_2
,这对于分隔第二个->
的左侧操作数至关重要,但没有出现,因此解析器认为表达式实际上是编写的:
a -> (b c -> (d) (e))
为了用我当前的策略解决这个问题,我需要一种在相邻表达式之间生成分隔符的方法,但前提是当前表达式是括号中包含的
From
或to
表达式。如果这是可能的,那么我只是没有看到它,答案应该很简单。但是,如果有更好的方法,请告诉我 我没有尝试详细分析它,但是:“从
或到
表达式括在括号中”听起来很像“上下文相关”,递归下降无法直接处理。为了避免上下文依赖,您可能需要为括号中的From
或To
与From
或To
单独生成一个不带括号的产品
编辑:虽然现在做任何好事都为时已晚,但如果我对您想要匹配的内容的理解是正确的,我想我会这样写:
Graph :=
| List Sep Graph
;
Sep := "->"
| "<-"
;
List :=
| Value List
;
Value := Number
| Identifier
| String
| '(' Graph ')'
;
Graph:=
|列表Sep图
;
九月:=“->”
|“啊哈!没错。我将尝试添加另一个生成规则。通常我不使用递归下降,因为我不喜欢重构复杂的语法,所以这对我来说是一种学习经验。一切就绪!感谢您的帮助。”。
Graph :=
| List Sep Graph
;
Sep := "->"
| "<-"
;
List :=
| Value List
;
Value := Number
| Identifier
| String
| '(' Graph ')'
;