3

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@()
Vitaliy
  • 2,744
  • 1
  • 24
  • 39
  • If you run `fsyacc.exe` manually (through the command-line), you'll get a nice friendly error. Please do so, and post here. – Ramon Snir Jul 05 '12 at 10:30
  • Currently I have only "fsyacc.exe has stopped working" exception without any log information – Vitaliy Jul 05 '12 at 10:34
  • I sure that my code is incorrect? but I don;t know how correctly use it with FsYacc - probably somebody will provide me with useful link (even to OCaml Yacc example, where it is used) – Vitaliy Jul 05 '12 at 10:55

1 Answers1

2

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

Ramon Snir
  • 7,520
  • 3
  • 43
  • 61
  • 1
    @Vitaliy glad to help. Reported it via CodePlex (and verified that the problem indeed lies in the FsYacc source code): http://fsharppowerpack.codeplex.com/workitem/7025 – Ramon Snir Jul 06 '12 at 14:22