How to add and use custom context parameters during parsing with F# FsYacc?

十年热恋 提交于 2019-12-21 06:21:47

问题


I'm using FsLex and FsYacc for string parsing in F# application. During Abstract Syntax Tree (AST) creation parser has to do a decision how to create the AST (make different trees, throw an exception, etc). The parser behaviour must depend on several parameters.

Here I've found that it is allowed to declare something like:

%type < (context -> context) > toplevel

But I could not find how to use this construction and during project compilation have "fsyacc.exe" exited with code 1." error

The Question is: is it possible and how to use context parameters during parsing with FsYacc?

Example of what I've tried:

%start startAst

%type < (bool -> MyAst) > startAst

%%   

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

and I've expected usage something like this:

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

Thanks in advance

Update following exception and call stack is generated during fsyacc.exe execution:

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:


Sorry for the long delay, but finally got around to this.

Whoever wrote FsYacc (the F# team?) missed the functions, as can be seen by their own comment on the page you linked. I tried several variations, but this is the only one I was able to make work (note: this requires either a #nowarn "62" in the .fsy file, which will propagate to the .fs file, or --nowarn:62 for the whole project):

%{

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) }

I got no idea why (and don't have the time to go over FsYacc's source, at least not right now).



来源:https://stackoverflow.com/questions/11342379/how-to-add-and-use-custom-context-parameters-during-parsing-with-f-fsyacc

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!