Next: Notes on the Implementation, Previous: The Database Language, Up: Another Example of Flex and Bison
上の節で、 小規模な言語について説明しました。 次にそれを実装してみることにしましょう。 以下のファイルがこれを実現します。
注:これはあくまでも1つの例として見てください。 特に文法の部分は、 英語のパース処理としてはあまり良い例ではありません。
以下はBisonのファイルです。
%union
の部分、
および、
yylval
にアクセスするために$$
と$
nを使う方法に注目してください。
/* Cコードはファイルの先頭で提供する */ %{ #include <stdio.h> #include <string.h> extern int yylexlinenum; /* lex.yy.cに存在する */ extern char *yytext; /* カレント・トークン */ %} /* キーワードと予約語がここから始まる */ %union{ /* これはデータの共用体 */ char name[128]; /* 名前 */ } /*------------- 予約語 ------------------*/ %token PERIOD %token NEWLINE %token POSITIONAL %token VERB %token ADVERB %token PROPER_NOUN %token NOUN %token DECLARATIVE %token CONDITIONAL %type <name> declarative %type <name> verb_phrase %type <name> noun_phrase %type <name> position_phrase %type <name> adverb %type <name> POSITIONAL VERB ADVERB PROPER_NOUN %type <name> NOUN DECLARATIVE CONDITIONAL %% sentence_list : sentence | sentence_list NEWLINE sentence ; sentence : verb_phrase noun_phrase position_phrase adverb period { printf("I understand that sentence.\n"); printf("VP = %s \n",$1); printf("NP = %s \n",$2); printf("PP = %s \n",$3); printf("AD = %s \n",$4); } | { yyerror("That's a strange sentence!"); } ; position_phrase : POSITIONAL declarative PROPER_NOUN { sprintf($$,"%s %s %s",$1,$2,$3); } | /* 空 */ { strcpy($$,""); } ; verb_phrase : VERB { strcpy($$,$1); strcat($$," "); } | adverb VERB { sprintf($$,"%s %s",$1,$2); } ; adverb : ADVERB { strcpy($$,$1); } | /* 空 */ { strcpy($$,""); } ; noun_phrase : DECLARATIVE NOUN { sprintf($$,"%s %s",$1,$2); } | CONDITIONAL declarative NOUN { sprintf($$,"%s %s %s",$1,$2,$3); } | NOUN { strcpy($$,$1); strcat($$," "); } ; declarative : DECLARATIVE { strcpy($$,$1); } | /* 空 */ { strcpy($$,""); } ; period : /* 空 */ | PERIOD ; %% /* main()およびyyerror()関数を提供する */ void main(int argc, char **argv) { yyparse(); /* ファイルをパースする */ } int yyerror(char *message) { extern FILE *yyout; fprintf(yyout,"\nError at line %5d. (%s) \n", yylexlinenum,message); }
以下はFlexのファイルです。 文字列が渡される方法に注意してください。 これは最適化された方法ではありませんが、 最も理解しやすい方法です。
%{ #include <stdio.h> #include <string.h> #include "y.tab.h" /* これはBisonにより生成される */ #define TRUE 1 #define FALSE 0 #define copy_and_return(token_type) \ { \ strcpy(yylval.name,yytext);\ return(token_type); \ } int yylexlinenum = 0; /* 行数カウント用 */ %} %% /* 字句解析ルールがここから始まる */ MEN|WOMEN|STOCKS|TREES copy_and_return(NOUN) MISTAKES|GNUS|EMPLOYEES copy_and_return(NOUN) LOSERS|USERS|CARS|WINDOWS copy_and_return(NOUN) DATABASE|NETWORK|FSF|GNU copy_and_return(PROPER_NOUN) COMPANY|HOUSE|OFFICE|LPF copy_and_return(PROPER_NOUN) THE|THIS|THAT|THOSE copy_and_return(DECLARATIVE) ALL|FIRST|LAST copy_and_return(CONDITIONAL) FIND|SEARCH|SORT|ERASE|KILL copy_and_return(VERB) ADD|REMOVE|DELETE|PRINT copy_and_return(VERB) QUICKLY|SLOWLY|CAREFULLY copy_and_return(ADVERB) IN|AT|ON|AROUND|INSIDE|ON copy_and_return(POSITIONAL) "." return(PERIOD); "\n" yylexlinenum++; return(NEWLINE); . %%
これらのファイルは、 以下を実行することでコンパイルできます。
% bison -d front.y % flex -I front.lex % cc -o front alloca.c front.tab.c lex.yy.c
または、 この例のソースが手元にあれば、 examplesサブディレクトリにおいて‘make front’を実行することでもコンパイルできます。
注:Bisonパーサはalloca.cというファイルを必要とします。
このファイルはexamplesサブディレクトリにあります。
Bisonの代わりにyacc
を使うのであれば、
このファイルは必要ありません。