首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Haskell中的Alex制作一个分析骰子的词汇

使用Haskell中的Alex制作一个分析骰子的词汇
EN

Stack Overflow用户
提问于 2020-07-13 04:48:16
回答 2查看 403关注 0票数 6

我正在为Haskell中的DSL创建一个解析器,使用Alex +快乐。我的DSL使用骰子卷作为可能表达式的一部分。

有时,我有一个要解析的表达式,看起来如下所示:

代码语言:javascript
复制
[some code...]  3D6  [... rest of the code]

它应大致翻译为:

代码语言:javascript
复制
TokenInt {... value = 3}, TokenD, TokenInt {... value = 6}

我的DSL也使用变量(基本上是Strings),所以我有一个特殊的令牌来处理变量名。因此,使用这个令牌:

代码语言:javascript
复制
"D"                                 { \pos str -> TokenD pos }
$alpha [$alpha $digit \_ \']*       { \pos str -> TokenName pos str}
$digit+                             { \pos str -> TokenInt pos (read str) }

现在使用我的解析时得到的结果是:

代码语言:javascript
复制
TokenInt {... value = 3}, TokenName { ... , name = "D6"}

这意味着我的lexer“读取”一个整数和一个名为"D6“的变量

我尝试过许多事情,例如,我将令牌D更改为:

代码语言:javascript
复制
$digit "D" $digit                   { \pos str -> TokenD pos }

但这只会消耗数字:

  • 我能用数字解析骰子卷吗?
  • 或者至少解析TokenInt-TokenD-TokenInt?

PS:我正在使用PosN作为包装,不确定是否相关。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-07-13 21:11:13

我的做法是将TokenD类型扩展到TokenD Int Int,因此为了方便起见,我将使用basic包装器

代码语言:javascript
复制
$digit+ D $digit+ { dice }
...
dice :: String -> Token
dice s = TokenD (read $ head ls) (read $ last ls)
  where ls = split 'D' s

split可以找到这里

这是一个额外的步骤,通常是在句法分析过程中完成的,但在这里并不会造成太大的伤害。

而且,我不能让亚历克斯为TokenD而不是TokenName解析TokenName。如果我们有Di而不是D,那就没问题了。从亚历克斯的医生那里:

当输入流匹配多个规则时,匹配输入流最长前缀的规则将获胜。如果仍然有几条规则匹配相同数量的字符,那么文件中最早出现的规则将获胜。

但这样你的代码就能工作了。我不知道这是不是亚历克斯的问题。

票数 1
EN

Stack Overflow用户

发布于 2020-07-14 01:34:05

我决定用小写字母开头的变量(像Haskell变量)可以生存下来,所以,只有当变量以小写字母开头时,我才会将lexer更改为解析变量。这也解决了一些其他保留词可能出现的问题。

我仍然很想知道是否有其他的解决方案,但问题本身已经解决了。

谢谢大家!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62869400

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档