2016-12-27 60 views
0

我正在開發lex/yacc c編譯器。 爲了處理故障和解析錯誤,我想部署一個異常系統處理程序。嘗試在lex&yacc中製作簡單的解析器

實際上只是一個 「解析錯誤」 消息處理任何is.for例子問題

這是法文件

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];} 
%% 

和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; 
} 

我嘗試編譯此代碼,我得到了這個錯誤和警告:y.tab.c:在

> 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

查看MiniBasic。 https://sourceforge.net/projects/minibasic/?source=directory一旦您從頭開始編寫遞歸下降解析器,就會更容易理解如何使用yacc等工具。 –

+0

您應該從非常小的東西開始,爲每個輸入創建一個測試。這裏有很多錯誤,例如'Integer({Digit)| {Hex} | {Decimal} | {Octal} | {Binary})+'應該是'{Digit}'而不是'{Digit' – cpatricio

回答

1

多個問題

  • 你不能在解析器使用yytext,只有在詞法分析器。它TEMPORARILY擁有當前的令牌 - 一旦yylex返回它不再有效。因此,您需要在詞法分析器操作中創建一個字符串副本(例如,使用strdup),然後在yylval中返回。

  • 在詞法分析器[]裝置字符類,所以像[true]|[false]的圖案匹配單個字符 - aeflrst,或者u