문제

I know that it is possible to pass parameters to a lexer:

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

but I'm not able to define my parser start symbol in a similar fashion.

I tried to define it like this: (thanks to this question)

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

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

But then I would have to define every non-terminal symbol like this and they would all return lambdas. This is not what I'm trying to achieve though, I'd like to be able to access the scope parameter within several non-terminals and execute their action during parsing.

I noticed that there is a ParserLocalStore in the IParseState type, which contains only the LexBuffer (only checked by debugging). Since I have access to it via parseState in every non-terminal, may I be able to store parameters in there, or would that be a bad idea?

I thought about using mutable variables in the head section of the parser, but they would be static (I think?) and that would prevent me from parsing multiple inputs simultaneously...

Edit:

Currently I store the scope parameter in specific tokens:

%token <string * IScope> IDENT

I pass scope to the Lexer, who embeds it in the relevant tokens when he creates them... I really don't like this solution, but I was unable to come up with something better yet.

도움이 되었습니까?

해결책

There is a Dictionary<string, obj> in the LexBuffer, which can also be obtained via parseState. Having found no better solution, I ended up storing my parameters there.

I'm aware that this is very likely not intended to be used in such a way and may not be available in future versions of fsyacc, but I'm sticking to it for now. In case someone needs to do the same, I leave the two extension methods here which I created to access my parameters in a cleaner manner:

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

Since there haven't been any answers yet, I'll accept this one for now. Feel free though to suggest a better solution and I'll change the accepted answer.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top