整個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
- PL/0語言建立一個詞法分程序GETSYM(函數)
把關鍵字、算符、界符稱爲語言固有的單詞,標識符、常量稱爲用戶自定義的單詞。爲此設置三個全程量:SYM,ID,NUM 。
SYM:存放每個單詞的類別,爲內部編碼的表示形式。
ID:存放用戶所定義的標識符的值,即標識符字符串的機內表示。
NUM:存放用戶定義的數。
GETSYM要完成的任務:
- 濾掉單詞間的空格。
- 識別關鍵字,用查關鍵字表的方法識別。當單詞是關鍵字時,將對應的類別放在SYM中。如IF的類別爲IFSYM,THEN的類別爲THENSYM。
- 識別標識符,標識符的類別爲IDENT,IDENT放在SYM中,標識符本身的值放在ID中。關鍵字或標識符的最大長度是10。
- 拼數,將數的類別NUMBER放在SYM中,數本身的值放在NUM中。
- 拼由兩個字符組成的運算符,如:>=、<=等等,識別後將類別存放在SYM中。
- 打印源程序,邊讀入字符邊打印。
由於一個單詞是由一個或多個字符組成的,所以在詞法分析程序GETSYM中定義一個讀字符過程GETCH。
因爲剛做完第一個,且只驗證第一個的結果,就寫了一個cpp文件,可以自己修改噢。
程序是從文件裏讀入的,結果輸出到命令行
#include <iostream>
#include <string>
#include <cstdio>
#include <fstream>
#include <cstdlib>
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 << "(" <<str << " , "<<code<<" , - )" << endl;
// cout << "( " << code << ", - )" << endl;
}
}
else if (IsDigit(ch)) {
while (IsDigit(ch)) {
if (pos > 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;
}