整个PL/0编译器文件已上传:https://download.csdn.net/download/qq_41102235/12038487
PL/0 词法分析、语法分析、语义分析与中间代码生成、解释执行 最终结果输出目标代码、符号表、解释执行结果
Pl/0语言文法的BNF表示:
〈程序〉→〈分程序〉。
〈分程序〉→ [<常量说明部分>][<变量说明部分>][<过程说明部分>]〈语句〉
<常量说明部分> → CONST<常量定义>{ ,<常量定义>};
<常量定义> → <标识符>=<无符号整数>
<无符号整数> → <数字>{<数字>}
<变量说明部分> → VAR<标识符>{ ,<标识符>};
<标识符> → <字母>{<字母>|<数字>}
<过程说明部分> → <过程首部><分程度>;{<过程说明部分>}
<过程首部> → procedure<标识符>;
<语句> → <赋值语句>|<条件语句>|<当型循环语句>|<过程调用语句>|<读语句>|<写语句>|<复合语句>|<空>
<赋值语句> → <标识符>:=<表达式>
<复合语句> → begin<语句>{ ;<语句>}<end>
<条件> → <表达式><关系运算符><表达式>|odd<表达式>
<表达式> → [+|-]<项>{<加减运算符><项>}
<项> → <因子>{<乘除运算符><因子>}
<因子> → <标识符>|<无符号整数>|(<表达式>)
<加减运符> → +|-
<乘除运算符> → *|/
<关系运算符> → =|#|<|<=|>|>=
<条件语句> → if<条件>then<语句>
<过程调用语句> → call<标识符>
<当型循环语句> → while<条件>do<语句>
<读语句> → read(<标识符>{ ,<标识符>})
<写语句> → write(<标识符>{,<标识符>})
<字母> → a|b|c…x|y|z
<数字> → 0|1|2…7|8|9
把关键字、算符、界符称为语言固有的单词,标识符、常量称为用户自定义的单词。为此设置三个全程量:SYM,ID,NUM 。
SYM:存放每个单词的类别,为内部编码的表示形式。
ID:存放用户所定义的标识符的值,即标识符字符串的机内表示。
NUM:存放用户定义的数。
GETSYM要完成的任务:
由于一个单词是由一个或多个字符组成的,所以在词法分析程序GETSYM中定义一个读字符过程GETCH。
因为刚做完第一个,且只验证第一个的结果,就写了一个cpp文件,可以自己修改噢。
程序是从文件里读入的,结果输出到命令行
#include
#include
#include
#include
#include
using namespace std;
const int num_word = 13;//关键字
const int num_opt = 13;//操作符
const int MAXLEN = 10;//*str的最大长度
static int line = 0;//判断文件读到第几行
static string stable[100];
static int stlen = 0;
static string ntable[100];
static int ntlen = 0;
enum SYM
{
SYMUNUSE,//0不设保留字
SYMCONST,SYMVAR,SYMPROCEDURE,SYMBEGIN,SYMEND,SYMODD,SYMIF,SYMTHEN,SYMCALL,SYMWHILE,SYMDO,SYMREAD,SYMWRITE,
SYMIDENTIFIER,SYMNUM,
SYMPLUS,//+
SYMMINUS,//-
SYMMUL,//*
SYMDIV,// /
SYMASSI,//assignment :=
SYMEQ,//=
SYMNEQ,// #
SYMLESS,// <
SYMLESSEQ,// <=
SYMBIG,//>
SYMBIGEQ,//>=
SYMLEFT,//(
SYMRIGHT,//)
SYMLEFTB,//{
SYMRIGHTB,//}
SYMSEM,//Semicolon ;
SYMCOM,// ,
};
int array_word[num_word] = { SYMCONST,SYMVAR,SYMPROCEDURE,SYMBEGIN,SYMEND,SYMODD,SYMIF,SYMTHEN,SYMCALL,SYMWHILE,SYMDO,SYMREAD,SYMWRITE };
bool IsLetter(char ch) {
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
return true;
else return false;
}
bool IsDigit(char ch) {
if (ch >= '0' && ch <= '9')
return true;
else return false;
}
//void GetBC(string str, char ch)
int Reserve(char* str) {
if (!strcmp(str, "const") )
// if(str=="const")
return SYMCONST;
if (!strcmp(str, "var"))
return SYMVAR;
if (!strcmp(str, "procedure"))
return SYMPROCEDURE;
if (!strcmp(str, "begin"))
return SYMBEGIN;
if (!strcmp(str, "end"))
return SYMEND;
// SYMODD, SYMIF, SYMTHEN, SYMCALL, SYMWHILE, SYMDO, SYMREAD, SYMWRITE
if (!strcmp(str, "odd"))
return SYMODD;
if (!strcmp(str, "if") )
return SYMIF;
if (!strcmp(str, "then") )
return SYMTHEN;
if (!strcmp(str, "call") )
return SYMCALL;
if (!strcmp(str, "while"))
return SYMWHILE;
if (!strcmp(str, "do") )
return SYMDO;
if (!strcmp(str, "read") )
return SYMREAD;
if (!strcmp(str, "write"))
return SYMWRITE;
return 0;
}
int InsertId(char* str) {
if (IsLetter(str[0])) {
stable[stlen] = str;
stlen++;
return stlen - 1;
}
if (IsDigit(str[0])) {
ntable[ntlen] = str;
ntlen++;
return ntlen - 1;
}
}
int GETSYM(FILE *filename) {
// string strToken = "";
int code=0, value=0;
int pos = 0;
extern char id[MAXLEN];
char str[MAXLEN + 1] = {};//strToken
char ch = ' ';
while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') //GetBC
{
ch = fgetc(filename);
if (ch == EOF)
{
return -1;
}
if (ch == '\n')
line++;
}
if (IsLetter(ch)) {
while (IsLetter(ch) || IsDigit(ch)) {
if (pos > MAXLEN)return -1;
str[pos++] = ch;
ch = fgetc(filename);
}
ungetc(ch, filename);
// cout << "hhhhhhhhhhh " << str << endl;
code = Reserve(str);
// cout << "code is " << code << endl;
if (code == 0) {
value = InsertId(str);
// char a[20] = {};
// _itoa(value, a, 10);
// printf("(%s , $ID , %d ) ", stable[value], a);
cout << "(" + stable[value] + " , $ID , " << value<< ")" << endl;
// cout << "( $ID , " << value << ")" << endl;
//printf( "(" + stable[value] + "," + "ID" + ","+to_string(value)+")");
}
else {
// char b[20] = {};
// _itoa(code, b, 10);
// printf("(%s , code , - ) ", stable[value]);
cout << "(" < MAXLEN)return -1;
str[pos++] = ch;
ch = fgetc(filename);
}
ungetc(ch, filename);
value = InsertId(str);
// char a[20] = {};
// _itoa(value, a, 10);
// printf("(%s , $INT , %d ) ", ntable[value], value);
cout << "(" + ntable[value] + " $INT, " << value <<")" << endl;
// cout << "( $INT , " << value << " )" << endl;
}
else if (ch == '=') {
printf("(= , SYMEQ , - )\n ");
}
// SYMPLUS+ SYMMINUS- SYMMUL* SYMDIV/ SYMASSI:= SYMEQ= SYMNEQ#
// SYMLEFT( SYMRIGHT) SYMLEFTB{ SYMRIGHTB} SYMSEM;
else if (ch == '+') {
printf("(+ , SYMPLUS , - )\n ");
}
else if (ch == '-') {
printf("(- , SYMMINUS , - )\n ");
}
else if (ch == '*') {
printf("(* , SYMMUL , - )\n ");
}
else if (ch == '/') {
printf("(/ , SYMDIV , - )\n ");
}
else if (ch == '=') {
printf("(= , SYMEQ , - )\n ");
}
else if (ch == '#') {
printf("(# , SYMNEQ , - )\n ");
}
else if (ch == '(') {
printf("(( , SYMLEFT , - )\n ");
}
else if (ch == ')') {
printf("() , SYMRIGHT , - )\n ");
}
else if (ch == '{') {
printf("({ , SYMLEFTB , - )\n ");
}
else if (ch == '}') {
printf("(} , SYMRIGHTB , - )\n ");
}
else if (ch == ';') {
printf("(; , SYMSEM , - )\n ");
}
else if (ch == ',') {
printf("(, , SYMSEM , - )\n ");
}
else if (ch == ':') {
ch = fgetc(filename);
if (ch == '=') {
printf("(:= , SYMASSI , - )\n ");
}
else {
ungetc(ch, filename);
printf("error! (: , UNDEFINED , - )\n ");
}
}
// SYMLESS < SYMLESSEQ<= SYMBIG> SYMBIGEQ>=
else if (ch == '<') {
ch = fgetc(filename);
if (ch == '=') {
printf("(<= , SYMLESSEQ , - )\n");
}
else {
ungetc(ch, filename);
printf("(< , SYMLESS , - )\n ");
}
}
else if (ch == '>') {
ch = fgetc(filename);
if (ch == '=') {
printf("(>= , SYMBIGEQ , - )\n");
}
else {
ungetc(ch, filename);
printf("(> , SYMBIG , - )\n ");
}
}
else printf("无法识别该符号");
return 1;
}
int main(int argc, char* argv[]) {
FILE* filename;
// char fname[50] = "D:\study\Compilation\pro1.txt";
filename = fopen("pro1.txt","r"); //这里使用的是绝对路径,修改的话把文件名改好就行
if (filename == NULL)
{
perror("打开文件时发生错误");
return(-1);
}
while (GETSYM(filename));
return 0;
}