ANTLR 4 语法分析器
ANTLR 4 Parser Grammar
如何改进我的解析器语法,而不是为我的测试代码创建一个包含几个 decFunc
规则的 AST。它只会创建一个并且 sum
成为第二个根。我尝试使用多种不同的方法来解决这个问题,但我总是遇到左递归错误。
这是我的测试代码:
f :: [Int] -> [Int] -> [Int]
f x y = zipWith (sum) x y
sum :: [Int] -> [Int]
sum a = foldr(+) a
这是我的语法:
这是在这个 link 中有两个 decFunc
的图像
http://postimg.org/image/w5goph9b7/
prog : stat+;
stat : decFunc | impFunc ;
decFunc : ID '::' formalType ( ARROW formalType )* NL impFunc
;
anotherFunc : ID+;
formalType : 'Int' | '[' formalType ']' ;
impFunc : ID+ '=' hr NL
;
hr : 'map' '(' ID* ')' ID*
| 'zipWith' '(' ('*' |'/' |'+' |'-') ')' ID+ | 'zipWith' '(' anotherFunc ')' ID+
| 'foldr' '(' ('*' |'/' |'+' |'-') ')' ID+
| hr op=('*'| '/' | '.&.' | 'xor' ) hr | DIGIT
| 'shiftL' hr hr | 'shiftR' hr hr
| hr op=('+'| '-') hr | DIGIT
| '(' hr ')'
| ID '(' ID* ')'
| ID
;
您的测试输入包含两个匹配 decFunc
规则的内容实例。生成的 parse-tree 准确地显示了:两个子树,每个子树都有一个 deFunc
作为根。
Antlr v4 不会生成真正的 AST,其中 f
和 sum
是单独子树的根。
Is there any thing can I do with the grammar to make both f
and sum
roots – Jonny Magnam
不是直接在 Antlr v4 语法中。你可以:
- 切换到 Antlr v3 或其他解析器工具,并根据需要定义生成的 AST。
- 遍历 Antlr v4 解析树并创建所需形式的单独 AST。
- 直接使用解析树,并意识到它在信息上等同于经典定义的 AST,并且该实现提供了许多实际好处。
具体来说,标准学术 AST 是可变的,这意味着每个(或除了第一个)访问者都是自定义的,而不是生成的,并且 AST 的基础语法或临时结构的任何变化都需要重新考虑和可能会更改每个后续访问者及其实施的逻辑。
Antlr v4 解析树本质上是不可变的,允许在不损失关系完整性的情况下针对树节点累积装饰。访问者都使用一个共同的基础结构,大大减少了由于语法变化和先前执行的访问者的影响而导致的脆弱性。实际上,树步道易于构建、快速且相互独立,除非明确要求。他们可以在设计中实现更大的关注点分离,并在实践中更轻松地维护代码。
为整个工作选择正确的工具,无论您如何定义它。
如何改进我的解析器语法,而不是为我的测试代码创建一个包含几个 decFunc
规则的 AST。它只会创建一个并且 sum
成为第二个根。我尝试使用多种不同的方法来解决这个问题,但我总是遇到左递归错误。
这是我的测试代码:
f :: [Int] -> [Int] -> [Int]
f x y = zipWith (sum) x y
sum :: [Int] -> [Int]
sum a = foldr(+) a
这是我的语法:
这是在这个 link 中有两个 decFunc
的图像
http://postimg.org/image/w5goph9b7/
prog : stat+;
stat : decFunc | impFunc ;
decFunc : ID '::' formalType ( ARROW formalType )* NL impFunc
;
anotherFunc : ID+;
formalType : 'Int' | '[' formalType ']' ;
impFunc : ID+ '=' hr NL
;
hr : 'map' '(' ID* ')' ID*
| 'zipWith' '(' ('*' |'/' |'+' |'-') ')' ID+ | 'zipWith' '(' anotherFunc ')' ID+
| 'foldr' '(' ('*' |'/' |'+' |'-') ')' ID+
| hr op=('*'| '/' | '.&.' | 'xor' ) hr | DIGIT
| 'shiftL' hr hr | 'shiftR' hr hr
| hr op=('+'| '-') hr | DIGIT
| '(' hr ')'
| ID '(' ID* ')'
| ID
;
您的测试输入包含两个匹配 decFunc
规则的内容实例。生成的 parse-tree 准确地显示了:两个子树,每个子树都有一个 deFunc
作为根。
Antlr v4 不会生成真正的 AST,其中 f
和 sum
是单独子树的根。
Is there any thing can I do with the grammar to make both
f
andsum
roots – Jonny Magnam
不是直接在 Antlr v4 语法中。你可以:
- 切换到 Antlr v3 或其他解析器工具,并根据需要定义生成的 AST。
- 遍历 Antlr v4 解析树并创建所需形式的单独 AST。
- 直接使用解析树,并意识到它在信息上等同于经典定义的 AST,并且该实现提供了许多实际好处。
具体来说,标准学术 AST 是可变的,这意味着每个(或除了第一个)访问者都是自定义的,而不是生成的,并且 AST 的基础语法或临时结构的任何变化都需要重新考虑和可能会更改每个后续访问者及其实施的逻辑。
Antlr v4 解析树本质上是不可变的,允许在不损失关系完整性的情况下针对树节点累积装饰。访问者都使用一个共同的基础结构,大大减少了由于语法变化和先前执行的访问者的影响而导致的脆弱性。实际上,树步道易于构建、快速且相互独立,除非明确要求。他们可以在设计中实现更大的关注点分离,并在实践中更轻松地维护代码。
为整个工作选择正确的工具,无论您如何定义它。