我正在使用Parsec/Megaparsec 作为解析器来实现编译器。我找不到重载 operator 的方法+
,我想将它用于整数加法和字符串连接。可能吗?
问问题
88 次
1 回答
1
首先编写编译器以使用不同的运算符进行字符串连接,例如@
. 当您运行并经过良好测试后,请查看您的代码。您可能会发现发生了两种情况之一,具体取决于您正在解析的语言和您使用的编译器体系结构。
第一种可能性是解析器的解析部分与解析器的解析+
部分完全分开@
(例如,它们位于两个不同的解析器函数中,一个用于解析数字表达式,另一个用于解析字符串表达式)。如果发生这种情况,恭喜,您只需替换"@"
为"+"
,运行一些测试,就可以了。
第二种可能性是和在同一个地方解析并产生具有不同构造函数的 AST 节点:+
@
data Expr ... =
...
| Plus Expr Expr -- the '+' operator
| Concat Expr Expr -- the '@' operator
...
在这种情况下,您可能还有编译器的某些部分正在生成代码(并希望有一些类型信息):
codeGen (Plus e1 e2)
= do (code1, typ1) <- codeGen e1
(code2, typ2) <- codeGen e2
if (typ1 == Num && typ2 == Num)
then genPlus code1 code2
else typeError "'+' needs numbers"
codeGen (Concat e1 e2)
= do (code1, typ1) <- codeGen e1
(code2, typ2) <- codeGen e2
if (typ1 == Str && typ2 == Str)
then genConcat code1 code2
else typeError "'@' needs strings"
在这种情况下,您应该修改解析器/AST 以将 AST 折叠为仅一个共享构造函数:
data Expr ... =
...
| ConcatPlus Expr Expr -- the '+' operator for numbers and strings
...
并在代码生成器中处理这两种情况,具体取决于可用的类型信息:
codeGen (ConcatPlus e1 e2)
= do (code1, typ1) <- codeGen e1
(code2, typ2) <- codeGen e2
case (typ1, typ2) of
(Num, Num) -> genPlus code1 code2
(Str, Str) -> genConcat code1 code2
_ -> typeError "'+' arguments must have same type (numbers or strings)"
如果您的编译器看起来不像这些示例,您必须发布一些代码,以便我们知道它的样子。
于 2019-07-04T19:19:32.893 回答