3
votes

If I generate a parser using FSYacc will it be thread safe?

The only reason I ask is because the functions

Parsing.rhs_start_pos and Parsing.symbol_end_pos

don't appear to have any state passed into them, which would lead me to assume that they are getting the current NonTerminal/Symbols from a shared location, is this correct?

After reflecting the code I see that they are getting the postion from a static property

internal static IParseState parse_information
{
    get
    {
        return parse_information;
    }
    set
    {
        parse_information = value;
    }
}

Is this correct? If so what can I do about it?

Edit: I also see a static method called set_parse_state

public static void set_parse_state(IParseState x)
{
    parse_information = x;
}

But that still wont solve my problem...

1

1 Answers

2
votes

I really don't like to answer my own question, however since this could save someone else a world of grief someday I will.

It turns out that the functions provided in the parsing module are NOT thread safe. What you can do however is access the parseState "variable", which is of type IParseState, in your nonterminal action.

For example (rough but work with me): If you have a NonTerminal like

%token<string> NAME
%%
Person:
       NAME NAME { $1 (* action *) }

The code that gets generated is:

(fun (parseState : Microsoft.FSharp.Text.Parsing.IParseState) ->
      let _1 = (let data = parseState.GetInput(1) in 
                           (Microsoft.FSharp.Core.Operators.unbox data : string)
                ) in
      Microsoft.FSharp.Core.Operators.box((_1) : 'Person)
);

So you can interact with that parseState object in the same fashion.

%token<string> NAME
%%
Person:
       NAME NAME { parseState.DoStuff(); }

The rhs_start_pos method basically does this:

let startPos,endPos = parseState.InputRange(n)

and the symbol_end_pos does this:

let startSymb,endSymb = parseState.ResultRange

I hope this helps