2015-04-16 4 views
0

Я новичок в программах lex и yacc. Я пытаюсь написать программу yacc, которая принимает в качестве входного выражения арифметическое выражение и дает постфиксную нотацию в качестве вывода. Грамматика, которую я использую: exp: exp + термин | exp - term | термин термин: термин * фактор | термин/коэффициент | фактор фактора: Numyacc программа для преобразования арифметического выражения в постфикс

Это мой закон Код:

%{ 
extern int yylval; 
#include "y.tab.h" 
%} 

%% 

[0-9]+ {yylval = atoi(yytext);return INTEGER;} 
[ \t\n]  /* skip whitespace */ 
. {return *yytext;} 
%% 

int yywrap(void) { 
return 1; 
} 

Это моя Yacc программа:

%{ 
#include<stdio.h> 
%} 
%token INTEGER 
%left '+' '-' 
%left '*' '/' 
%% 

E: E '+' T {printf("+");} 
    | E '-' T {printf("-");} 
    | T  
    ; 

T: T '*' F {printf("*");} 
    | T '/' F {printf("/");} 
    | F 
    ;  

F: '(' E ')' 
    | INTEGER {printf("%d",yylval);} 
    ; 

%% 

int main(){ 
    yyparse(); 
} 

int yyerror (char *msg) { 
    return printf ("error YACC: %s\n", msg); 
} 

Но этот код компиляция correctly.But вывода не является правильным, если «+ 'или' - 'используются в выражении Например, вход: 2 + 3 вывод: 23 (вместо 23+) Пожалуйста, помогите мне узнать об ошибке в коде. Спасибо.

+0

Ваша грамматика принимает только одно выражение. Если вы закрываете ввод после выражения, он будет печатать правильно. – rici

+0

Также обратите внимание, что вам не нужен T-терминал, потому что вы указываете то же самое с использованием приоритета оператора. – user3344003

ответ

2

Если вы вводите 2 + 3, и не более того, анализатор не знает, что вы намеревались это быть полным выражением. Это может быть начало выражения 2 + 3 * 4. Поэтому синер сидит там и ждет больше ввода.

Попробуйте добавить к вашей грамматике маркер конца выражения, например точку с запятой.

-1

Инфиксные и постфиксные обозначения являются результатом ходьбы AST в разных порядках. Поэтому вам нужно начать с создания АСТ, чтобы что-то ходить в выбранном порядке после АСТ завершен.

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

%start start 

%% 

start: E { walk_post_order($1); } 
+2

Это действительно неправда. Действия, отправленные OP, достаточны для того, чтобы ходить по дереву разбора. Не всегда необходимо строить AST: компиляторы производства были построены без них. – EJP

0

\ n {return (0); }

просто добавьте эту строку в раздел правил вашего кода в файл lex :)

+3

Почему? Немного объяснений было бы полезно. – showdev