Parsing 快乐与幸福;Alex-防止前瞻影响解析器lexer通信

Parsing 快乐与幸福;Alex-防止前瞻影响解析器lexer通信,parsing,haskell,compiler-construction,happy,alex,Parsing,Haskell,Compiler Construction,Happy,Alex,我目前正在为一种玩具语言的编译器编写解析器 使用Happy&Alex。由于某种形式的可选布局是必需的,我不得不改变 Alex在匹配块非终端之前的状态。不幸的是 Happy所需的先行令牌似乎已在之前读取 我有机会改变亚历克斯的状态 下面是一个演示问题的小片段: funcDef : header localDefs block ^ I have to change alex's state

我目前正在为一种玩具语言的编译器编写解析器 使用Happy&Alex。由于某种形式的可选布局是必需的,我不得不改变 Alex在匹配
非终端之前的状态。不幸的是 Happy所需的先行令牌似乎已在之前读取 我有机会改变亚历克斯的状态

下面是一个演示问题的小片段:

funcDef : header localDefs block
                          ^ I have to change alex's state 
                            before the underlying lexer
                            starts reading the block tokens.

有解决这个问题的通用方法吗?

我假设您使用的是线程lexer(so Happy和Alex在同一个monad中运行)。我在遇到类似问题时使用的技巧是创建一个空的生产规则,然后将其滑入规则中

changeAlexState :: { () }
  : {- empty -} {%% \tok -> changeAlexState *> pushTok tok }

funcDef : header localDefs changeAlexState block
然后,您需要向monad添加一些状态以支持
pushTok::Token->p()
(其中
p
是您的词法分析/解析monad),并确保在词法分析时始终弹出该标记。
%%
所做的是

n:t\u 1。。。t{%%}

。。。
的类型是相同的[仍然是
令牌->P a
],但在这种情况下,实际上放弃了先行令牌,并从输入中读取新令牌。当您想要更改下一个标记并继续解析时,这可能非常有用


我提到不久前我做过类似的事情,和。让我知道进展如何

你怎么知道一个街区从哪里开始?我假定,
localDefs
不是自终止的,因此必须有一些词汇特性,您可以使用它们来知道块从何处开始。你能解释一下吗?@rici该块要么被开始/结束关键字包围,要么是基于缩进的。它基本上定义为begin stmts+end或stmts autoend。lexer需要被通知begin丢失,以便在检测到标识更改时生成autoend。整个方法让人感觉非常粗糙,必须有更好的方法。我两周前刚刚解决了这个问题。“没想到其他人会碰到它。”亚历克急切地等待着细节!我将等待@alec写什么,但我的方法是要么使换行符对解析器可见,在这种情况下,lexer更改可以在触发器令牌之前完成,要么在lexer中处理所有内容。这两种语言都有点粗制滥造,但语法也是如此:)对比python对冒号的使用。