Бизон, взаимодействующий с flex в c ++ - PullRequest
0 голосов
/ 05 июня 2018

Я пытаюсь написать компилятор и использую flex / bison для сканирования и анализа.Мой вопрос о том, как эти 2 могут общаться, чтобы lex передавал тип токена и (если необходимо) семантическое значение.

Проблема в том, что я нахожу разные (противоречивые?) Документы.

Например, здесь они упоминают об использовании подполей yylval для семантического значения и возвращают тип токена (возможно, и целое число).

[0-9]+ {
   yylval->build<int> () = text_to_int (yytext);
   return yy::parser::token::INTEGER;
}
[a-z]+ {
   yylval->build<std::string> () = yytext;
   return yy::parser::token::IDENTIFIER;
 }

Но тогда я вижу (такжев официальных документах) this :

"-"      return yy::calcxx_parser::make_MINUS  (loc);
"+"      return yy::calcxx_parser::make_PLUS   (loc);
"*"      return yy::calcxx_parser::make_STAR   (loc);
"/"      return yy::calcxx_parser::make_SLASH  (loc);
"("      return yy::calcxx_parser::make_LPAREN (loc);
")"      return yy::calcxx_parser::make_RPAREN (loc);
":="     return yy::calcxx_parser::make_ASSIGN (loc);

{int}      {
  errno = 0;
  long n = strtol (yytext, NULL, 10);
  if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
    driver.error (loc, "integer is out of range");
  return yy::calcxx_parser::make_NUMBER (n, loc);
}
{id}       return yy::calcxx_parser::make_IDENTIFIER (yytext, loc);
.          driver.error (loc, "invalid character");
<<EOF>>    return yy::calcxx_parser::make_END (loc);

Здесь yylval вообще не упоминается, и мы возвращаем что-то странное make _ ???функции, которые я не понимаю, где они определены, какие параметры они принимают и что возвращают.

Может кто-нибудь объяснить мне, в чем разница между этими двумя подходами, и, если мне следует использовать второй,краткое объяснение этих таинственных марок _ ???методы?

Заранее спасибо!

1 Ответ

0 голосов
/ 05 июня 2018

Раздел документации, на который вы ссылаетесь, является первым из двух разделов, которые описывают альтернативные API.Было бы лучше начать чтение с , начиная с , где объясняется, что:

Фактический интерфейс с yylex зависит от того, используете ли вы объединения или варианты.

В приведенном вами примере используются варианты, и поэтому используется интерфейс complete symbol , в котором определены методы make_*.(Это не стандартные варианты библиотеки или Boost; они представляют собой простой распознаваемый класс объединения, определяемый инфраструктурой Bison.)

Какой из используемых вами API полностью зависит от вас;у них обоих есть свои преимущества и недостатки.

Существует также третий вариант: собрать как синтаксический анализатор, так и лексер с использованием интерфейсов C.Это не мешает вам использовать типы данных C ++, но вы не можете поместить их непосредственно в стек анализатора;Вы должны использовать указатели, и это делает управление памятью более ручным.(На самом деле, есть также два разных API C: традиционный, в котором анализатор автоматически вызывает сканер, когда ему нужен токен, и интерфейс «push», где сканер вызывает анализатор с каждым токеном.)

...