我正在为Haskell中的DSL创建一个解析器,使用Alex +快乐。我的DSL使用骰子卷作为可能表达式的一部分。
有时,我有一个要解析的表达式,看起来如下所示:
[some code...] 3D6 [... rest of the code]它应大致翻译为:
TokenInt {... value = 3}, TokenD, TokenInt {... value = 6}我的DSL也使用变量(基本上是Strings),所以我有一个特殊的令牌来处理变量名。因此,使用这个令牌:
"D" { \pos str -> TokenD pos }
$alpha [$alpha $digit \_ \']* { \pos str -> TokenName pos str}
$digit+ { \pos str -> TokenInt pos (read str) }现在使用我的解析时得到的结果是:
TokenInt {... value = 3}, TokenName { ... , name = "D6"}这意味着我的lexer“读取”一个整数和一个名为"D6“的变量。
我尝试过许多事情,例如,我将令牌D更改为:
$digit "D" $digit { \pos str -> TokenD pos }但这只会消耗数字:
PS:我正在使用PosN作为包装,不确定是否相关。
发布于 2020-07-13 21:11:13
我的做法是将TokenD类型扩展到TokenD Int Int,因此为了方便起见,我将使用basic包装器
$digit+ D $digit+ { dice }
...
dice :: String -> Token
dice s = TokenD (read $ head ls) (read $ last ls)
where ls = split 'D' ssplit可以找到这里。
这是一个额外的步骤,通常是在句法分析过程中完成的,但在这里并不会造成太大的伤害。
而且,我不能让亚历克斯为TokenD而不是TokenName解析TokenName。如果我们有Di而不是D,那就没问题了。从亚历克斯的医生那里:
当输入流匹配多个规则时,匹配输入流最长前缀的规则将获胜。如果仍然有几条规则匹配相同数量的字符,那么文件中最早出现的规则将获胜。
但这样你的代码就能工作了。我不知道这是不是亚历克斯的问题。
发布于 2020-07-14 01:34:05
我决定用小写字母开头的变量(像Haskell变量)可以生存下来,所以,只有当变量以小写字母开头时,我才会将lexer更改为解析变量。这也解决了一些其他保留词可能出现的问题。
我仍然很想知道是否有其他的解决方案,但问题本身已经解决了。
谢谢大家!
https://stackoverflow.com/questions/62869400
复制相似问题