Парсеры, сгенерированные потоком FSYacc, безопасны?
Если я сгенерирую парсер с помощью 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 ответ
Я действительно не люблю отвечать на свой собственный вопрос, однако, поскольку это может спасти кого-то еще от горя, когда-нибудь я это сделаю.
Оказывается, что функции, предоставляемые в модуле синтаксического анализа, НЕ являются потокобезопасными. Однако вы можете получить доступ к parseState
"переменная", которая имеет тип IParseState
в твоих нетерминальных действиях.
Например (грубо, но работайте со мной): если у вас есть нетерминал, как
% tokenNAME %% Человек: NAME NAME { $1 (* action *) }
Сгенерированный код:
(fun (parseState: Microsoft.FSharp.Text.Parsing.IParseState) -> let _1 = (let data = parseState.GetInput (1) в (Microsoft.FSharp.Core.Operators.unbox data: string)) в Microsoft.FSharp.Core.Operators.box((_1): 'Person));
Таким образом, вы можете взаимодействовать с этим объектом parseState таким же образом.
% tokenNAME %% Человек: NAME NAME { parseState.DoStuff(); }
rhs_start_pos
Метод в основном делает это:
let startPos, endPos = parseState.InputRange (n)
и symbol_end_pos
Является ли это:
let startSymb, endSymb = parseState.ResultRange
надеюсь, это поможет