2016-12-27 14 views
0

私はlex/yaccのcコンパイラを開発しています。 エラーを処理してエラーを解析するために、例外システムハンドラをデプロイします。lexとyaccで簡単なパーサーを作ろう

は実際には "エラーを解析する" メッセージが、これは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];} 
%% 

とyaccファイルである例

is.forどんな問題が処理されます。

%{ 
#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に戻す必要があります。 aeflrst、またはu - レクサーで

  • []はそう[true]|[false]のようなパターンは、単一の文字にマッチし、文字クラスを意味します。

関連する問題