编译原理实验二


实验二词法分析(小组验收)

实验目的

  • 根据 PL/0 语言的文法规范,编写 PL/0 语言的词法分析程序。
  • 通过设计调试词法分析程序,实现从源程序中分出各种单词的方法;
    加深对课堂教学的理解;提高词法分析方法的实践能力。
  • 掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示
    文件的法。
  • 掌握词法分析的实现方法。
  • 上机调试编出的词法分析程序。

实验时间

  • 4学时

实验内容

  • 输入 PL/0 语言程序,输出程序中各个单词符号(关键字、专用符号以及
    其它标记)。

    实验要求

  • 确定编译中单词种类、使用的表格、标识符与关键字的区分方法等。
  • 词法分析器读入 PL/0 语言源程序(文本文件),识别结果也以文本
    文件保存。
  • 词法分析器的输出形式采用二元式序列,即:
    (单词种类, 单词的值)
  • 源程序中字符不区分大小写,即:“a1”和“A1”是同一个标识符。
  • 准备至少 5 组测试用例,每组测试用例包括:输入源程序文件和输
    出结果。
  • 测试用例必须包含所有的基本字、运算符、界符、以及各种标识符
    和常数。对不合法单词进行分类考虑测试用例,特别是对一些运算
    符要充分考虑各种组合。

输入输出样例

实验代码

//
// Created by 高松 on 2017/4/6.
//

#ifndef EX02_HELP_H
#define EX02_HELP_H

bool IsAlpha(char ch){
    if((ch >='a'&&ch<='z')||(ch>='A'&&ch<='Z')){
        return true;
    }
    return false;
}

bool IsDigit(char ch){
    if( ch>='0'&&ch<='9'){
        return true;
    }
    return false;
}

bool IsAlphOrNum(char ch){
    if(IsAlpha(ch)){
        return true;
    }
    if(IsDigit(ch)){
        return true;
    }
    return false;
}
#endif //EX02_HELP_H
#include <iostream>
using namespace std;
#include <cstring>
#include <cstdio>
#include <fstream>
#include <string>
#include <map>
#include "help.h"
#define FILEPATH "test.txt"
#define TOKENPATH "Mapper.txt"
#define TABSIZE 10

char prog[80],token[10];
char ch;
int syn,p,m = 0,n,row,sum = 0;
char *rwtab[TABSIZE] = {
        "begin","if","then","while","do","end","read","write","const","var",
};

map<int ,string> Mapper;



void scaner(){
    for(n = 0;n<8;n++){
        token[n] = NULL;
    }
    ch = prog[p++];
    while(ch == ' '){
        ch = prog[p];
        p++;
    }
    if(IsAlpha(ch)){
        m = 0;
        while(IsAlphOrNum(ch)){
            token[m++] = ch;
            ch = prog[p++];
        }
        token[m++] = 0;
        p--;
        syn = 10;
        for(n = 0;n<TABSIZE;n++){
            if(strcmp(token,rwtab[n])==0){
                syn = n+31;
                break;
            }
        }
    }
    else if( IsDigit(ch)){
        sum  = 0;
        while(isdigit(ch)){
            sum = sum*10 +ch-'0';
            ch = prog[p++];
        }
        p--;
        syn = 11;
        if(sum>32767){
            syn = -1;
        }
    }else switch(ch){
            case '<': m = 0; token[m++] = ch;
                ch = prog[p++];
                if(ch == '>'){
                    syn = 21;
                    token[m++]  = ch;
                }
                else if(ch == '='){
                    syn = 2;;
                    token[m++] = ch;
                }
                else {
                    syn = 23;
                    p--;
                }
                break;
            case '>': m = 0; token[m++] = ch;
                ch = prog[p++];
                if( ch == '='){
                    syn = 24;
                    token[m++] = ch;
                }
                else{
                    syn = 20;
                    p--;
                }
                break;
            case ':': m = 0;token[m++] = ch;
                ch = prog[p++];
                if( ch =='='){
                    syn = 18;
                    token[m++] = ch;
                }
                else{
                    syn = 17;
                    p--;
                }
                break;
            case ',' : syn=19;token[0] = ch; 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; break;
        }
}

int main() {
    Mapper.clear();
    p = 0;
    row = 1;
    ifstream MapFile(TOKENPATH);
    string line;
    if(MapFile){
        while(getline(MapFile,line)){
            bool IsNum = false;
            int sum = 0;
            string token = "";
            for(int  i =0;i<line.size();i++){
                if( line[i] ==' '){
                    IsNum = true;
                    continue;
                }
                if(IsNum == true ){
                    sum = sum*10+(char)line[i]-'0';
                }
                else {
                    token += line[i];
                }
            }
            Mapper[sum] = token;
        }
    }
    Mapper[0] = "peroid";

//    map<int,string>:: iterator it;
//    for(it = Mapper.begin();it!=Mapper.end();it++){
//        cout<<it->first<<","<<it->second<<endl;
//    }
//    return 0 ;

    ifstream in(FILEPATH);
    if(in){
        while(getline(in,line)){
            char c[100];
            strcpy(c,line.c_str());
            for(int i = 0;i<strlen(c);i++){
                ch = line[i];
                prog[p++] = ch;
                if(ch == '.'){
                    goto A;
                }
            }
        }
    }
//    for(int i = 0;i<p;i++){
//        cout<<prog[i];
//    }
//    return 0;

    A:
    p = 0;
    do {
        scaner();
//        cout<<"syn = "<<syn<<endl;
        switch(syn){
            case 11: cout<<"("<<Mapper[11]<<" "<<sum<<")"<<endl;break;
            case -1: cout<<" Error in row "<<endl;
            default: cout<<"("<<Mapper[syn]<<" "<<token<<")"<<endl;break;
        }
    }while(syn!=0);

    return 0;
}

测试样例

样例1
  • 题目给的样例
const a = 10;
var b,c;
begin
 read(b);
 c:=a+b;
 wrrite(c)
 end.
  • 输出结果
(const const)
(Identity a)
(Equal =)
(Digit 10)
(semicolon ;)
(var var)
(Identity b)
(comma ,)
(Identity c)
(semicolon ;)
(Beginsys begin)
(read read)
(lparen ()
(Identity b)
(rparen ))
(semicolon ;)
(Identity c)
(becomes :=)
(Identity a)
(Plus +)
(Identity b)
(semicolon ;)
(Identity wrrite)
(lparen ()
(Identity c)
(rparen ))
(End end)
(peroid .)
样例2
  • 包含大写的样例
CONST a=10;
VAR b,c;
begin
 read(b);
 c:=a+b;
 wrrite(c)
 end.
  • 输出结果
(Identity CONST)
(Identity a)
(Equal =)
(Digit 10)
(semicolon ;)
(Identity VAR)
(Identity b)
(comma ,)
(Identity c)
(semicolon ;)
(Beginsys begin)
(read read)
(lparen ()
(Identity b)
(rparen ))
(semicolon ;)
(Identity c)
(becomes :=)
(Identity a)
(Plus +)
(Identity b)
(semicolon ;)
(Identity wrrite)
(lparen ()
(Identity c)
(rparen ))
(End end)
(peroid .)
样例3
  • 拼写有错的样例
cons a = 10;
var b,c;
begin
 read(b);
 c:=a+b;
 wrrite(c)
 end.
  • 输出结果
(Identity cons)
(Identity a)
(Equal =)
(Digit 10)
(semicolon ;)
(var var)
(Identity b)
(comma ,)
(Identity c)
(semicolon ;)
(Beginsys begin)
(read read)
(lparen ()
(Identity b)
(rparen ))
(semicolon ;)
(Identity c)
(becomes :=)
(Identity a)
(Plus +)
(Identity b)
(semicolon ;)
(Identity wrrite)
(lparen ()
(Identity c)
(rparen ))
(End end)
(peroid .)
样例4
  • 包含大于等于号的样例

    const a = 10;
    var b,c;
    begin
    read(b);
    if(a>=b) then

    c:=b+a;
    

    write(c);
    end.

  • 输出结果
(const const)
(Identity a)
(Equal =)
(Digit 10)
(semicolon ;)
(var var)
(Identity b)
(comma ,)
(Identity c)
(semicolon ;)
(Beginsys begin)
(read read)
(lparen ()
(Identity b)
(rparen ))
(semicolon ;)
(Ifsys if)
(lparen ()
(Identity a)
(EqualOrGreat >=)
(Identity b)
(rparen ))
(Thensys then)
(Identity c)
(becomes :=)
(Identity b)
(Plus +)
(Identity a)
(semicolon ;)
(write write)
(lparen ()
(Identity c)
(rparen ))
(semicolon ;)
(End end)
(peroid .)
样例5
  • 包含空格回车的样例
const a = 10;
var b, c;



begin
 read(b);
 if(a>=b) then
   c:=b+a;
 write(c);
end.
  • 输出结果
(const const)
(Identity a)
(Equal =)
(Digit 10)
(semicolon ;)
(var var)
(Identity b)
(comma ,)
(Identity c)
(semicolon ;)
(Beginsys begin)
(read read)
(lparen ()
(Identity b)
(rparen ))
(semicolon ;)
(Ifsys if)
(lparen ()
(Identity a)
(EqualOrGreat >=)
(Identity b)
(rparen ))
(Thensys then)
(Identity c)
(becomes :=)
(Identity b)
(Plus +)
(Identity a)
(semicolon ;)
(write write)
(lparen ()
(Identity c)
(rparen ))
(semicolon ;)
(End end)
(peroid .)
文章目录
  1. 1. 实验二词法分析(小组验收)
    1. 1.0.1. 实验目的
    2. 1.0.2. 实验时间
    3. 1.0.3. 实验内容
    4. 1.0.4. 实验要求
    5. 1.0.5. 输入输出样例
    6. 1.0.6. 实验代码
    7. 1.0.7. 测试样例
      1. 1.0.7.1. 样例1
      2. 1.0.7.2. 样例2
      3. 1.0.7.3. 样例3
      4. 1.0.7.4. 样例4
      5. 1.0.7.5. 样例5
|