LEX学习 第二节

接着第一节中的第一个示例,我们扩展第二个示例,将词法分析程序扩展为识别不同的词性。

下面是程序示例:

%{
/*
 * 扩展第一个示例以识别其他的词性
 *
 */
%}

%%
[ \t ]+  /* 忽略空白 */;
is |
am |
are |
were |
was |
be |
being |
been |
do |
does |
did |
will |
would |
should |
can |
could |
has |
had |
go {printf("%s: is a verb",yytext);}

very |
simply |
gently |
quietly |
calmly |
angrily {printf("%s: is an adverb",yytext);}

to |
from |
behind |
above |
below |
between {printf("%s: is a preposition",yytext);}

if |
then |
and |
but |
or {printf("%s: is a conjunction",yytext);}

their |
my |
your |
his |
her |
its {printf("%s : is an adjection",yytext);}

I |
you |
he |
she |
we |
they {printf("%s: is a pronoun",yytext);}

[a-zA-Z]+ {
    printf("%s: do not recognize,mignt be a noun",yytext);
}

.| {ECHO; /* 通常的默认状态 */}

%%

int main()
{
    yylex();
    return 0;
}

int yywrap()
{
    return 1;
}

第二个示例实际上与第一个没有什么不同,仅仅就是列出了比前面更多的单词,原则上可以扩展这个示例为任意多的单词。但是这样感觉有些笨拙,如果是单词比较多的话,就需要将所有的单词都要列出来,如果能够有一个单词表,能够实时的添加新的单词的话,扩展性上就会好很多。下面我们再扩展一下,就是在词法分析程序运行时从输入文件中读取声明的单词时允许动态的声明词性。声明行以词性的名称开始,后面跟着要声明的单词。例如:

声明4个名词和3个动词:

noun dog cat horse cow

verb chew eat lick

该单词表在lex和yacc中就是一个简单的符号表,添加符号表可以完全改变词性语法分析程序,不必在词法分析程序中为每个要匹配的单词放置独立的模式,只要有一个匹配任意单词的模式,再查阅符号表就能决定所找到的词性。由于词性引入了一个声明行,所以他们现在是”保留字“。对于每一个保留字仍然有一个独立的lex模式。还必须添加符号表维护例程。add_word()表示添加单词,lookup_word()表示查询单词。

同时在程序代码中需要一个state变量用来记录是查找单词还是添加单词。无论如何只要我们看到以词性名字开始的行,就可以知道状态为添加单词,每次看到\n的时候,都切换回正常的查找状态。

下面是程序的实现:

%{
    /*
     * 带符号表的单词识别程序
     */
    enum{
        LOOKUP = 0, /* 默认-查找而不是定义 */
        VERB,
        ADJ,
        ADV,
        NOUN,
        PREP,
        PRON,
        CONJ
    };

    int state;

    int add_word(int type,char *word);
    int lookup_word(char *word);
%}

%%

 {state = LOOKUP;} /* 行结束,返回默认状态 */
    /* 无论何时return wp->word_type,行都以保留的词性名字开始 */
    /* 开始定义该类型的单词 */
^verb {state = VERB; }
^adj  {state = ADJ;  }
^adv  {state = ADV;  }
^noun {state = NOUN; }
^prep {state = PREP; }
^pron {state = PRON; }

[a-zA-Z]+ {
    /* 一个标准的单词,定义他或查找它 */
    if(state != LOOKUP){
        /* 定义当前单词 */
        add_word(state,yytext);
    }else{
        switch(lookup_word(yytext)){
            case VERB: printf("%s: verb",yytext); break;
            case ADJ:  printf("%s: adjective",yytext); break;
            case ADV: printf("%s: adverb",yytext); break;
            case NOUN: printf("%s: noun",yytext); break;
            case PREP: printf("%s: preposition",yytext); break;
            case PRON: printf("%s: pronoun",yytext); break;
            case CONJ: printf("%s: conjunction",yytext); break;
            default:
                printf("%s: do not recognize",yytext);
                break;
        }
    }
}
. /* 忽略其他return wp->word_type的东西 */

%%

int main()
{
    yylex();
    return 0;
}

/* 定义一个单词和类型的链表 */
struct word{
    char *word_name;
    int word_type;
    struct word *next;
};

struct word *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",word);
        return 0;
    }

    /* 单词不在那里,分配一个新的条目并将它链接到链表上 */
    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;
    }
    return LOOKUP;
}

int yywrap()
{
    return 1;
}

下面是我的程序的输出结果:

时间: 2024-11-05 06:12:02

LEX学习 第二节的相关文章

Linux学习第二节课(2019.9.7)

昨晚课程由于加班没有参加到上课,第二天补听了课程,再来写博客.第二节课,老刘跟我们第一章讲了如何安装虚拟机,安装linux系统,RPM和YUM仓库各种关系.然后老刘给我们讲一个"灰常恐怖的gui故事"来引入第二章的内容,讲述shell的作用,最后讲述了命令的长格式和短格式以及常用命令的ehco(echo 老刘真帅).date.reboot.poweroff.wget命令.目前还是能跟得上老刘的课程,要继续努力,复习预习,争取早日考过rhce. ---------------------

oracle的学习 第二节:创建数据表

学习内容: A.创建数据库和表空间 B.创建用户和分配权限 C.创建数据表 一.创建数据库和表空间 (一)SQL语言的基本概念 1.概念 高级的结构化查询语言:沟通数据库服务器和客户的重要桥梁. PL/sql语言是结构化的查询语言. 2.分类: 数据定义语言  :create  alter  drop 数据操作语言: insert update delete 数据控制语言:select (二)创建数据库的两种方式 方式一:图形界面: 方式二:create  Datebase命令方法.(常用) 具

2020前端基础知识学习第二节

1. var a = { n: 1 }; var b = a; a.x = a = { n: 2 }; console.log(a); console.log(b); 答案:{ n: 2 },{ n: 1, x: { n: 2 } } 分析:这里最核心的地方就是a.x运算优先级高于=,因为a.x优先级高于=,所以在a还是{ n: 1 }的时候添加了x: { n: 2 }这个属性, 因为前面b = a;使的b和a指向了同一个地址,所以b就是{ n: 1, x: { n: 2 } }.下面有更专业和

python学习第二节

python3中的input与python2中的raw_input一样python2中的input()用户输入的是什么类型,就被定义为什么类型,所以在python2中input()中需要加'' 定义为字符串,否则会以为是变量名,然而没有这个变量名的值,所以会报错. end=' '将print自带的换行符换成空 输出1-10 除了7 1-100的和 找出所有奇数 #求1-2+3-4+5 ... 99的所有数的和 限制用户登录 另 字符串格式操作符2.7print "%s is number %d!

Coursera在线学习---第二节.Octave学习

1)两个矩阵相乘 A*B 2)两个矩阵元素位相乘(A.B矩阵中对应位置的元素相乘) A.*B 3)矩阵A的元素进行平方 A.^2 4)向量或矩阵中的元素求倒数 1./V    或   1./A 5)对数与幂运算 log(V)       exp(v) 即e的v次方 6)求绝对值 abs(v) 7)加减 -V    等于所有元素乘以-1 V+ones(length(v),1)   V向量中所有元素+1 V+1 同上 8)矩阵转置 A'                   (A')'=A 9)求逆矩

C#基础入门学习-第二节-代码注释的使用以及常用技巧

1.在当前解决方案中含有一个项目,如何在添加一个项目? (1)方案1,在解决方案管理器中的解决方案名称上点击鼠标右键,选择增加,选择新建项目,输入项目名称即可 (2)方案2,在VS菜单中选择文件,新建,项目,输入项目名称,解决方案选择,增加到解决方案即可 2.在多个项目中如何运行某个项目? (1)我们在解决方案管理器中查看那个项目文件名是黑色,代表那个是当前的项目,在调试的时候会运行该项目,如果我们想运行其它项目,在其它项目点击右键 设为启动项目即可,或者解决方案,右键属性,单启动项目,选择要启

JPA学习---第二节:JPA开发环境和思想介绍

一.下载相关 jar http://hibernate.org/orm/ 下载 hibernate ,解压 http://www.slf4j.org/download.html 下载 slf4j,解压 http://www.apache.org/dyn/closer.cgi/logging/log4j/2.0.2/apache-log4j-2.0.2-bin.zip 下载 log4j, 解压 二.开发 JPA 依赖的jar hibernate-release-4.3.6.Final\lib\re

Hibernate学习---第二节:hibernate 增、删、改、查

1.增,向数据库中写入数据,代码如下: /** * 数据保存 * 1.save() * 2.persist() */ @Test private void testSave(){ Configuration config = new Configuration().configure(); /** * 获取连接工程场 * 通常对应一个数据库,通常一个应用程序只有一个,再启动的时候创建 * 线程安全 */ /** * buildSessionFactory() 属于 hibernate3 中的方法

Ant学习---第二节:Ant添加文件夹和文件夹集的使用

一.创建 java 项目(Eclipse 中),结构图如下: 1.创建 .java 文件,代码如下: package com.learn.ant; public class HelloWorld { public static void main(String[] args) { for(String arg : args) System.out.println("Hello World" + arg); } } 2.创建 build.xml 文件,代码如下: <?xml ver