出自:lex和yacc(第二版)例子,
文件1:
[root@localhost ~/test/flex_bison/flex/ch1-05]
# cat test1.l
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test1.tab.h"
#define LOOKUP (0)
int state;
int lookup_word(char *word);
int add_word(int type, char *word);
%}
%%
\n {state = LOOKUP;}
\.\n {
state = LOOKUP;
return 0; /*meaning the sentence end*/
}
^verb {state = VERB;}
^adj {state = ADJ;}
^adv {state = ADV;}
^noun {state = NOUN;}
^prep {state = PREP;}
^pron {state = PRON;}
^conj {state = CONJ;}
[a-zA-Z]+ {
if (state != LOOKUP) {
add_word(state, yytext);
} else {
switch (lookup_word(yytext)) {
case VERB: return VERB;
case ADJ: return ADJ;
case ADV: return ADV;
case NOUN: return NOUN;
case PREP: return PREP;
case PRON: return PRON;
case CONJ: return CONJ;
default: printf("%s: dont recognize\n", yytext);
}
}
}
. /*ignore anything*/ ;
%%
#if 0
int main(int argc, char *const argv[])
{
yylex();
return 0;
}
#endif
struct word {
char *word_name;
int word_type;
struct word *next;
};
struct word *word_list = NULL;
extern void *malloc();
int
lookup_word(char *word)
{
struct word *wp = NULL;
for (wp = word_list; wp; wp = wp->next) {
if (0 == strcmp(wp->word_name, word)) {
return wp->word_type;
}
}
return LOOKUP;
}
int
add_word(int type, char *word)
{
struct word *wp = NULL;
if (LOOKUP != lookup_word(word)) {
printf("%s has already existed\n", word);
return 0;
}
printf("add %s[type: %d]\n", word, type);
wp = (struct word *)malloc(sizeof(struct word));
memset(wp, 0, sizeof(struct word));
wp->word_name = (char *)malloc(strlen(word) + 1);
memset(wp->word_name, 0, strlen(word) + 1);
strcpy(wp->word_name, word);
wp->word_type = type;
wp->next = word_list;
word_list = wp;
return 1;
}
文件2:
[root@localhost ~/test/flex_bison/flex/ch1-05]
# cat test1.y
%{
#include <stdio.h>
void yyerror(char *s);
%}
%token NOUN PRON VERB ADV ADJ PREP CONJ
%%
sentence: subject VERB object {printf("Sentence is valid.\n");}
;
subject: NOUN
| PRON
;
object: NOUN
;
%%
extern FILE *yyin;
int main(int argc, char *const argv[])
{
do {
yyparse();
} while(!feof(yyin));
return 0;
}
void
yyerror(char *s)
{
fprintf(stderr, "Error: %s!!\n", s);
}
编译:
[root@localhost ~/test/flex_bison/flex/ch1-05]
# flex *.l; bison -d *.y; gcc *.c -o test1 -lfl
[root@localhost ~/test/flex_bison/flex/ch1-05]
# ls
lex.yy.c test1 test1.l test1.tab.c test1.tab.h test1.y
执行:
[root@localhost ~/test/flex_bison/flex/ch1-05]
# ./test1
verb is be
add is[type: 260]
add be[type: 260]
noun book
add book[type: 258]
book is book
Sentence is valid.
book is book .
Sentence is valid.
*.y文件中
%%和%%之间的为规则段,每条规则都有“:”操作左侧的一个名字、右侧的符号列表和动作代码,以及指示规则结尾的分号组成。
默认情况下,第一条规则是最高级别的规则。
当词法分析程序报告输入结束时,词法分析程序会返回到他的调用程序中,在这里,是主程序。
随后,对yyparse()的调用重置状态,并在此开始处理。因为sentence是最高层次的符号,所以整个输入必须匹配sentence。
如果看到输入标记的“subject VERB object”列表,将打印一条消息“Sentence is valid.”;如果看到“subject subject",语法分析程序将调用yyerror()(用户的子程序中提供),将打印”Error: syntax error!!“。yyparse()在发现错误后,返回到调用程序。
*.y的第三部分,即用户子程序段,包含任意C代码,并且被逐字地复制到最终的语法分析程序中。