Какова цель типов / объединения в yaccs и lex? - PullRequest
0 голосов
/ 16 июня 2019

Я изучаю yacc и lex с помощью некоторого учебного кода, который создает парсер, позволяющий вам делать следующее: 1. Назначьте целые числа для однобуквенных переменных 2. Делайте сложение и вычитание, используя числа и переменные 3. Выведите значение переменной

В учебнике говорится, что для разрешения присвоения чисел переменным нам необходим файл lex, чтобы возвращать два разных типа значений, которые затем объявляются в объединении в файле yacc.

Я понятия не имею, почему это даже необходимо. Я на самом деле пошел дальше и изменил учебный код, чтобы он работал без использования types / union и работал просто отлично (я просто использовал значение NAME, чтобы установить индекс в symtbl для целого числа, которому он назначен). Так что меня смущает то, зачем вообще использовать типы и объединение? Ниже приведен код из учебника.

%{
...

int symtbl[26];
bool issym[26];
%}

%union {
  int rvalue; /* value of evaluated expression */
  int lvalue; /* index into symtbl for variable name */
}

%token <rvalue> NUMBER
%token <lvalue> NAME 

%type <rvalue> expression
%type <rvalue> const

%%
statement_list : statement '\n'
      | statement_list statement '\n'
      ;

statement: NAME '=' expression { symtbl[$1] = $3; issym[$1] = true; }
      | expression  { printf("%d\n", $1); }
      ;

expression: expression '+' const { $$ = $1 + $3; }
      | expression '-' const { $$ = $1 - $3; }
      | const { $$ = $1; }
      ;

const: NUMBER { $$ = $1; }
     | NAME 
       { 
          if (issym[$1]) { $$ = symtbl[$1]; } 
          else { fprintf(stderr, "Error: variable %c not previously defined\n", $1+'a'); exit(1); }
       }
     ;
%%

Итак, мой вопрос: зачем нам нужны типы rvalue и lvalue? Зачем ставить это в союз? Также зачем объявлять правило как определенный тип?

...