2016-12-27 2 views
0

Je développe un compilateur de lex/yacc c. Afin de gérer les erreurs et d'analyser les erreurs, je veux déployer un gestionnaire de système d'exception.essayer de faire l'analyseur simple dans lex & yacc

En fait, seul un message "parse error" est géré quel que soit le problème is.for exemple

c'est le fichier lex

Boolean   [true]|[false] 
Char  '[\41-\176]' 
Integer  ({Digit)|{Hex}|{Decimal}|{Octal}|{Binary})+ 
String  \"[^"\n]*\" 
Intptr   \"[intptr] 
Charptr  \"[charptr] 
If  \"[if] 
Else  \"[else] 
While  \"[while] 
Var   \var({Space})({Letter}+)({Variables})({Space})\: ({Space}) 
Procedure \"[procedure] 
Return  \"[return] 
Null  null 
Uppercase  [A-Z] 
Letter   [a-zA-Z] 
Notchar  "{Letter}" 
Digit   [0-9] 
Decimal   ([1-9]{Digit})*|[0] 
Hex    0[X|x][0-9A-F]+ 
Octal   [0]([1-7][0-7]*) 
Binary   (0|1)+"b" 
String1   ({Letter}|{Digit}|{Char})* 
Stringerror  \"[^\n]*\" 
VALUE  [|]{Integer}[|] 
LENGTHSTRING [|]{String}[|] 
Enter  [\15]+ 
Space  [ \t\r]* 
Newline   \n 
Type  [{Boolean}|{Integer}|{Var}|{String}] 
Typeptr  {Charptr}|{Intptr} 
Identifier  {Letter}({Letter}|{Digit}"_")+ 
Comment  \/\%({String1}|{Space})*\%\/ 
Variables  (\,{Letter}+)*{Type}\; 
%{ 
%} 
%% 
Boolean  {return BOOLEAN;} 
Integer  {return INTEGER;} 
Digit  {return DIGIT;} 
Char  {return CHAR;} 
Enter  {return ENTER;} 
Space  {return SPACE;} 
Letter  {return LETTER;} 
Newline  {return NEWLINE;} 
Type  {return TYPE;} 
Typeptr  {return TYPEPTR;} 
String  {return STRING;} 
Stringerror {return STRINGERROR;} 
Notchar  {return NOTCHAR;} 
Identifier {return ID;} 
Hex  {return HEX;} 
Binary  {return BINARY;} 
Decimal  {return DECIMAL;} 
Octal  {return OCTAL;} 
Comment  {return COMMENT;} 
Variables {return VARIABLES;} 
If  {return IF;} 
Else  {return ELSE;} 
While  {return WHILE;} 
Var  {return VAR;} 
Procedure {return PROCEDURE;} 
[0-9]+  {return NUM;} 
"=="  {return EQ;} 
"&&"  {return AND;} 
"/"   {return DIVISION;} 
"="   {return ASSIGN;} 
">"   {return GREATER;} 
">="  {return GREATEREQ;} 
"<="  {return LESSEQ;} 
"<"   {return LESS;} 
"-"   {return MINUS;} 
"!"   {return NOT;} 
"!="  {return NOTEQUAL;} 
"||"  {return OR;} 
"|"   {return ABSUOLUT;} 
"+"   {return PLUS;} 
"*"   {return MUL;} 
"&"   {return ADDRESS;} 
"^"   {return DEREFERENCE;} 
"'"   {return SINGLEQUETE;} 
";"   {return SEMICOLON;} 
":"   {return COLUMS;} 
"("   {return LP;} 
")"   {return RP;} 
"}"   {return RB;} 
"{"  {return LB;} 
","   {return COMMA;} 
.  {return yytext[0];} 
%% 

et fichier yacc:

%{ 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
typedef struct node 
{ 
char* token; 
struct node* left; 
struct node* right; 
}node; 
node* mknode(char* token,node* left, node* right); 
void printtree(node* tree); 
#define YYSTYPE struct node* 
%} 
%start s 
%token BOOLEAN STRING STRINGERROR CHAR NOTCHAR IDENTIFIER INTEGER 
%token DIGIT LETTER NEWLINE TYPE TYPEPTR VARIABLES PROCEDURE 
%token HEX BINARY DECIMAL OCTAL 
%token IF ELSE WHILE COMMENT ENTER SPACE VAR 
%token NUM ASSIGN GREATER GREATEREQ LESSEQ LESS MINUS PLUS MUL DIVISION 
%token NOT NOTEQUAL OR ABSUOLUT ADDRESS DEREFERENCE 
%token SINGLEQUETE SEMICOLON COLUMS LP RP RB LB COMMA AND 
%left NUM 
%left AND 
%left DIVISION 
%left ASSIGN 
%left GREATER 
%left GREATEREQ 
%left LESSEQ 
%left LESS 
%left MINUS 
%left NOT 
%left NOTEQUAL 
%left OR 
%left ABSUOLUT 
%left PLUS 
%left MUL 
%left ADDRESS 
%left DEREFERENCE 
%left SINGLEQUETE 
%left SEMICOLON 
%left COLUMS 
%left LP RP RB LB 
%left COMMA 
%% 
s:exp {printf("OK\n"); printtree($1);} 
exp: 
    exp AND exp {$$=mknode("&&",$1,$3);} 
| exp DIVISION exp {$$=mknode("/",$1,$3);} 
| exp ASSIGN exp {$$=mknode("=",$1,$3);} 
| exp GREATER exp {$$=mknode(">",$1,$3);} 
| exp GREATEREQ exp {$$=mknode(">=",$1,$3);} 
| exp LESSEQ exp {$$=mknode("<=",$1,$3);} 
| exp LESS exp {$$=mknode("<",$1,$3);} 
| exp MINUS exp {$$=mknode("-",$1,$3);} 
| exp NOT exp {$$=mknode("!",$1,$3);} 
| exp NOTEQUAL exp {$$=mknode("!=",$1,$3);} 
| exp OR exp {$$=mknode("||",$1,$3);} 
| exp ABSUOLUT exp {$$=mknode("|",$1,$3);} 
| exp PLUS exp {$$=mknode("+",$1,$3);} 
| exp MUL exp {$$=mknode("*",$1,$3);} 
| exp ADDRESS exp {$$=mknode("&",$1,$3);} 
| exp DEREFERENCE exp {$$=mknode("^",$1,$3);} 
| exp SINGLEQUETE exp {$$=mknode("'",$1,$3);} 
| exp SEMICOLON exp {$$=mknode(";",$1,$3);} 
| exp COLUMS exp {$$=mknode(":",$1,$3);} 
| exp LP exp {$$=mknode("(",$1,$3);} 
| exp RP exp {$$=mknode(")",$1,$3);} 
| exp LB exp {$$=mknode("{",$1,$3);} 
| exp RB exp {$$=mknode("}",$1,$3);} 
| exp COMMA exp {$$=mknode(",",$1,$3);} 
| NUM {$$=mknode(yytext,NULL,NULL);} 
%% 
#include "lex.yy.c" 
main() 
{ 
return yyparse(); 
} 
node* mknode(char* token,node* left,node* right) 
{ 
node *newnode=(node*) malloc (sizeof(node)); 
char *newstr=(char*) malloc (sizeof(token)+1); 
strcpy(newstr,token); 
newnode->left=left; 
newnode->right=right; 
newnode->token=newstr; 
return newnode; 
} 
void printtree(node* tree) 
{ 
printf("%s\n",tree->token); 
if(tree->left) 
    printtree(tree->left); 
if(tree->right) 
    printtree(tree->right); 
} 
int yyerror() 
{ 
printf("ERROR\n"); 
return 0; 
} 

i essayer pour compiler ce code et j'ai eu cette erreur et les avertissements: y.tab.c: En

> function ‘yyparse’: y.tab.c:1319:16: warning: implicit declaration of 
> function ‘yylex’ [-Wimplicit-function-declaration] 
>  yychar = yylex(); 
>    ^prt2.y:72:21: error: ‘yytext’ undeclared (first use in this function) | NUM {$$=mknode(yytext,NULL,NULL);} 
>     ^prt2.y:72:21: note: each undeclared identifier is reported only once for each function it appears in y.tab.c:1604:7: 
> warning: implicit declaration of function ‘yyerror’ 
> [-Wimplicit-function-declaration] 
>  yyerror (YY_("syntax error")); 
>  ^prt2.y: At top level: prt2.y:75:1: warning: return type defaults to ‘int’ [-Wimplicit-int] main() 
+0

Découvrez MiniBasic. https://sourceforge.net/projects/minibasic/?source=directory Une fois que vous avez écrit un analyseur de descente récursif à partir de zéro, il devient plus facile de comprendre comment utiliser les outils comme yacc. –

+0

Vous devriez commencer par quelque chose de très petit et créer un test pour chaque entrée. Il y a beaucoup d'erreurs là, par exemple 'Entier ({Chiffre) | {Hex} | {Décimal} | {Octal} | {Binaire}) +' devrait être '{Digit}' et pas '{Digit)' – cpatricio

Répondre

1

problèmes multiples

  • vous ne pouvez pas utiliser yytext dans l'analyseur, seulement dans le lexer. Il TEMPORARILY contient le jeton en cours - une fois que yylex retourne il n'est plus valide. Donc, vous devez faire une copie de la chaîne dans l'action lexer (par exemple, avec strdup) et renvoyer cela dans yylval.

  • [] dans le lexer signifie classe de caractères, donc un modèle comme [true]|[false] correspond à un seul caractère - a, e, f, l, r, s, t ou u.