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()
の
MiniBasicをご覧ください。 https://sourceforge.net/projects/minibasic/?source=directory再帰的降下パーサーを一度書き直せば、yaccのようなツールの使い方を理解しやすくなります。 –
非常に小さいものから始め、各入力に対してテストを作成する必要があります。例えば、 'Integer({Digit)| {Hex} | {Decimal} | {Octal} | {Binary})+' '{Digit}'ではなく '{Digit} 'でなければなりません。 – cpatricio