简单的词法分析器的实现

来源:互联网 发布:java环境变量配置linux 编辑:程序博客网 时间:2024/05/22 06:45

参照百度百科,词法分析器又称扫描器,其作用为将编写的文本代码流解析成一个个记号(种别码),供后续语法分析使用。扫描器在其工作过程中,一般应完成下列的任务


(1)识别出源程序中的各个单词符号,并将其转换为内部编码形式;(2)删除无用的空白字符、回车字符以及其它非实质性字符;(3)删除注释;(4)进行词法检查,报告所发现的错误。

大概花了一节课的时间思考了一下实现流程:首先,读到空格则略过,读下一个字符;若读到的是字母,就再接着读,直到读到的既不是字母也不是数字也不是下划线(终于知道为什么变量必须字母打头了),并将读到的写入到token数组;若读到的是数字,直到读到的不是数字或小数点,将读到的写入到token数组;若读到的是<|>|=,则再读入下一位,若为=,则该运算符为<=|>=|==,若为其他字符,则返回<|>|=的种别码;若读到的是/,则读下一位,若为*,则说明之后为注释内容,一直读入直到读入*,并判断下一位是否为/,若是则注释结束,不是继续往下一位读入;若读入\n,则行数加一,若读入的字符与以上都不匹配,则报错,并输出出错行数

种别码:

单词符号

种别码

单词符号

种别码

NUM

1

+

22

ID

2

-

23

main

3

*

24

if

4

/

25

else

5

=

26

while

6

>=

27

do

7

>

28

Int

8

<=

29

double

9

<

30

float

10

,

31

void

11

.

32

switch

12

%

33

case

13

:

34

for

14

;

35

(

15

36

)

16

!

37

{

17

[

19

}

18

]

20

#

0

++

38

/*

40

--

39

*/

41

 



代码实现:

#include<iostream>#include<string.h>#include<stdlib.h>#define token_size 10#define code_size 100const char *keyword[12]={"main","if","else","while","do","int","double","float","void","switch","case","for"};using namespace std;void input_code(char *code){    char ch;    int i;    for(i=0;cin.get(ch) && ch!='#';i++){        *(code+i)=ch;    }    *(code+i)='#';}void init_token(char *token){          //初始化token数组    for(int i=0;i<token_size;i++)        *(token+i)=NULL;}int judge_token(char *code, char *token, int *order){    init_token(token);    int token_num=0;    while( *(code+*order)==' ' )        (*order)++;    if( *(code+*order)>='0'&&*(code+*order)<='9' ){          //判断是否为数字        while( *(code+*order)>='0'&&*(code+*order)<='9'||*(code+*order)=='.' ){            *(token+token_num)=*(code+*order);            token_num++;(*order)++;        }        return 1;    }    else if( (*(code+*order)>='a'&&*(code+*order)<='z') || (*(code+*order)>='A'&&*(code+*order)<='Z') ){          //判断是否为标识符或变量名        while( (*(code+*order)>='0'&&*(code+*order)<='9') || (*(code+*order)>='a'&&*(code+*order)<='z') || (*(code+*order)>='A'&&*(code+*order)<='Z') || *(code+*order)=='_' ){            *(token+token_num)=*(code+*order);            token_num++;(*order)++;        }        *(token+token_num++)='\0';        for(int i=0;i<12;i++){            if( strcmp(token,keyword[i]) )                return i+2;        }        return 2;    }    else {          //判断是否为其他运算符        *(token+token_num++)=*(code+(*order));        switch( *(code+(*order)++) ){        case '(': return 15;        case ')': return 16;        case '{': return 17;        case '}': return 18;        case '[': return 19;        case ']': return 20;        case '#': return 0;        case '+':            if( *(code+(*order))=='+' ){                *(token+token_num++)=*(code+(*order)++);                return 22;            }            else {                return 38;            }        case '-':            if( *(code+(*order))=='-' ){                *(token+token_num++)=*(code+(*order)++);                return 23;            }            else {                return 39;            }        case '*':            if( *(code+(*order))!='/' )                return 24;            else {                *(token+token_num++)=*(code+(*order)++);                return 41;            }        case '/':            if( *(code+(*order))!='*' )                return 25;            else {                *(token+token_num++)=*(code+(*order)++);                return 40;            }        case '=': return 26;        case '>':            if( *(code+(*order))=='=' ){                *(token+token_num++)=*(code+(*order)++);                return 27;            }            else {                return 28;            }        case '<':            if( *(code+(*order))=='=' ){                *(token+token_num++)=*(code+(*order)++);                return 29;            }            else {                return 30;            }        case ',': return 31;        case '.': return 32;        case '%': return 33;        case ':': return 34;        case ';': return 35;        case '"': return 36;        case '!': return 37;        case '\n': init_token(token); return -2;        default:  return -1;        }    }}void judge(char *code){    int order=0, row=1;    int symbol;    char token[token_size];    do{        symbol=judge_token(code, token, &order);        switch(symbol){        case -1:          //返回未识别字符所在行数            cout << "第" << row << "行出现错误" << endl;            break;        case -2:          //读到了回车键,进行换行,行数加一            row++;            break;        case 40:            cout << "<" << symbol << "," << token << ">" << endl;        //读到注释开始符            cout << "这里有注释" << endl;            while( !(*(code+order)=='*'&&*(code+order+1)=='/') )         //忽略注释内容,直到读到注释结束符                order++;            break;        default:            cout << "<" << symbol << "," << token << ">" << endl;        }    }while(*(code+order)!='#');}int main(){char code[code_size];cout << "请输入程序段,回车换行,输入#完成输入" << endl;input_code(code);judge(code);system("pause");return 0;}


举一个例子: