Zeb*_*Zeb 7 dsl parsing haskell lexer alex
我正在使用 Alex + Happy 为 Haskell 中的 DSL 制作解析器。我的 DSL 使用掷骰子作为可能表达式的一部分。
有时我有一个我想解析的表达式,如下所示:
[some code...] 3D6 [... rest of the code]
Run Code Online (Sandbox Code Playgroud)
这应该大致翻译为:
TokenInt {... value = 3}, TokenD, TokenInt {... value = 6}
Run Code Online (Sandbox Code Playgroud)
我的 DSL 也使用变量(基本上是字符串),所以我有一个特殊的标记来处理变量名。所以,有了这个令牌:
"D" { \pos str -> TokenD pos }
$alpha [$alpha $digit \_ \']* { \pos str -> TokenName pos str}
$digit+ { \pos str -> TokenInt pos (read str) }
Run Code Online (Sandbox Code Playgroud)
我现在使用解析时得到的结果是:
TokenInt {... value = 3}, TokenName { ... , name = "D6"}
Run Code Online (Sandbox Code Playgroud)
这意味着我的词法分析器“读取”了一个整数和一个名为“D6”的变量。
我尝试了很多东西,例如,我将令牌D更改为:
$digit "D" $digit { \pos str -> TokenD pos }
Run Code Online (Sandbox Code Playgroud)
但这只会消耗数字:(
PS:我使用 PosN 作为包装器,不确定是否相关。
小智 1
我的方法是将类型扩展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' s
Run Code Online (Sandbox Code Playgroud)
split
可以在这里找到。
这是一个额外的步骤,通常在句法分析过程中完成,但在这里并没有太大影响。
另外,我无法让 Alex 解析$alpha
为TokenD
而不是TokenName
。如果我们有Di
而不是D
那就没问题了。来自亚历克斯的文档:
当输入流匹配多个规则时,匹配输入流最长前缀的规则获胜。如果仍有多个规则匹配相同数量的字符,则文件中最早出现的规则获胜。
但是这样你的代码应该可以工作。我不知道这是否是亚历克斯的问题。