我可以将参数传递给我的fsyacc解析器吗?

3

我知道可以向词法分析器传递参数:

rule tokenize scope = parse
  | whitespace       { tokenize scope lexbuf                       }
  | newline          { newline lexbuf; tokenize scope lexbuf       }

但是我无法以类似的方式定义我的解析器起始符号。

我尝试像这样定义它:(感谢this问题)

%type < (IScope, AST.Script) Fun > Script

// with the following definition in the head section of the parser:
type ('a,'b) Fun = 'a -> 'b

但是我需要这样定义每个非终端符号,并且它们都返回lambda。这不是我想要实现的,我希望能够在解析过程中访问“scope”参数并执行它们的操作。
我注意到IParseState类型中有一个“ParserLocalStore”,其中仅包含“LexBuffer”(仅通过调试进行检查)。由于我可以通过每个非终端符号中的“parseState”访问它,所以我可以在其中存储参数吗?或者那是一个坏主意?
我考虑在解析器的头部使用可变变量,但它们会是静态的(我认为?),这将阻止我同时解析多个输入... 编辑: 目前我将“scope”参数存储在特定的标记中:
%token <string * IScope> IDENT

我将scope传递给词法分析器,当它创建相关的标记时,将其嵌入其中...我真的不喜欢这个解决方案,但我还没有想到更好的方法。


不是答案,但你考虑过 FParsec 吗?参数传递已经内置且易于操作。 - Daniel
目前还没有。我们即将开始另一个解析器项目,可能会在那里使用ANTLR。如果我们(在某个时候)决定也在当前项目中使用ANTLR,我使用fsyacc进行移植会更容易。就解析器组合器而言(至少据我所知),我没有非常清晰的语法,并且必须以相当不同的方式完成所有操作,而fsyacc / ANTLR解析器的大部分结构似乎是相似的。 - enzi
1个回答

0

LexBuffer 中有一个 Dictionary<string, obj>,也可以通过parseState获得。在找不到更好的解决方案时,我最终将我的参数存储在那里。

我知道这很可能不是预期以这种方式使用的,而且在未来版本的 fsyacc 中可能不可用,但我现在仍然坚持使用它。如果有人需要做相同的事情,我提供了两个扩展方法,以更清晰的方式访问我的参数:

type IParseState with
    member x.LexBuffer() = x.ParserLocalStore.["LexBuffer"] :?> LexBuffer<char>

type LexBuffer<'a> with
    member x.SomeParameter
        with get() = x.BufferLocalStore.["SomeParameter"] :?> SomeParamType
        and set(v) = x.BufferLocalStore.["SomeParameter"] <- v

由于目前还没有任何答案,我暂时接受这个答案。但是如果您有更好的解决方案,请随时提出,我会更改已接受的答案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接