问题
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