符号表

列举单词表的方式虽然简单但是不全面,如果在词法分析程序运行时可以构建一个单词表,那么就可以在添加新的单词时不用修改词法分析程序。

下面示例便利用符号表实现,即在词法分析程序运行时从输入文件中读取声明的单词时允许动态的声明单词。声明以词性的名字开始,后面跟着要声明的单词。

添加符号表可以完全的改变词法分析程序,不必在词法分析程为每个要匹配的单词放置独立的模式,只要有一个匹配任意单词的模式,再查阅符号表就能决定所找到的词性。

lex程序ch1-04.l

%{
/*
*带符号表的词法分析程序
*/ enum{
LOOKUP = 0, /*默认——查找而不是定义*/
VERB,
ADJ,
ADV,
NOUN,
PREP,
PRON,
CONJ
}; int state;
int add_word(int type, char *word);
int lookup_word(char *word);
%} %%
\n {state = LOOKUP;} /*行结束,返回到默认状态*/ /*无论何时,行都以保留字的词性名字开始*/
/*定义该类型的单词*/
^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: printf("%s: verb\n",yytext); break;
case ADJ: printf("%s: adj\n",yytext); break;
case ADV: printf("%s: adv\n",yytext); break;
case NOUN: printf("%s: noun\n",yytext); break;
case PREP: printf("%s: prep\n",yytext); break;
case PRON: printf("%s: pron\n",yytext); break;
case CONJ: printf("%s: conj\n",yytext); break;
default:
printf("%s: don't recognize\n",yytext);
break;
}//switch
}//else
}
/*忽略其他的东西*/
%% int main()
{
yylex();
} /*定义一个连接的单词和类型列表*/
struct word{
char *word_name;
int word_type;
struct word *next;
}; struct word *word_list; //first element in word list extern void *malloc(); int add_word(int type, char *word)
{
struct word *wp;
if(lookup_word(word) != LOOKUP)
{
printf("!!! warning : word %s already defined \n ",word);
return 0;
}//if /*单词不在那里,分配一个新的条目并将它连接到列表上*/
wp = (struct word*) malloc (sizeof(struct word)); wp->next = word_list; /*还必须复制单词本身*/
wp->word_name = (char *)malloc(strlen(word)+1);
strcpy(wp->word_name,word);
wp->word_type = type;
word_list = wp;
return 1; /*它被处理过*/
} int lookup_word(char *word)
{
struct word *wp = word_list; /*向下搜索列表以寻找单词*/
for(; wp ; wp = wp->next)
{
if(strcmp(wp->word_name , word) == 0)
return wp->word_type;
}//for
return LOOKUP;
} int yywrap()
{
return 1;
}

运行命令及结果:

程序代码说明:

在上述lex词法分析程序中,add_word()表示在符号表中放置一个新的单词;

lookup_word()表示查询已经输入的单词。

在程序代码中,声明一个变量state,用来记录是在查找单词(状态LOOKUP)还是在声明它们(在这种情况下,state能记住我们正在声明的单词种类)。

无论何时,只要我们看到以词性名字开始的行,就可以将状态设置为声明单词的种类;每次看到\n时就都切换回正常的查找状态。

Lex与Yacc学习(三)之符号表的更多相关文章

  1. Lex与Yacc学习(一)之环境配置篇

    Abstract 在开发程序的过程中经常会遇到文本解析的问题,例如:解析 C 语言源程序,编写 脚本引擎等等,解决这种文本解析的方法有很多,一种方法就是自己手动用 C 或者 C++直接编写解析程序,这 ...

  2. Lex与Yacc学习(九)之Yacc语法

    Yacc语法 本文讨论yacc语法的格式并描述可用的各种特征和选项 yacc语法结构 yacc语法包括三部分:定义段.规则段和用户子例程段 ...定义段... %% ...规则段... %% ...用 ...

  3. Lex与Yacc学习(四)之Lex规范

    Lex规范的结构 lex程序由三部分组成:定义段.规则段和用户子例程序段 ...定义段... %% ...规则段... %% ...用户子例程序段... 这些部分由以两个百分号组成的行分隔开.尽管某一 ...

  4. Lex与Yacc学习(十)之Yacc库

    Yacc库 每个实现都需要有用的例程库,在UNIX系统中,可以通过cc命令行尾端给出-ly标志(或通过其他系统下的等价物)来包含库. 库的内容在不同的实现之间是不同的,但总是包括main()和yyer ...

  5. Lex与Yacc学习(六)之lex & yacc (简单计算器程序) 运行

    词法分析程序ch3-01.l %{ #include "ch3-01.tab.h" extern int yylval; %} %% [0-9]+ { yylval = atoi( ...

  6. Lex与Yacc学习(五)之正则表达式篇

    正则表达式语法 lex模式是由编辑程序和实用程序使用的正则表达式的扩展版本.正则表达式由常规字符(代表它们本身)和元字符(在一种模式中具有特殊含义)组成. 元字符 . . 匹配除了换行符 \n 之外的 ...

  7. Hibernate学习(三)自动建表

    一般情况下有如下两种方法: 1.在配置文件中添加如下配置 <property name="hibernate.hbm2ddl.auto">create</prop ...

  8. Lex与Yacc学习(二)之第一个Lex程序

    用lex识别单词 构建一个识别不同类型英语单词的简单程序.先识别词性(名词,动词等),然后再扩展到处理符合简单英语语法的多个单词的句子. 先列出要识别的一组动词: is    am   are   w ...

  9. Lex与Yacc学习

    http://www.cnblogs.com/shine-yr/p/5214976.html

随机推荐

  1. python学习之j进程和线程:

    每个进程至少有一个线程,python因为每个线程都共用一个GIL全局锁(同时只能运行一个线程),所以不能用多线程(除非重新写C解释器),但是多进程的GIL锁各自独立可多进程. 进程与线程的区别在于一个 ...

  2. “玲珑杯”ACM比赛 Round #4 E -- array DP

    http://www.ifrog.cc/acm/problem/1050?contest=1006&no=4 DP[val]表示以val这个值结尾的等差数列有多少个 DP[val] += DP ...

  3. Scanner-String-StringBuilder-API

    1.能够明确API的使用步骤     1)打开帮助文档     2)点击显示,找到索引,看到输入框     3)你要找谁?在输入框里输入,然后回车     4)看包:java.lang下的类不需 ...

  4. Android GreenDao 深查询 n:m 的关系

    在我的应用程序这样设计的关系:和我想选择至少一个用户作为一个朋友的所有聊天. 基本上,我想要执行以下查询:\ SELECT c.* FROM CHAT c, USER u, UserChats uc ...

  5. block 应用说明

    一.Block定义 Block可以理解为一个函数指针(即它是一个指针,指向某个函数) returnType (^blockName) (parameter list) = ^ (parameter l ...

  6. IOS typedef 函数指针的用法

    代码简化, 促进跨平台开发的目的. typedef 行为有点像 #define 宏,用其实际类型替代同义字. 不同点:typedef 在编译时被解释,因此让编译器来应付超越预处理器能力的文本替换. 用 ...

  7. 洛谷 2299 Mzc和体委的争夺战

    题目背景 mzc与djn第四弹. 题目描述 mzc家很有钱(开玩笑),他家有n个男家丁(做过前三弹的都知道).但如此之多的男家丁吸引来了我们的体委(矮胖小伙),他要来与mzc争夺男家丁. mzc很生气 ...

  8. fluent_python2

    字典和集合 泛映射类型, 继承自collections.abc, Mapping和MutableMapping 标准库里的所有映射类型都是利用 dict 来实现的,因此它们有个共同的限制,即只有可散列 ...

  9. 并查集+思维——X-Plosives

    一.问题描述(题目链接) 有n种化合物,每种化合物由两种元素组成.当几种的化合物数量等于他们所含不同元素的数量时,就会发生爆炸.现在依次给出化合物的组成,当新的化合物与之前的化合物放在一起会发生爆炸时 ...

  10. QT 图形视图框架

    https://blog.csdn.net/qq769651718/article/details/79357936 使用QPushButton.QLabel.QCheckBox等构成GUI的控件或自 ...