样式缩进/缩进标记与alex / haskell?

我正在为Haskell写一个Alex语言的小型语言词法分析器。

该语言被指定为具有pythonesque重要缩进,并且每当缩进级别改变时都会发出INDENT标记或DEDENT标记。

在像C这样的传统命令式语言中,你会在词法分析器中保留一个全局,并用每行的缩进级别进行更新。

这在Alex / Haskell中不起作用,因为我不能在Haskell的任何地方存储任何全局数据,并且我不能将所有的lexing规则放在任何monad或任何内容中。

那么,我该怎么做? 它甚至有可能吗? 或者我将不得不写我自己的词法分析器,并避免使用alex?


请注意,在其他空白敏感语言(如Haskell)中,布局处理确实是在词法分析器中完成的。 GHC实际上在Alex中实现了布局处理。 来源如下:

https://github.com/ghc/ghc/blob/master/compiler/parser/Lexer.x

正如jrockway指出的那样,在你的问题中有一些严重的错误会导致你误入歧途。 “我无法在Haskell的任何地方存储任何全球数据”处于错误的轨道上。 首先,你可以拥有全局状态,其次,你不应该在这里使用全局状态,当亚历克斯以安全的方式完全支持规则中的状态转换时。

看看Alex提供的AlexState结构,让你通过你的词法分析器进行状态检查。 然后,看看在GHC的布局实现中如何使用状态来实现缩进/取消缩进布局规则。 (在GHC的词法分析器中搜索“ - 布局处理”以查看状态是如何被推入和弹出的)。


我无法用Haskell在任何地方存储任何全局数据

这不是真的; 在大多数情况下,像国家monad就足够了,但也有ST monad。

但是,您不需要全局状态来执行此任务。 编写解析器由两部分组成; 词法分析和语法分析。 词法分析只是将一串字符变成一串有意义的记号。 语法分析将令牌转化为AST; 这是你应该处理缩进的地方。

当你解释缩进时,你会调用一个处理函数作为缩进级别的变化 - 当它增加(嵌套)时,你调用你的处理函数(也许增加一个arg,如果你想跟踪缩进级别); 当级别降低时,您只需从函数返回相关的AST部分。

(顺便说一下,使用全局变量对于我来说是一种命令式语言中不会出现的 - 如果有的话,它是一个实例变量。国家monad在概念上与此非常相似。)

最后,我认为“我不能把所有的规则放在任何monad里面”这句话表明对monad的某种误解。 如果我需要解析并保持全局状态,我的代码将如下所示:

data AST = ...
type Step = State Int AST

parseFunction :: Stream -> Step
parseFunction s = do
   level <- get
   ...
   if anotherFunction then put (level + 1) >> parseFunction ...
   else parseWhatever
   ...
   return node

parse :: Stream -> Step
parse s = do
   if looksLikeFunction then parseFunction ...

main = runState parse 0 -- initial nesting of 0

将功能应用程序与(.)($)组合在一起,可以将它们与(>>=)(>>) 。 除此之外,算法是相同的。 (“内部”没有“monad”。)

最后,你可能会喜欢适用的函子:

eval :: Environment -> Node -> Evaluated
eval e (Constant x) = Evaluated x
eval e (Variable x) = Evaluated (lookup e x)
eval e (Function f x y) = (f <$> (`eval` x) <*> (`eval` y)) e

(要么

eval e (Function f x y) = ((`eval` f) <*> (`eval` x) <*> (`eval` y)) e

如果你有类似“funcall”的东西......但我会离题。)

有大量关于应用函数,单子和箭头的文献分析。 所有这些都有可能解决您的问题。 阅读这些内容,看看你得到了什么。

链接地址: http://www.djcxy.com/p/65623.html

上一篇: style indent/dedent tokens with alex/haskell?

下一篇: Calculate Maturity date in SQL Server 2008