Я экспериментирую с lex и yacc и столкнулся со странной проблемой, но я думаю, что было бы лучше показать вам мой код, прежде чем подробно описать проблему. Это мой лексер:
%{
#include <stdlib.h>
#include <string.h>
#include "y.tab.h"
void yyerror(char *);
%}
%%
[a-zA-Z]+ {
yylval.strV = yytext;
return ID;
}
[0-9]+ {
yylval.intV = atoi(yytext);
return INTEGER;
}
[\n] { return *yytext; }
[ \t] ;
. yyerror("invalid character");
%%
int yywrap(void) {
return 1;
}
Это мой парсер:
%{
#include <stdio.h>
int yydebug=1;
void prompt();
void yyerror(char *);
int yylex(void);
%}
%union {
int intV;
char *strV;
}
%token INTEGER ID
%%
program: program statement EOF { prompt(); }
| program EOF { prompt(); }
| { prompt(); }
;
args: /* empty */
| args ID { printf(":%s ", $<strV>2); }
;
statement: ID args { printf("%s", $<strV>1); }
| INTEGER { printf("%d", $<intV>1); }
;
EOF: '\n'
%%
void yyerror(char *s) {
fprintf(stderr, "%s\n", s);
}
void prompt() {
printf("> ");
}
int main(void) {
yyparse();
return 0;
}
Очень простой язык, состоящий не более чем из строк и целых чисел и базового REPL. Теперь вы заметите в синтаксическом анализаторе, что args выводятся с начальным двоеточием, при этом предполагается, что в сочетании с первым шаблоном правила оператора взаимодействие с REPL будет выглядеть примерно так:
> aaa aa a
:aa :a aaa>
Однако взаимодействие таково:
> aaa aa a
:aa :a aaa aa aa
>
Почему идентификатор токена в следующем правиле
statement: ID args { printf("%s", $<strV>1); }
| INTEGER { printf("%d", $<intV>1); }
;
есть семантическое значение всей входной строки, включая перевод строки? Как переработать мою грамматику так, чтобы взаимодействие, которое я задумал?