大连理工大学软件学院编译技术课程——MicroC词法分析上机实验

实验目的:对循环语句和条件判断语句编写词法分析编译程序,只能通过一遍扫描完成。

 

实验要求:

  1. 关键字:

for    if    then  else  while    do    until    int    input    output

所有关键字都是小写。

(2)运算符和分隔符:

  :  =   +   -   *    /   <    >   <=   <>    >=    ;    (  )   #

  1. 其他标识符(ID)和整型常数(NUM),通过以下模式定义:

ID=letter(letter | digit)*

NUM=digit digit*

(4)空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM、运算符、分隔符和关键字,词法分析阶段通常被忽略。

 

各种词法单元对应的词法记号如下:

 

词法单元

词法记号

词法单元

词法记号

for

1

:

17

if

2

:=

18

then

3

<

20

else

4

<>

21

while

5

<=

22

do

6

>

23

letter(letter+digit)*

10

>=

24

digit digit*

11

=

25

+

13

;

26

-

14

(

27

*

15

)

28

/

16

#

0

until

29

int

30

input

31

output

32

 

浮点数             33

词法分析程序的功能

输入:源程序

输出:二元组(词法记号,属性值/其在符号表中的位置)构成的序列。

 

例如:对源程序

int x:=5;  if (x>0)  then  x:=2*x+1/3;  else  x:=2/x;  #

经词法分析后输出如下序列:

(30, int)(10,’x’)(18, :=) (11,5) (26, ;) (2, if )  (27,( )……

 

我的思路:

状态转换图如下:

其中1,7,8,9,10是确定终态,其他是非确定终态。

用move函数模拟状态转换。

word类(封装词法分析相关的函数):

import java.util.HashMap;


public class word {
    //关键字、操作符都与对应的状态号形成映射,便于查找
    HashMap<String,Integer> op = new HashMap<String, Integer>(){{
        put("+",13);
        put("-",14);
        put("*",15);
        put("/",16);
        put(":",17);
        put(":=",18);
        put("<",20);
        put("<>",21);
        put("<=",22);
        put(">",23);
        put(">=",24);
        put("=",25);
        put(";",26);
        put("(",27);
        put(")",28);
        put("#",0);
    }};
    HashMap<String,Integer> kw = new HashMap<String,Integer>(){{
        put("for",1);
        put("if",2);
        put("then",3);
        put("else",4);
        put("while",5);
        put("do",6);
        put("until",29);
        put("int",30);
        put("input",31);
        put("output",32);
    }};

    //判断扫描到的字符串是不是映射中已有的操作符
    int matchOp(String ope){
        if(op.containsKey(ope))
            return op.get(ope);
        else
            return -1;

    }
    //判断扫描到的字串是不是映射中已有的关键字
    int matchKw(String kwo){
        if(kw.containsKey(kwo))
            return kw.get(kwo);
        else
            return -1;
    }
    //模拟状态转换
    int Move(int beg,char c){
        int en = 0;
        int c_asc = (int)c;
        switch(beg){
            case 0:
                if(c_asc>=48&&c_asc<=57)
                    en = 6;
                else if((c_asc>=65&&c_asc<=90)||(c_asc>=97&&c_asc<=122))
                    en = 11;
                else if(c==' ')
                    en = 1;
                else{
                    if(c==':')
                        en = 4;
                    else if(c=='>')
                        en = 3;
                    else if(c=='<')
                        en = 2;
                    else
                        en = 5;}
                break;
            case 2:
                if(c=='>')
                    en = 7;
                else if(c=='=')
                    en = 8;
                else
                    en = 1;
                break;
            case 3:
                if(c=='=')
                    en = 9;
                else
                    en = 1;
                break;
            case 4:
                if(c=='=')
                    en = 10;
                else
                    en = 1;
                break;
            case 5:
                en = 1;
                break;
            case 6:
                if(c_asc>=48&&c_asc<=57)
                    en = 6;
                else if(c=='.')
                    en = 14;
                else
                    en = 1;
                break;
            case 11:
                if(c_asc>=48&&c_asc<=57)
                    en = 13;
                else if((c_asc>=65&&c_asc<=90)||(c_asc>=97&&c_asc<=122))
                    en = 12;
                else
                    en = 1;
                break;
            case 12:
                if(c_asc>=48&&c_asc<=57)
                    en = 13;
                else if((c_asc>=65&&c_asc<=90)||(c_asc>=97&&c_asc<=122))
                    en = 12;
                else
                    en = 1;
                break;
            case 13:
                if(c_asc>=48&&c_asc<=57)
                    en = 13;
                if(c_asc>=65&&c_asc<=90||c_asc>=97&&c_asc<=122)
                    en = 13;
                else
                    en = 1;
                break;
            case 14:
                if(c_asc>=48&&c_asc<=57)
                    en = 15;
                else
                    en = 1;
                break;
            case 15:
                if(c_asc>=48&&c_asc<=57)
                    en = 15;
                else
                    en =1;
                break;
        }
        return en;
    }

    void handle(String s){
        int state=0,state2=0;
        String temp = "";
        char c;
        int end = 0;

        //如果是空格,直接截掉
        while(s.length()>0){
            while(s.charAt(end)==' ')
                s = s.substring(1);

            do{
                c = s.charAt(end++);
                state = Move(state,c);
                if(state!=1){
                    state2 = state;
                    temp += c;
                }
            }while(state!=1&&state!=7&&state!=8&&state!=9&&state!=10&&s.length()>end);

            //这些全是操作符
            if(state2>1&&state2<=10&&state2!=6){
                System.out.print("("+matchOp(temp)+","+temp+") ");
            }

            //这是数字
            if(state2==6){
                System.out.print("(11,"+temp+") ");
            }
            if(state2==14){      //如果输入x.则转化为x.0,假装浮点数的词法记号是33
                System.out.print("(33," + temp+"0) ");
            }
            if(state2==15){
                System.out.println("(33,"+temp+") ");
            }
            //剩下是字母/数字串,字母串要匹配关键字
            if(state2==13||state2==11){
                System.out.print("(10,"+temp+") ");
            }
            if(state2==12&&matchKw(temp)!=-1){
                System.out.print("("+matchKw(temp)+","+temp+") ");
            }

            if(state2==12&&matchKw(temp)==1){
                System.out.println("(10,"+temp+") ");
            }

            //切掉
            s = s.substring(temp.length());
            temp = "";
            end = 0;
            state = 0;
            state2 = 0;
        }
    }



}

主函数类:

import java.util.Scanner;


public class Main {
    public static void main(String[] args) {
        int i;
        word w = new word();
        String s;
        Scanner in = new Scanner(System.in);
        s = in.nextLine();
        w.handle(s);
    }
}

 

大连理工大学软件学院编译技术课程——词法分析上机实验 实验目的:对循环句和条件判断句编写词法分析编译程序,只能通过一遍扫描完成。(用c++实现) 实验要求: (1) 关键字: for if then else while do 所有关键字都是小写。 (2)运算符和分隔符: : = + - * / <= >= ; ( ) # (3)其他标识符(ID)和整型常数(NUM),通过以下正规式定义: ID=letter(letter | digit)* NUM=digit digit* (4)空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM、运算符、分隔符和关键字,词法分析阶段通常被忽略。 各种词法单元对应的词法记号如下: 词法单元 词法记号 词法单元 词法记号 for 1 : 17 if 2 := 18 then 3 < 20 else 4 21 while 5 23 letter(letter+digit)* 10 >= 24 digit digit* 11 = 25 + 13 ; 26 - 14 ( 27 * 15 ) 28 / 16 # 0 词法分析程序的功能 输入:源程序 输出:二元组(词法记号,属性值/其在符号表中的位置)构成的序列。 例如:对源程序 x:=5; if (x>0) then x:=2*x+1/3; else x:=2/x; # 经词法分析后输出如下序列: (10,’x’)(18, :=) (11,5) (26, ;) (2, if ) (27,( )…… 1.几点说明: (1)关键字表的初值。 关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符,查关键字表。如能查到匹配的单词,则该单词的关键字,否则为一般标识符。关键表为一个字符串数组,其描述如下: char *keyword[6]={”for”, ”if”, ”then” ,”else”,”while”, ”do” }; (2) 程序中需要用到的主要变量为 token , id和num. 1)id用来存放构成词法单元的字符串; 2)num用来存放整数(可以扩展到浮点数和科学计数法表示); 3)token用来存放词法单元的词法记号。 可以参考下面的代码: do{ lexical(); //将词法单元对应的记号保存到token中,属性值保存到num或者id中 switch(token) { case 11: printf ("(token, %d\n) ", num); break; case -1: printf("error!\n");break; default: printf("(%d,%s)\n", token, id); } }while (token!=0);
基于microC词法分析器(c/c++版本)是一个用于分析和处理microC编程言的工具。microC是一种简化的C言,用于教学和学习目的词法分析器的主要功能是将源代码分解为一个个的词法单元,比如标识符、关键字、运算符、常量等。同时,词法分析器会忽略空白字符和注释。 为了实现词法分析器,我们需要定义和识别microC言中的各种词法单元。这些词法规则可以根据microC言的法来确定。 词法分析器的工作流程如下: 1. 首先,读取源代码文件。 2. 然后,逐个字符读取源代码,将其组成一个个的词法单元。 3. 对于每个词法单元,根据预定义的词法规则进行识别,并将其分类。 4. 词法单元分析完毕后,将其分类结果保存,并继续进行下一个词法单元的分析。 5. 最后,将词法单元的分类结果输出或者传递给法分析器进行进一步处理。 在实现词法分析器时,我们可以使用C或者C++编程言来实现。可以通过读取源代码文件,并使用循环和条件句来逐个字符地进行分析和识别。同时,可以使用数据结构,如数组和链表来保存和管理词法单元的分类结果。 词法分析器对于编程言的解析和理解非常重要,同时也是其他编译器前端的基础。通过实现基于microC词法分析器,我们可以更好地理解和学习编译原理的相关知识,同时也可以为后续的法分析和义分析等工作奠定基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值