goyacc: получение контекста для парсера yacc / нет `% param` - PullRequest
1 голос
/ 29 апреля 2019

Какой самый идиоматический способ получить некоторую форму контекста для синтаксического анализатора yacc в goyacc, т.е. эмулировать команду %param в традиционной yacc?

Мне нужно проанализировать для моей функции .Parse некоторый контекст (в данном случае, в том числе, например, где построить дерево синтаксического анализа).

Функция goyacc .Parse имеет значение объявлено

func ($$rcvr *$$ParserImpl) Parse($$lex $$Lexer) int {

Вещи, о которых я думал:

  • $$ParserImpl не могут быть изменены файлом .y,так что очевидное решение (добавить поля к нему) прямо сейчас, а жаль.
  • Поскольку $$Lexer - это интерфейс, я мог бы вставить контекст синтаксического анализатора в реализацию Lexer, а затем принудительно преобразовать тип $$lex к этой реализации (при условии, что мой синтаксический анализатор всегда использовал один и тот же лексер), но это кажется довольно отвратительным (для которого чтение не идиоматическое).Более того, (казалось бы) нет способа поместить сгенерированную пользователем строку в верхнюю часть функции Parse, например c := yylex.(*lexer).c, поэтому во многих десятках мест, где я хочу обратиться к этой переменной, я должен использовать довольнонекрасивая форма yylex.(*lexer).c, а не просто c.
  • Обычно я бы использовал %param в обычном yacc / C (ну, в любом случае, bison), но этоне существует в goyacc.
  • Я бы хотел избежать постобработки моего сгенерированного файла .go с sed или perl по понятным причинам.
  • Iхотите иметь возможность (идти) yacc для анализа более одного файла одновременно, поэтому глобальная переменная невозможна (и глобальные переменные вряд ли идиоматичны).

Какое здесь самое идиоматическое решение?Я продолжаю думать, что, должно быть, упускаю что-то простое.

1 Ответ

0 голосов
/ 01 мая 2019

Мое собственное решение состоит в том, чтобы изменить goyacc ( см. Этот PR ), который добавляет директиву %param, позволяющую добавить одно или несколько полей в структуру $$ParserImpl (доступную как $$rcvrв коде).Это кажется самым идиоматическим маршрутом.Это позволяет не только передавать контекст, но и возможность для пользователя добавлять дополнительные func() с использованием $$ParserImpl в качестве получателя.

...