简单的c语言实现词法分析器

c语言词法分析器

任务1:识别小型语言所有单词的词法分析程序设计

源程序设计语言 G[程序]

程序→变量说明BEGIN 语句表 END.

变量说明→VAR变量表:类型;|空

变量表→变量表,变量|变量

类型→INTEGER

语句表→语句 | 语句;语句表

语句→赋值语句|条件语句|WHILE语句|复合语句

赋值语句→变量:=算术表达式

条件语句→IF关系表达式THEN语句ELSE语句

WHILE语句→WHILE关系表达式DO语句

复合语句→BEGIN语句表END

算术表达式→项|算术表达式+项|算术表达式-项

项→因式|项*因式|项/因式

因式→变量|整数|(算术表达式)

关系表达式→算术表达式关系符算术表达式

变量→标识符

标识符→标识符字母|标识符数字|字母

整数→0|非零数字泛整数

泛整数→数字|数字泛整数|ε

关系符→|=|==||=|

字母

→A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z

非零数字→1|2|3|4|5|6|7|8|9

数字→非零数字|0

空→

要求和提示:

词法分析阶段,可以打开任意位置和名称的源文件进行词法分析,可以进行非法字符和数字后边跟字母的错误判断,如果没有错误则提示“词法分析正确完成!”,并且可以选择输出token.txt(token文件)string.txt(符号表)两个文件;

1.词法分析程序的主要任务如下:

① 组织源程序的输入,识别出源程序中的各个基本语法单位(也称为单词或语法符号),按规则转换成二元式的形式;

② 删除无用的空白字符、回车符、及其它非实质性符号;

③ 删除注解行;

④ 为后面的语法和语义分析提供二元式链表;

单词 编码 单词 编码

标识符 1 15

正整数 2 = 16

BEGIN 3 17

END 4 = 18

IF 5 19

THEN 6 == 20

ELSE 7 ; 21

WHILE 8 . 22

DO 9 := 23

INTEGER 10 , 24

+ 11 ( 25

– 12 ) 26

* 13

/ 14

1) 对标识符的长度控制在8个字符(包括8个)以内,超过的做截断处理;

2) 数字不大于65535,否则报错;

3) 能跳过源程序中的空白格:两个单词之间的任何空格,制表符,回车,换行都是白空格,除了用来分隔单词以外,没有意义;

4) 能跳过注释:

a) 接连出现的/*到下一次接连出现的*/之间的任何文字都是注释(多行);

b) 从某行接连出现的//到该行的结尾的任何文字都是注释(单行)。

3.怎样编写词法分析程序:

1) 预处理:把源文件一个字符一个字符的读入词法分析程序设置的输入字符结构体数组中(输入缓冲区),读入过程要删除注释,删除多余的白空格;

2) 从源程序字符数组中获得单词, 编码为二元式.:

二元式采用结构体数组存储, 把单词类型和词元记录下来。

分解单词的方法:

1) Case多路转换语句根据单词的特点直接编写;

2) 通过描述单词的正规文法得到相应的有穷自动机,通过case多路转换语句完成有穷自动机的处理流程。

3.编写词法分析程序要注意的问题:

1) 检查词法是否有错误

检查是否有非法字符:如 @, , !

检查标志符和数字是否满足限制条件

检查注释符号是否配对

2) 符分隔单词

能够区分两个单词的符号为界符

有些界符不是单词:如白空格

有些界符仅仅用来分隔:如;

有些界符本身还是源程序不可缺少的单词,如(, ), +, /, 等等

有些界符包含两个字符:如, =等等

3) 输出词法错误

如果有错误,需要报告词法错误的原因。并且要能够越过错误,分解下一个单词,直到源程序结束。

4) 输出的二元式流保存在二元式结构体数组中。

简单的c语言实现词法分析器

编译原理课程设计-词法分析器设计(C语言)

#include “stdio.h”                  /*定义I/O库所用的某些宏和变量*/

#include “string.h”                 /*定义字符串库函数*/

#include “conio.h”                  /*提供有关屏幕窗口操作函数*/

#include “ctype.h”                  /*分类函数*/

char prog[80]={‘\0’},

token[8];                     /*存放构成单词符号的字符串*/

char ch;

int syn,                           /*存放单词字符的种别码*/

n,

sum,                           /*存放整数型单词*/

m,p;                           /*p是缓冲区prog的指针,m是token的指针*/

char *rwtab[6]={“begin”,”if”,”then”,”while”,”do”,”end”};

void scaner(){

m=0;

sum=0;

for(n=0;n8;n++)

token[n]=’\0′;

ch=prog[p++];

while(ch==’ ‘)

ch=prog[p++];

if(isalpha(ch))    /*ch为字母字符*/{

while(isalpha(ch)||isdigit(ch))    /*ch 为字母字符或者数字字符*/{

token[m++]=ch;

ch=prog[p++];}

token[m++]=’\0′;

ch=prog[p–];

syn=10;

for(n=0;n6;n++)

if(strcmp(token,rwtab[n])==0)    /*字符串的比较*/{

syn=n+1;

break;}}

else

if(isdigit(ch))    /*ch是数字字符*/{

while(isdigit(ch))    /*ch是数字字符*/{

sum=sum*10+ch-‘0’;

ch=prog[p++];}

ch=prog[p–];

syn=11;}

else

switch(ch){

case”:m=0;token[m++]=ch;ch=prog[p++];

if(ch==”){

syn=21;

token[m++]=ch;}

else if(ch==’=’){

syn=22;

token[m++]=ch;}

else{

syn=20;

ch=prog[p–];}

break;

case”:m=0;token[m++]=ch;ch=prog[p++];

if(ch==’=’){

syn=24;

token[m++]=ch;}

else{

syn=23;

ch=prog[p–];}

break;

case’:’:m=0;token[m++]=ch;ch=prog[p++];

if(ch==’=’){

syn=18;

token[m++]=ch;}

else{

syn=17;

ch=prog[p–];}

break;

case’+’:syn=13;token[0]=ch;break;

case’-‘:syn=14;token[0]=ch;break;

case’*’:syn=15;token[0]=ch;break;

case’/’:syn=16;token[0]=ch;break;

case’=’:syn=25;token[0]=ch;break;

case’;’:syn=26;token[0]=ch;break;

case'(‘:syn=27;token[0]=ch;break;

case’)’:syn=28;token[0]=ch;break;

case’#’:syn=0;token[0]=ch;break;

default:syn=-1;}}

main()

{

printf(“\n\nThe significance of the figures:\n”

“1.figures 1 to 6 said Keyword\n”

“2.figures 10 and 11 said Other indicators\n”

“3.figures 13 to 28 said Operators\n”);

p=0;

printf(“\nplease input string:\n”);

do {

ch=getchar();

prog[p++]=ch;

}while(ch!=’#’);

p=0;

do{

scaner();

switch(syn){

case 11: printf(“(%d,%d)\n”,syn,sum);break;

case -1: printf(“\n ERROR;\n”);break;

default: printf(“(%d,%s)\n”,syn,token);

}

}while(syn!=0);

getch();

}

程序测试结果

对源程序begin x:=9: if x9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下图5-1所示:

具体的你在修改修改吧

C语言的语法分析器

先做个LL(1)或者LALR的语法分析器,然后先把教材上的几个LL(1)的例子调通过。然后网上有C语言子集的文法,有人做了转成大小写这样的表述。通过那个的测试就差不多了。。。。其实做语法分析也没多大用

编译器的难点在于语法制导、代码优化之类的,真要做C语言的完整编译器,普通的学生都几乎不可能实现。。。。就不多说了

你可以动手开始做了

如果你有较强的程序设计能力,做个漂亮的LR(1)分析器还是可以的,实在不会就做SLR(1)这样的分析器,如果程序设计能力比较差,建议先做LL(1),那个比较好做。码字不易,望采纳!

简易C语言词法分析器的设计与实现。求源代码

这个是编译原理的课程设计吧, 做词法分析这个题目算是最简单的了

只需输入合法词的正则表达式,就可以输出一个确定有限状态自动机(DFA),而DFA的表现形式,往往是一张分析表。

有了词法分析器的自动生成器,则可以避免繁琐的单词识别程序,直接对照分析表即可得出yes or no,

c语言的词法分析器

任务1:识别小型语言所有单词的词法分析程序设计

源程序设计语言

G[程序]

程序→变量说明BEGIN

语句表

END.

变量说明→VAR变量表:类型;|空

变量表→变量表,变量|变量

类型→INTEGER

语句表→语句

|

语句;语句表

语句→赋值语句|条件语句|WHILE语句|复合语句

赋值语句→变量:=算术表达式

条件语句→IF关系表达式THEN语句ELSE语句

WHILE语句→WHILE关系表达式DO语句

复合语句→BEGIN语句表END

算术表达式→项|算术表达式+项|算术表达式-项

项→因式|项*因式|项/因式

因式→变量|整数|(算术表达式)

关系表达式→算术表达式关系符算术表达式

变量→标识符

标识符→标识符字母|标识符数字|字母

整数→0|非零数字泛整数

泛整数→数字|数字泛整数|ε

关系符→|=|==||=|

字母

→A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z

非零数字→1|2|3|4|5|6|7|8|9

数字→非零数字|0

空→

要求和提示:

词法分析阶段,可以打开任意位置和名称的源文件进行词法分析,可以进行非法字符和数字后边跟字母的错误判断,如果没有错误则提示“词法分析正确完成!”,并且可以选择输出token.txt(token文件)string.txt(符号表)两个文件;

1.词法分析程序的主要任务如下:

组织源程序的输入,识别出源程序中的各个基本语法单位(也称为单词或语法符号),按规则转换成二元式的形式;

删除无用的空白字符、回车符、及其它非实质性符号;

删除注解行;

为后面的语法和语义分析提供二元式链表;

单词

编码

单词

编码

标识符

1

15

正整数

2

=

16

BEGIN

3

17

END

4

=

18

IF

5

19

THEN

6

==

20

ELSE

7

21

WHILE

8

22

DO

9

:=

23

INTEGER

10

24

+

11

(

25

12

26

*

13

/

14

1)

对标识符的长度控制在8个字符(包括8个)以内,超过的做截断处理;

2)

数字不大于65535,否则报错;

3)

能跳过源程序中的空白格:两个单词之间的任何空格,制表符,回车,换行都是白空格,除了用来分隔单词以外,没有意义;

4)

能跳过注释:

a)

接连出现的/*到下一次接连出现的*/之间的任何文字都是注释(多行);

b)

从某行接连出现的//到该行的结尾的任何文字都是注释(单行)。

3.怎样编写词法分析程序:

1)

预处理:把源文件一个字符一个字符的读入词法分析程序设置的输入字符结构体数组中(输入缓冲区),读入过程要删除注释,删除多余的白空格;

2)

从源程序字符数组中获得单词,

编码为二元式.:

二元式采用结构体数组存储,

把单词类型和词元记录下来。

分解单词的方法:

1)

Case多路转换语句根据单词的特点直接编写;

2)

通过描述单词的正规文法得到相应的有穷自动机,通过case多路转换语句完成有穷自动机的处理流程。

3.编写词法分析程序要注意的问题:

1)

检查词法是否有错误

检查是否有非法字符:如

@,

,

!

检查标志符和数字是否满足限制条件

检查注释符号是否配对

2)

符分隔单词

能够区分两个单词的符号为界符

有些界符不是单词:如白空格

有些界符仅仅用来分隔:如;

有些界符本身还是源程序不可缺少的单词,如(,

),

+,

/,

等等

有些界符包含两个字符:如,

=等等

3)

输出词法错误

如果有错误,需要报告词法错误的原因。并且要能够越过错误,分解下一个单词,直到源程序结束。

4)

输出的二元式流保存在二元式结构体数组中。

怎么用c语言编一个词法分析器

简而言之就是先画一个状态图,然后根据图来编码就行

一个简单的xml的词法分析器供参考

#include

stdio.h

#include

stdlib.h

#include

string.h

typedef

struct

{

char

*p;

int

len;

}

xml_Text;

typedef

enum

{

xml_tt_U,

/*

Unknow

*/

xml_tt_H,

/*

Head

?xxx?*/

xml_tt_E,

/*

End

/xxx

*/

xml_tt_B,

/*

Begin

xxx

*/

xml_tt_BE,

/*

Begin

End

xxx/

*/

xml_tt_T

/*

Text

xxx

*/

}

xml_TokenType;

typedef

struct

{

xml_Text

text;

xml_TokenType

type;

}

xml_Token;

int

xml_initText(xml_Text

*pText,

char

*s)

{

pText-p

=

s;

pText-len

=

strlen(s);

return

0;

}

int

xml_initToken(xml_Token

*pToken,

xml_Text

*pText)

{

pToken-text.p

=

pText-p;

pToken-text.len

=

0;

pToken-type

=

xml_tt_U;

return

0;

}

int

xml_print(xml_Text

*pText)

{

int

i;

for

(i

=

0;

i

pText-len;

i++)

{

putchar(pText-p[i]);

}

return

0;

}

int

xml_println(xml_Text

*pText)

{

xml_print(pText);

putchar(‘\n’);

return

0;

}

int

xml_getToken(xml_Text

*pText,

xml_Token

*pToken)

{

char

*start

=

pToken-text.p

+

pToken-text.len;

char

*p

=

start;

char

*end

=

pText-p

+

pText-len;

int

state

=

0;

pToken-text.p

=

p;

pToken-type

=

xml_tt_U;

for

(;

p

end;

p++)

{

switch(state)

{

case

0:

switch(*p)

{

case

”:

state

=

1;

break;

default:

state

=

7;

break;

}

break;

case

1:

switch(*p)

{

case

‘?’:

state

=

2;

break;

case

‘/’:

state

=

4;

break;

default:

state

=

5;

break;

}

break;

case

2:

switch(*p)

{

case

‘?’:

state

=

3;

break;

default:

state

=

2;

break;

}

break;

case

3:

switch(*p)

{

case

”:

pToken-text.len

=

p

start

+

1;

pToken-type

=

xml_tt_H;

return

1;

default:

state

=

-1;

break;

}

break;

case

4:

switch(*p)

{

case

”:

pToken-text.len

=

p

start

+

1;

pToken-type

=

xml_tt_E;

return

1;

default:

state

=

4;

break;

}

break;

case

5:

switch(*p)

{

case

”:

pToken-text.len

=

p

start

+

1;

pToken-type

=

xml_tt_B;

return

1;

case

‘/’:

state

=

6;

break;

default:

state

=

5;

break;

}

break;

case

6:

switch(*p)

{

case

”:

pToken-text.len

=

p

start

+

1;

pToken-type

=

xml_tt_BE;

return

1;

default:

state

=

-1;

break;

}

break;

case

7:

switch(*p)

{

case

”:

p–;

pToken-text.len

=

p

start

+

1;

pToken-type

=

xml_tt_T;

return

1;

default:

state

=

7;

break;

}

break;

default:

pToken-text.len

=

p

start

+

1;

pToken-type

=

xml_tt_T;

return

1;

}

}

return

0;

}

int

main()

{

int

ret

=

0;

xml_Text

xml;

xml_initText(xml,

“?xml?root

ss

hahahoho/haha/root”);

xml_Token

token;

xml_initToken(token,

xml);

ret

=

xml_getToken(xml,

token);

printf(“ret=%d;text=”,ret);

xml_print(token.text);

printf(“;type=%d;\n\n”,

token.type);

ret

=

xml_getToken(xml,

token);

printf(“ret=%d;text=”,ret);

xml_print(token.text);

printf(“;type=%d;\n\n”,

token.type);

ret

=

xml_getToken(xml,

token);

printf(“ret=%d;text=”,ret);

xml_print(token.text);

printf(“;type=%d;\n\n”,

token.type);

ret

=

xml_getToken(xml,

token);

printf(“ret=%d;text=”,ret);

xml_print(token.text);

printf(“;type=%d;\n\n”,

token.type);

ret

=

xml_getToken(xml,

token);

printf(“ret=%d;text=”,ret);

xml_print(token.text);

printf(“;type=%d;\n\n”,

token.type);

ret

=

xml_getToken(xml,

token);

printf(“ret=%d;text=”,ret);

xml_print(token.text);

printf(“;type=%d;\n\n”,

token.type);

ret

=

xml_getToken(xml,

token);

printf(“ret=%d;text=”,ret);

xml_print(token.text);

printf(“;type=%d;\n\n”,

token.type);

return

0;

}

本文来自投稿,不代表【】观点,发布者:【

本文地址: ,如若转载,请注明出处!

举报投诉邮箱:253000106@qq.com

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2024年3月27日 11:59:51
下一篇 2024年3月27日 12:06:16

相关推荐

  • c语言中判断函数的类型,c语言函数值的类型怎么判断

    在c语言中用什么函数判定一个变量的类型 c语言没有检查变量类型的函数,在C语言中定义的变量,只是根据变量类型来分配默认的存储空间大小,而不记录空间中存储的具体的值的类型。比如定义的字符类型可以当整形来用,可以直接在上面加减一个数值。 变量是int型的还是char型,是由声明决定的。函数调用时参数类型错,你编译时就通不过呀。unsigned char 可以当无…

    2024年5月18日
    3600
  • xy》zc语言,xyc语言

    怎么用C语言编写这样的问题“输入两个整型变量XY,编写程序和它们的最… 可以使用以下三个方法实现:方法一:【中间变量】通过设置一个变量交换两个值。 输入部分。用getchar循环读入字符,当读入值为换行\n时退出循环。2 统计部分。对每个输入的字符进行判断,如果为数字字符,则累加。3 输出部分。退出输入循环后,输出结果值。 前面声明变量的时候类型…

    2024年5月18日
    4100
  • c语言常用字符串函数,c语言字符串函数

    C语言常用的函数有哪些 1、max函数 用于求数组中的最大元素。暂时用到的语法形式有以下3种:C = max(A);C = max(A, B);C = max(A, [], dim);描述:C = max(A)返回数组不同维度的最大元素。 2、在 C 语言中,常用的输入输出函数包括以下几个: `printf()` 函数:用于输出信息到控制台或者文件,可以输出…

    2024年5月18日
    3900
  • c语言输出众数,c语言怎么输出整个数组

    如何用c语言求众数 先将数组a[N]排序(增序、降序都可以)从a[i++]开始统计,若相等则计数器b[j++],如此重复。 算法很多。大致思路如下:定义数据范围:如0-100,定义数组1:int a[101]//标保证任何数据都可以容纳,并且初始化为0。定义数组2:int data[n] //待处理数组,自己初始化。 给一个数组,然后依次读取输入数据,并存到…

    2024年5月18日
    4200
  • c语言boolean,C语言bool的用法

    bool在c语言中是什么意思? 布尔型(bool)变量的值只有 真 (true) 和假 (false)。布尔型变量可用于逻辑表达式,也就是“或”“与”“非”之类的逻辑运算和大于小于之类的关系运算,逻辑表达式运算结果为真或为假。 在C语言中,没有bool这种类型,但是在C++中,把bool当做一种基本的数据类型。在C语言中,当我们要表示真或假的时候,都是定义一…

    2024年5月18日
    3700
  • c语言的关键字和命令,c语言32个关键字详解

    C语言的全部命令?? 命令的基本形式如下:line number[filename]其中的数字为任何正整数,可选的文件名为任意有效文件标识符。行号为源程序中当前行号,文件名为源文件的名字。命令# line主要用于调试及其它特殊应用。 展开全部 我们可以在C源程序中插入传给编译程序的各中指令,这些指令被称为预处理器指令,它们扩充了程序设计的环境。 我的建议是:…

    2024年5月18日
    2700
  • c语言用到的软件,c语言有哪些软件

    c语言工作使用的软件? 1、常用的c语言编程软件有:devc++是比较容易上手的编程软件,优点是功能简洁,页面简洁。 2、C语言用Code:Blocks软件。Code:Blocks是一个开放源码的全功能的跨平台C/C++集成开发环境,由纯粹的C++语言开发完成,支持语法彩色醒目显示,支持代码完成、支持工程管理、项目构建、调试,而且具有灵活而强大的配置功能。 …

    2024年5月18日
    3500
  • c语言1245052,草莓熊代码编程C语言

    C语言和汇编语言的关系? 程序员编写的C语言代码,首先要经过C语言编译器,生成汇编代码,这个过程称为编译阶断,当C语言编译器生成汇编代码后,再调用汇编器来将汇编代码编译成汇编指令。 C语言是一种计算机程序设计语言。它既有高级语言的特点,又具有汇编语言的特点。它可以作为系统设计语言,编写工作系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程…

    2024年5月18日
    4300
  • 求pi的c语言程序,用c语言求pi

    C语言的求π的值? 标准的C语言中没有π这个符号及常量,一般在开发过程中是通过开发人员自己定义这个常量的,最常见的方式是使用宏定义:#definePI141592。 首先,while循环,条件是某一项,也就是t的绝对值小于10的-6次方,fabs是求绝对值的函数。 后面应该是9,1..;可以用i=1; i+=2;来表示。 我们经常会运用C语言进行各种数学运算…

    2024年5月18日
    4300
  • c语言如何实现四舍五入,c语言怎样实现四舍五入

    c语言四舍五入 1、首先打开DEV C++软件,点击“新建源代码”,在编辑页面输入以下代码。因为题目要求我们先输入一个整数,所以在定义变量时,就应该将其定义为整数型,注意,在输入,输出函数中,整数型对应的是“%d”。 2、要用C语言实现四舍五入,有一个很巧妙的方法,仅使用int i=(int)(a+0.5)即可。如果遇到有负数的情况,只需要将加号改为减号即可…

    2024年5月18日
    3300

发表回复

登录后才能评论



关注微信