如何在使用F#FsYacc解析期间添加和使用自定义上下文参数?

时间:2012-07-05 10:24:57

标签: parsing f# fsyacc

我正在使用 FsLex FsYacc 在F#应用程序中进行字符串解析。在抽象语法树(AST)创建过程中,解析器必须决定如何创建AST(制作不同的树,抛出异常等)。 解析器行为必须依赖于几个参数。

Here我发现允许声明类似的内容:

%type < (context -> context) > toplevel

但是我找不到如何使用这种结构,在项目编译过程中,“fsyacc.exe”退出了代码1.“错误

问题是:是否可以以及如何在使用FsYacc解析时使用上下文参数?

我试过的

示例

%start startAst

%type < (bool -> MyAst) > startAst

%%   

startAst:
| MyAst EOF { 
                    (fun (x : bool) -> 
                        if x then 
                            MyAst.Type1 $1 
                        else 
                            MyAst.Type2) 
                }
...

我希望使用类似这样的东西:

let lexbuf = Lexing.LexBuffer<char>.FromString text
lexbuf |> Lexer.tokenize |> Parser.startAst (ctx: bool)

提前致谢

以下异常

更新,并在执行fsyacc.exe期间生成调用堆栈:

Unhandled Exception: System.Exception: more than one input given
   at FSharp.PowerPack.FsYacc.Driver.clo@67-5.Invoke(String x)
   at <StartupCode$fsyacc>.$Arg.findMatchingArg$cont@104-1(FSharpRef`1 cursor, FSharpFunc`2 other, String usageText, FSharpList`1 argSpecs, String arg, Unit unitVar)
   at <StartupCode$fsyacc>.$Arg.findMatchingArg@64(FSharpRef`1 cursor, String[] argv, FSharpFunc`2 other, String usageText, Int32 nargs, FSharpList`1 argSpecs, String arg, FSharpList`1 args)
   at Internal.Utilities.ArgParser.ParsePartial(FSharpRef`1 cursor, String[] argv, IEnumerable`1 arguments, FSharpOption`1 otherArgs, FSharpOption`1 usageText)
   at Internal.Utilities.ArgParser.Parse(IEnumerable`1 arguments, FSharpOption`1 otherArgs, FSharpOption`1 usageText)
   at <StartupCode$fsyacc>.$FSharp.PowerPack.FsYacc.Driver.main@()

1 个答案:

答案 0 :(得分:2)

很抱歉长时间拖延,但终于解决了这个问题。

谁写过FsYacc(F#团队?)错过了这些功能,可以通过他们自己对您链接的页面的评论看出来。我尝试了几种变体,但这是我唯一能够工作的变体(注意:这需要#nowarn "62"文件中的.fsy,它将传播到.fs文件,或--nowarn:62整个项目):

%{

open Ast

type ('a,'b) Fun = 'a -> 'b

%}

%start startAst

%token <string> MyAst
%token EOF

%type < (bool, MyAst) Fun > startAst

%%

startAst:
| MyAst EOF { (fun (x : bool) ->
                if x then
                    MyAst.Type1 $1
                else
                    MyAst.Type2) }

我不知道为什么(并且没有时间回顾FsYacc的来源,至少现在不是这样)。