Разбирать приложения в стиле лямбда-исчисления с помощью LL1-парсера
Я использую TinyPG, который является генератором парсера LL1, для разбора лямбда-исчисления. Я пытаюсь написать правило, которое будет анализировать функцию приложения, как (a b)
или же (a b c)
и так далее.
Пока что у меня есть это правило (немного упрощенное):
APPLICATION -> LPARENTHESES VARIABLE (SPACE+ VARIABLE)+ RPARENTHESES;
Но это не сможет проанализировать термин, который имеет пробелы после левых и перед правыми скобками: ( a b )
, Я могу разрешить пробелы после открывающей скобки, как это:
APPLICATION -> LPARENTHESES SPACE* VARIABLE (SPACE+ VARIABLE)+ RPARENTHESES;
Но у меня возникли проблемы с настройкой, чтобы оставить пробелы перед закрывающей скобкой. Я пришел с этим, который, кажется, работает:
ARG_LIST -> (RPARENTHESES | (SPACE+ (RPARENTHESES | (VARIABLE ARG_LIST))));
APPLICATION -> LPARENTHESES SPACE* VARIABLE ARG_LIST;
Но он беспорядочный и рекурсивный, что затруднит чтение и компиляцию узлов. Есть ли нерекурсивный или хотя бы более простой способ разобрать это?
1 ответ
Нет смысла путать парсер с пробелами. Достаточно игнорировать его в сканере, используя [Skip]
атрибут, как показано в руководстве:
[Skip] WHITESPACE -> @"\s+";
"Пропустить" не означает "удалить". Это означает, что сканер должен распознать токен, а затем проигнорировать его. Если пропустить пробел, пробел все равно будет отлично разделять буквенно-цифровые токены. Вам просто не нужно включать пробел в вашу грамматику, оставляя вас с:
APPLICATION -> LPARENTHESES VARIABLE VARIABLE+ RPARENTHESES;
(На самом деле, пустые списки приложений обычно разрешены, поэтому я бы написал это с *
вместо +
, Но это твой язык.)