Парсеры, сгенерированные потоком FSYacc, безопасны? - PullRequest
3 голосов
/ 04 июня 2009

Если я сгенерирую парсер с помощью FSYacc, будет ли он потокобезопасным?

Единственная причина, по которой я спрашиваю, заключается в том, что функции

Parsing.rhs_start_pos и Parsing.symbol_end_pos

не не представляется для передачи какого-либо состояния в них, что заставило бы меня предположить, что они получают текущий нетерминал / символы из общего расположения, это правильно?

После отражения кода я вижу, что они получают статическое свойство

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

Это правильно? Если так, что я могу с этим поделать?

Редактировать: я также вижу статический метод с именем set_parse_state

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

Но это все равно не решит мою проблему ...

1 Ответ

2 голосов
/ 04 июня 2009

Мне действительно не нравится отвечать на мой собственный вопрос, однако, поскольку это может спасти кого-то еще от горя, когда-нибудь я смогу.

Оказывается, что функции, предусмотренные в модуле синтаксического анализа, НЕ являются потокобезопасными. Однако вы можете получить доступ к parseState «переменной» типа IParseState в своем нетерминальном действии.

Например (грубо, но работай со мной): Если у вас нетерминал, такой как

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

Генерируемый код:

(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)
);

Таким образом, вы можете взаимодействовать с этим объектом parseState таким же образом.

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

Метод rhs_start_pos в основном делает это:

let startPos,endPos = parseState.InputRange(n)

и symbol_end_pos делает это:

let startSymb,endSymb = parseState.ResultRange

Надеюсь, это поможет

...