Jison парсер генератор сдвига уменьшить конфликт с круглыми скобками, как решить? - PullRequest
0 голосов
/ 14 марта 2020

Я пытаюсь использовать скобки в моем парсере, но у меня конфликт в моей грамматике. «Конфликт в грамматике: несколько действий возможны, когда токен lookahead равен ) » Вот его упрощенная версия:

// grammar
{
    "Root": ["", "Body"],
    "Body": ["Line", "Body TERMINATOR Line"],
    "Line": ["Expression", "Statement"],
    "Statement": ["VariableDeclaration", "Call", "With", "Invocation"],
    "Expression": ["Value", "Parenthetical", "Operation", "Assign"],
    "Identifier": ["IDENTIFIER"],
    "Literal": ["String", "Number"],
    "Value": ["Literal", "ParenthesizedInvocation"],
    "Accessor": [". Property"],
    "ParenthesizedInvocation": ["Value ParenthesizedArgs"],
    "Invocation": ["Value ArgList"],
    "Call": ["CALL ParenthesizedInvocation"],
    "ParenthesizedArgs": ["( )", "( ArgList )"],
    "ArgList": ["Arg", "ArgList , Arg"],
    "Arg": ["Expression", "NamedArg"],
    "NamedArg": ["Identifier := Value"],
    "Parenthetical": ["( Expression )"],
    "Operation": ["Expression + Expression", "Expression - Expression"]
}

//precedence
[
  ['right', 'RETURN'],
  ['left', ':='],
  ['left', '='],
  ['left', 'IF'],
  ['left', 'ELSE', 'ELSE_IF'],
  ['left', 'LOGICAL'],
  ['left', 'COMPARE'],
  ['left', '&'],
  ['left', '-', '+'],
  ['left', 'MOD'],
  ['left', '\\'],
  ['left', '*', '/'],
  ['left', '^'],
  ['left', 'CALL'],
  ['left', '(', ')'],
  ['left', '.'],
]

В моей реализации мне нужны такие вызовы функций (с круглыми скобками и запятой) разделены):

Foo(1, 2)
Foo 1, 2

И иметь возможность использовать обычные скобки для приоритета операций. Даже в вызовах функций (но только в вызовах функций, заключенных в скобки):

Foo(1, (2 + 4) / 2)
Foo 1, 2

Вызов функции без круглых скобок, рассматриваемых как оператор, вызов функции с круглыми скобками, рассматриваемый как выражение.

Как мне разрешить этот конфликт

1 Ответ

0 голосов
/ 14 марта 2020

В VBA операторы вызова функций (в отличие от выражений) имеют две формы (упрощенно):

 CALL name '(' arglist ')'
 name arglist

Обратите внимание, что у второго нет круглых скобок вокруг списка аргументов. Именно для того, чтобы избежать двусмысленности:

Func (3) 

, с которой вы сталкиваетесь.

Неоднозначность состоит в том, что неясно, являются ли круглые скобки круглыми скобками, которые окружают список аргументов, или круглыми скобками, которые заключают круглое выражение в скобки. Это не существенная двусмысленность, так как результат фактически тот же. Но это все еще важно из-за возможности продолжения программы следующим образом:

Foo (3), (4)

, в этом случае важно, чтобы скобки были проанализированы как скобки, окружающие выражение в скобках.

Так одна возможность состоит в том, чтобы изменить вашу грамматику так, чтобы она была похожа на грамматику в справочнике VBA :

call-statement = "Call" (simple-name-expression / member-access-expression / index-expression / with-expression)
call-statement =/ (simple-name-expression / member-access-expression / with-expression) argument-list

Но я полагаю, что вы действительно хотите реализовать язык, похожий на VBA, не будучи строго совместимый. Это немного усложняет ситуацию.

В первом приближении вы можете потребовать, чтобы форма name '(' [arglist] ')' имела как минимум два аргумента (если он не пустой):

# Not tested
"Invocation": ["Literal '(' ArgList2 ')' ", "Literal '(' ')' ", "Literal ArgList"],
"ArgList": ["Arg", "ArgList2"],
"ArgList2": ["Arg ',' Arg", "ArgList2 ',' Arg"],
...