实验二词法分析(小组验收)
实验目的
- 根据 PL/0 语言的文法规范,编写 PL/0 语言的词法分析程序。
- 通过设计调试词法分析程序,实现从源程序中分出各种单词的方法;
加深对课堂教学的理解;提高词法分析方法的实践能力。 - 掌握从源程序文件中读取有效字符的方法和产生源程序的内部表示
文件的法。 - 掌握词法分析的实现方法。
- 上机调试编出的词法分析程序。
实验时间
- 4学时
实验内容
- 输入 PL/0 语言程序,输出程序中各个单词符号(关键字、专用符号以及
其它标记)。实验要求
- 确定编译中单词种类、使用的表格、标识符与关键字的区分方法等。
- 词法分析器读入 PL/0 语言源程序(文本文件),识别结果也以文本
文件保存。 - 词法分析器的输出形式采用二元式序列,即:
(单词种类, 单词的值) - 源程序中字符不区分大小写,即:“a1”和“A1”是同一个标识符。
- 准备至少 5 组测试用例,每组测试用例包括:输入源程序文件和输
出结果。 - 测试用例必须包含所有的基本字、运算符、界符、以及各种标识符
和常数。对不合法单词进行分类考虑测试用例,特别是对一些运算
符要充分考虑各种组合。
输入输出样例
实验代码
- help.h 代码链接
//
// 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
- main.cpp 代码链接
#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) thenc:=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 .)