主题:请高手帮帮忙!对PL/0语言及其编译器进行扩充和修改(有源代码)
rcdd
[专家分:0] 发布于 2005-07-05 10:16:00
《编译原理》要求你对PL/0语言及其编译器进行扩充和修改。
(1) 修改后的PL/0语言文本。包含词法分析(正规式),语法分析(BNF)。
(2) 程序流程图
(3) 有关修改后的PL/0编译/解释器的说明。详细说明你的编译器是如何编译新的PL/0语言程序的。指出你的程序中最精彩的部分,以及你为什么这样做,你是如何控制和恢复语义错误的。
(4) 给出你所改动后的编译器源程序清单,并标记出你所修改的部分。比较你的编译器和原来的编译器之间的差别。
(5) 说明你的编译器中可能存在的错误。
对现存的PL/0编译程序可做如下修改或扩充。
(1) 注释
注释由(*和*)包含,不允许嵌套。
(2) 布尔类型的数据
布尔类型的BNF为:
var_option → ε| var var_decl_list
var_decl_list → var_decl | var_decl_list var_decl
var_decl → ident_list : data_type
data_type → integer | boolean
这种修改包括:
(i) 区别整型与布尔型变量、常量和表达式。
(ii) 增加按严格计算的布尔类型运算符and、or和not。这些算符以及己有的运算符的优先级与Pascal语言相同。
(iii) 能够使用布尔常量true和false。
(iv) 把PL/0语言中的“条件”概念一般化为Pascal语言那样。
(v) 布尔表达式可以比较大小:false < true
(3) 布尔表达式的短路计算(5分)
增加布尔类型(见(2),除(2)的(ii)外),但对and和or采取短路计算。
(4) 数组(10分)
增加由任何数据类型构造的一维数组。数组的下标限于纯量类型。
注意:数组可以由其它的数组来构造,因而必须考虑多维数组的情况。数组的上下界可为任意的纯量常数。
数组的定义如下:
data_type → integer | boolean | array [const..const] of data_type
const → ident | number
语言中允许有数组说明,对数组元素赋值,在表达式中引用数组元素。为了便于解释执行,可能要增加新的PL/0机器操作指令。
(5) 参数 语法同Pascal,采用值-结果方式传递(不用var声明)。
(6) 函数 语法同Pascal。
(7) else子句和repeat语句
(8) for语句,语法参照Pascal或C语言
(9) exit语句(退出当前执行过程)和break语句(跳出包含它的最内层循环),(5分)
(10) 记录(结构),语法同Pascal语言。
(11) 更有力的语法错误恢复机制
(12) 分离解释和编译器
另外,为了实现以上功能,你可任意增加PL/0处理机的指令。但要注意指令的简单与合理。
实现PL/0语言的输入、输出语句。其语法、语义定义和Pascal语言相同。可以仅仅实现一次输入或输出一个值的语句——语句参数固定;也可以实现完全和Pascal语言一样,能够接受任意个数参数的输入或输出语句。
回复列表 (共20个回复)
沙发
rcdd [专家分:0] 发布于 2005-07-05 10:19:00
附源程序:
/************ PL0.h *************/
#include <stdio.h>
#define NRW 11 // number of reserved words(保留字的数量)
#define TXMAX 500 // length of identifier table(标识符表长度)
#define MAXNUMLEN 14 // maximum number of digits in numbers(数字的最大长度)
#define NSYM 10 // maximum number of symbols in array ssym and csym
#define MAXIDLEN 10 // length of identifiers(标识符的长度)
#define MAXADDRESS 32767 // maximum address(最大地址)
#define MAXLEVEL 32 // maximum depth of nesting block
#define CXMAX 500 // size of code array
#define MAXSYM 30 // maximum number of symbols
#define STACKSIZE 1000 // maximum storage(堆栈的最大值)
enum symtype
{
SYM_NULL,
SYM_IDENTIFIER,
SYM_NUMBER,
SYM_PLUS,
SYM_MINUS,
SYM_TIMES,
SYM_SLASH,
SYM_ODD,
SYM_EQU,
SYM_NEQ,
SYM_LES,
SYM_LEQ,
SYM_GTR,
SYM_GEQ,
SYM_LPAREN,
SYM_RPAREN,
SYM_COMMA,
SYM_SEMICOLON,
SYM_PERIOD,
SYM_BECOMES,
SYM_BEGIN,
SYM_END,
SYM_IF,
SYM_THEN,
SYM_WHILE,
SYM_DO,
SYM_CALL,
SYM_CONST,
SYM_VAR,
SYM_PROCEDURE
};//定义标识符的类型,即是变量,常量;还是过程名
enum idtype
{
ID_CONSTANT, ID_VARIABLE, ID_PROCEDURE
};
enum opcode
{
LIT, OPR, LOD, STO, CAL, INT, JMP, JPC
};//定义操作符
enum oprcode
{
OPR_RET, OPR_NEG, OPR_ADD, OPR_MIN,
OPR_MUL, OPR_DIV, OPR_ODD, OPR_EQU,
OPR_NEQ, OPR_LES, OPR_LEQ, OPR_GTR,
OPR_GEQ
};//定义一系列枚举类型
typedef struct
{
int f; // function code
int l; // level
int a; // displacement address
} instruction;
//////////////////////////////////////////////////////////////////////
char* err_msg[] =
{
/* 0 */ "",
/* 1 */ "Found ':=' when expecting '='.",
/* 2 */ "There must be a number to follow '='.",
/* 3 */ "There must be an '=' to follow the identifier.",
/* 4 */ "There must be an identifier to follow 'const', 'var', or 'procedure'.",
/* 5 */ "Missing ',' or ';'.",
/* 6 */ "Incorrect procedure name.",
/* 7 */ "Statement expected.",
/* 8 */ "Follow the statement is an incorrect symbol.",
/* 9 */ "'.' expected.",
/* 10 */ "';' expected.",
/* 11 */ "Undeclared identifier.",
/* 12 */ "Illegal assignment.",
/* 13 */ "':=' expected.",
/* 14 */ "There must be an identifier to follow the 'call'.",
/* 15 */ "A constant or variable can not be called.",
/* 16 */ "'then' expected.",
/* 17 */ "';' or 'end' expected.",
/* 18 */ "'do' expected.",
/* 19 */ "Incorrect symbol.",
/* 20 */ "Relative operators expected.",
/* 21 */ "Procedure identifier can not be in an expression.",
/* 22 */ "Missing ')'.",
/* 23 */ "The symbol can not be followed by a factor.",
/* 24 */ "The symbol can not be as the beginning of an expression.",
/* 25 */ "The number is too great.",
/* 26 */ "",
/* 27 */ "",
/* 28 */ "",
/* 29 */ "",
/* 30 */ "",
/* 31 */ "",
/* 32 */ "There are too many levels."
};//定义出错提示信息
//////////////////////////////////////////////////////////////////////
char ch; // last character read
int sym; // last symbol read
char id[MAXIDLEN + 1]; // last identifier read
int num; // last number read
int cc; // character count字符统计
int ll; // line length行的长度
int kk;
int err;
int cx; // index of current instruction to be generated.
int level = 0;
int tx = 0;
char line[80];
instruction code[CXMAX];
char* word[NRW + 1] =
{
"", /* place holder */
"begin", "call", "const", "do", "end","if",
"odd", "procedure", "then", "var", "while"
};//定义保留字
int wsym[NRW + 1] =
{
SYM_NULL, SYM_BEGIN, SYM_CALL, SYM_CONST, SYM_DO, SYM_END,
SYM_IF, SYM_ODD, SYM_PROCEDURE, SYM_THEN, SYM_VAR, SYM_WHILE
};
int ssym[NSYM + 1] =
{
SYM_NULL, SYM_PLUS, SYM_MINUS, SYM_TIMES, SYM_SLASH,
SYM_LPAREN, SYM_RPAREN, SYM_EQU, SYM_COMMA, SYM_PERIOD, SYM_SEMICOLON
};
char csym[NSYM + 1] =
{
' ', '+', '-', '*', '/', '(', ')', '=', ',', '.', ';'
};定义运算符
#define MAXINS 8
char* mnemonic[MAXINS] =
{
"LIT", "OPR", "LOD", "STO", "CAL", "INT", "JMP", "JPC"
};
typedef struct
{
char name[MAXIDLEN + 1];
int kind;
int value;
} comtab;
comtab table[TXMAX];
typedef struct
{
char name[MAXIDLEN + 1];
int kind;
short level;
short address;
} mask;
FILE* infile;//定义文件指针
// EOF PL0.h
/************ SET.h *************/
#ifndef SET_H
#define SET_H
typedef struct snode
{
int elem;
struct snode* next;
} snode, *symset;
/* 定义名为snode的结构体类型,并定义一个结构体变量snode和一个snode类型的指针symset */
symset phi, declbegsys, statbegsys, facbegsys, relset;
symset createset(int data, .../* SYM_NULL */);
void destroyset(symset s);
symset uniteset(symset s1, symset s2);
int inset(int elem, symset s);
#endif
// EOF set.h
板凳
rcdd [专家分:0] 发布于 2005-07-05 10:21:00
/************ SET.h *************/
#ifndef SET_H
#define SET_H
typedef struct snode
{
int elem;
struct snode* next;
} snode, *symset;
/* 定义名为snode的结构体类型,并定义一个结构体变量snode和一个snode类型的指针symset */
symset phi, declbegsys, statbegsys, facbegsys, relset;
symset createset(int data, .../* SYM_NULL */);
void destroyset(symset s);
symset uniteset(symset s1, symset s2);
int inset(int elem, symset s);
#endif
// EOF set.h
/************ SET.c *************/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "set.h"
symset uniteset(symset s1, symset s2)
{
symset s;
snode* p;
s = p = (snode*) malloc(sizeof(snode));
//snode*实现强制类型转换;malloc函数完成什么功能?????
while (s1 && s2)
/* &&没有重载,怎么能直接运算呢?????s1,s2是指针类型的变量可以运算,判断s1,s2是不是空指针 */
{
p->next = (snode*) malloc(sizeof(snode));
p = p->next;
if (s1->elem < s2->elem)
{
p->elem = s1->elem;
s1 = s1->next;
}
else
{
p->elem = s2->elem;
s2 = s2->next;
}//判断s1,s2的elem属性的大小,并将大的赋给指针p的elem
}
while (s1)
{
p->next = (snode*) malloc(sizeof(snode));
p = p->next;
p->elem = s1->elem;
s1 = s1->next;
}
while (s2)
{
p->next = (snode*) malloc(sizeof(snode));
p = p->next;
p->elem = s2->elem;
s2 = s2->next;
}
p->next = NULL;
return s;
} // uniteset
void setinsert(symset s, int elem)
{
snode* p = s;
snode* q;
while (p->next && p->next->elem < elem)
{
p = p->next;
}
q = (snode*) malloc(sizeof(snode));
q->elem = elem;
q->next = p->next;
p->next = q;
} // setinsert
symset createset(int elem, .../* SYM_NULL */)
{
va_list list;
symset s;
s = (snode*) malloc(sizeof(snode));
s->next = NULL;
va_start(list, elem);
while (elem)
{
setinsert(s, elem);
elem = va_arg(list, int);
}
va_end(list);
return s;
} // createset创建节点
void destroyset(symset s)
{
snode* p;
while (s)
{
p = s;
s = s->next;
free(p);
}
} // destroyset释放结点
int inset(int elem, symset s)
{
s = s->next;
while (s && s->elem < elem)
s = s->next;
if (s && s->elem == elem)
return 1;
else
return 0;
} // inset
// EOF set.c
3 楼
rcdd [专家分:0] 发布于 2005-07-05 10:23:00
/************ PL0.c *************/
// pl0 compiler source code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "set.h"
#include "pl0.h"
//////////////////////////////////////////////////////////////////////
// print error message.
void error(n)
{
int i;
printf(" ");
for (i = 1; i <= cc - 1; i++)
printf(" ");
printf("^\n");
printf("Error %3d: %s\n", n, err_msg[n]);
err++;
} // error
//////////////////////////////////////////////////////////////////////
void getch(void)
{
if (cc == ll)
{
if (feof(infile))
{
printf("\nPROGRAM INCOMPLETE\n");
exit(1);
}
ll = cc = 0;
printf("%5d ", cx);
while (!feof(infile) && (ch = getc(infile))!='\n')
{
printf("%c", ch);
line[++ll] = ch;
} // while
printf("\n");
line[++ll] = ' ';
}
ch = line[++cc];
} // getch
//////////////////////////////////////////////////////////////////////
// gets a symbol from input stream.
void getsym(void)
{
int i, k;
char a[MAXIDLEN + 1];
while (ch == ' ')
getch();
if (isalpha(ch))
{ // symbol is a reserved word or an identifier.
k = 0;
do
{
if (k < MAXIDLEN)
a[k++] = ch;
getch();
}
while (isalpha(ch) || isdigit(ch));
a[k] = 0;
strcpy(id, a);
word[0] = id;
i = NRW;
while (strcmp(id, word[i--]));
if (++i)
sym = wsym[i]; // symbol is a reserved word
else
sym = SYM_IDENTIFIER; // symbol is an identifier
}
else if (isdigit(ch))
{ // symbol is a number.
k = num = 0;
sym = SYM_NUMBER;
do
{
num = num * 10 + ch - '0';
k++;
getch();
}
while (isdigit(ch));
if (k > MAXNUMLEN)
error(25); // The number is too great.
}
else if (ch == ':')
{
getch();
if (ch == '=')
{
sym = SYM_BECOMES; // :=
getch();
}
else
{
sym = SYM_NULL; // illegal?
}
}
else if (ch == '>')
{
getch();
if (ch == '=')
{
sym = SYM_GEQ; // >=
getch();
}
else
{
sym = SYM_GTR; // >
}
}
else if (ch == '<')
{
getch();
if (ch == '=')
{
sym = SYM_LEQ; // <=
getch();
}
else if (ch == '>')
{
sym = SYM_NEQ; // <>
getch();
}
else
{
sym = SYM_LES; // <
}
}
else
{ // other tokens
i = NSYM;
csym[0] = ch;
while (csym[i--] != ch);
if (++i)
{
sym = ssym[i];
getch();
}
else
{
printf("Fatal Error: Unknown character.\n");
exit(1);
}
}
} // getsym
//////////////////////////////////////////////////////////////////////
// generates (assembles) an instruction.
void gen(int x, int y, int z)
{
if (cx > CXMAX)
{
printf("Fatal Error: Program too long.\n");
exit(1);
}
code[cx].f = x;
code[cx].l = y;
code[cx++].a = z;
} // gen
//////////////////////////////////////////////////////////////////////
// tests if error occurs and skips all symbols that do not belongs to s1 or s2.
void test(symset s1, symset s2, int n)
{
symset s;
if (! inset(sym, s1))
{
error(n);
s = uniteset(s1, s2);
while(! inset(sym, s))
getsym();
destroyset(s);
}
} // test
//////////////////////////////////////////////////////////////////////
int dx; // data allocation index
// enter object(constant, variable or procedre) into table.
void enter(int kind)
{
mask* mk;
tx++;
strcpy(table[tx].name, id);
table[tx].kind = kind;
switch (kind)
{
case ID_CONSTANT:
if (num > MAXADDRESS)
{
error(25); // The number is too great.
num = 0;
}
table[tx].value = num;
break;
case ID_VARIABLE:
mk = (mask*) &table[tx];
mk->level = level;
mk->address = dx++;
break;
case ID_PROCEDURE:
mk = (mask*) &table[tx];
mk->level = level;
break;
} // switch
} // enter
//////////////////////////////////////////////////////////////////////
// locates identifier in symbol table.
int position(char* id)
{
int i;
strcpy(table[0].name, id);
i = tx + 1;
while (strcmp(table[--i].name, id) != 0);
return i;
} // position
//////////////////////////////////////////////////////////////////////
void constdeclaration()
{
if (sym == SYM_IDENTIFIER)
{
getsym();
if (sym == SYM_EQU || sym == SYM_BECOMES)
{
if (sym == SYM_BECOMES)
error(1); // Found ':=' when expecting '='.
getsym();
if (sym == SYM_NUMBER)
{
enter(ID_CONSTANT);
getsym();
}
else
{
error(2); // There must be a number to follow '='.
}
}
else
{
error(3); // There must be an '=' to follow the identifier.
}
}
error(4); // There must be an identifier to follow 'const', 'var', or 'procedure'.
} // constdeclaration
//////////////////////////////////////////////////////////////////////
4 楼
rcdd [专家分:0] 发布于 2005-07-05 10:23:00
void vardeclaration(void)
{
if (sym == SYM_IDENTIFIER)
{
enter(ID_VARIABLE);
getsym();
}
else
{
error(4); // There must be an identifier to follow 'const', 'var', or 'procedure'.
}
} // vardeclaration
//////////////////////////////////////////////////////////////////////
void listcode(int from, int to)
{
int i;
printf("\n");
for (i = from; i < to; i++)
{
printf("%5d %s\t%d\t%d\n", i, mnemonic[code[i].f], code[i].l, code[i].a);
}
printf("\n");
} // listcode
//////////////////////////////////////////////////////////////////////
void factor(symset fsys)
{
void expression();
int i;
symset set;
test(facbegsys, fsys, 24); // The symbol can not be as the beginning of an expression.
while (inset(sym, facbegsys))
{
if (sym == SYM_IDENTIFIER)
{
if ((i = position(id)) == 0)
{
error(11); // Undeclared identifier.
}
else
{
switch (table[i].kind)
{
mask* mk;
case ID_CONSTANT:
gen(LIT, 0, table[i].value);
break;
case ID_VARIABLE:
mk = (mask*) &table[i];
gen(LOD, level - mk->level, mk->address);
break;
case ID_PROCEDURE:
error(21); // Procedure identifier can not be in an expression.
break;
} // switch
}
getsym();
}
else if (sym == SYM_NUMBER)
{
if (num > MAXADDRESS)
{
error(25); // The number is too great.
num = 0;
}
gen(LIT, 0, num);
getsym();
}
else if (sym == SYM_LPAREN)
{
getsym();
set = uniteset(createset(SYM_RPAREN, SYM_NULL), fsys);
expression(set);
destroyset(set);
if (sym == SYM_RPAREN)
{
getsym();
}
else
{
error(22); // Missing ')'.
}
}
test(fsys, createset(SYM_LPAREN, SYM_NULL), 23);
} // while
} // factor
//////////////////////////////////////////////////////////////////////
void term(symset fsys)
{
int mulop;
symset set;
set = uniteset(fsys, createset(SYM_TIMES, SYM_SLASH, SYM_NULL));
factor(set);
while (sym == SYM_TIMES || sym == SYM_SLASH)
{
mulop = sym;
getsym();
factor(set);
if (mulop == SYM_TIMES)
{
gen(OPR, 0, OPR_MUL);
}
else
{
gen(OPR, 0, OPR_DIV);
}
} // while
destroyset(set);
} // term
//////////////////////////////////////////////////////////////////////
void expression(symset fsys)
{
int addop;
symset set;
set = uniteset(fsys, createset(SYM_PLUS, SYM_MINUS, SYM_NULL));
if (sym == SYM_PLUS || sym == SYM_MINUS)
{
addop = sym;
getsym();
term(set);
if (addop == SYM_MINUS)
{
gen(OPR, 0, OPR_NEG);
}
}
else
{
term(set);
}
while (sym == SYM_PLUS || sym == SYM_MINUS)
{
addop = sym;
getsym();
term(set);
if (addop == SYM_PLUS)
{
gen(OPR, 0, OPR_ADD);
}
else
{
gen(OPR, 0, OPR_MIN);
}
} // while
destroyset(set);
} // expression
//////////////////////////////////////////////////////////////////////
5 楼
rcdd [专家分:0] 发布于 2005-07-05 10:23:00
void condition(symset fsys)
{
int relop;
symset set;
if (sym == SYM_ODD)
{
getsym();
expression(fsys);
gen(OPR, 0, 6);
}
else
{
set = uniteset(relset, fsys);
expression(set);
destroyset(set);
if (! inset(sym, relset))
{
error(20);
}
else
{
relop = sym;
getsym();
expression(fsys);
switch (relop)
{
case SYM_EQU:
gen(OPR, 0, OPR_EQU);
break;
case SYM_NEQ:
gen(OPR, 0, OPR_NEQ);
break;
case SYM_LES:
gen(OPR, 0, OPR_LES);
break;
case SYM_GEQ:
gen(OPR, 0, OPR_GEQ);
break;
case SYM_GTR:
gen(OPR, 0, OPR_GTR);
break;
case SYM_LEQ:
gen(OPR, 0, OPR_LEQ);
break;
} // switch
} // else
} // else
} // condition
//////////////////////////////////////////////////////////////////////
void statement(symset fsys)
{
int i, cx1, cx2;
symset set1, set;
if (sym == SYM_IDENTIFIER)
{ // variable assignment
mask* mk;
if (! (i = position(id)))
{
error(11); // Undeclared identifier.
}
else if (table[i].kind != ID_VARIABLE)
{
error(12); // Illegal assignment.
i = 0;
}
getsym();
if (sym == SYM_BECOMES)
{
getsym();
}
else
{
error(13); // ':=' expected.
}
expression(fsys);
mk = (mask*) &table[i];
if (i)
{
gen(STO, level - mk->level, mk->address);
}
}
else if (sym == SYM_CALL)
{ // procedure call
getsym();
if (sym != SYM_IDENTIFIER)
{
error(14); // There must be an identifier to follow the 'call'.
}
else
{
if (! (i = position(id)))
{
error(11); // Undeclared identifier.
}
else if (table[i].kind == ID_PROCEDURE)
{
mask* mk;
mk = (mask*) &table[i];
gen(CAL, level - mk->level, mk->address);
}
else
{
error(15); // A constant or variable can not be called.
}
getsym();
}
}
else if (sym == SYM_IF)
{ // if statement
getsym();
set1 = createset(SYM_THEN, SYM_DO, SYM_NULL);
set = uniteset(set1, fsys);
condition(set);
destroyset(set1);
destroyset(set);
if (sym == SYM_THEN)
{
getsym();
}
else
{
error(16); // 'then' expected.
}
cx1 = cx;
gen(JPC, 0, 0);
statement(fsys);
code[cx1].a = cx;
}
else if (sym == SYM_BEGIN)
{ // block
getsym();
set1 = createset(SYM_SEMICOLON, SYM_END, SYM_NULL);
set = uniteset(set1, fsys);
statement(set);
while (sym == SYM_SEMICOLON || inset(sym, statbegsys))
{
if (sym == SYM_SEMICOLON)
{
getsym();
}
else
{
error(10);
}
statement(set);
} // while
destroyset(set1);
destroyset(set);
if (sym == SYM_END)
{
getsym();
}
else
{
error(17); // ';' or 'end' expected.
}
}
else if (sym == SYM_WHILE)
{ // while statement
cx1 = cx;
getsym();
set1 = createset(SYM_DO, SYM_NULL);
set = uniteset(set1, fsys);
condition(set);
destroyset(set1);
destroyset(set);
cx2 = cx;
gen(JPC, 0, 0);
if (sym == SYM_DO)
{
getsym();
}
else
{
error(18); // 'do' expected.
}
statement(fsys);
gen(JMP, 0, cx1);
code[cx2].a = cx;
}
test(fsys, phi, 19);
} // statement
//////////////////////////////////////////////////////////////////////
6 楼
rcdd [专家分:0] 发布于 2005-07-05 10:24:00
void block(symset fsys)
{
int cx0; // initial code index
mask* mk;
int block_dx;
int savedTx;
symset set1, set;
dx = 3;
block_dx = dx;
mk = (mask*) &table[tx];
mk->address = cx;
gen(JMP, 0, 0);
if (level > MAXLEVEL)
{
error(32); // There are too many levels.
}
do
{
if (sym == SYM_CONST)
{ // constant declarations
getsym();
do
{
constdeclaration();
while (sym == SYM_COMMA)
{
getsym();
constdeclaration();
}
if (sym == SYM_SEMICOLON)
{
getsym();
}
else
{
error(5); // Missing ',' or ';'.
}
}
while (sym == SYM_IDENTIFIER);
} // if
if (sym == SYM_VAR)
{ // variable declarations
getsym();
do
{
vardeclaration();
while (sym == SYM_COMMA)
{
getsym();
vardeclaration();
}
if (sym == SYM_SEMICOLON)
{
getsym();
}
else
{
error(5); // Missing ',' or ';'.
}
}
while (sym == SYM_IDENTIFIER);
// block = dx;
} // if
while (sym == SYM_PROCEDURE)
{ // procedure declarations
getsym();
if (sym == SYM_IDENTIFIER)
{
enter(ID_PROCEDURE);
getsym();
}
else
{
error(4); // There must be an identifier to follow 'const', 'var', or 'procedure'.
}
if (sym == SYM_SEMICOLON)
{
getsym();
}
else
{
error(5); // Missing ',' or ';'.
}
level++;
savedTx = tx;
set1 = createset(SYM_SEMICOLON, SYM_NULL);
set = uniteset(set1, fsys);
block(set);
destroyset(set1);
destroyset(set);
tx = savedTx;
level--;
if (sym == SYM_SEMICOLON)
{
getsym();
set1 = createset(SYM_IDENTIFIER, SYM_PROCEDURE, SYM_NULL);
set = uniteset(statbegsys, set1);
test(set, fsys, 6);
destroyset(set1);
destroyset(set);
}
else
{
error(5); // Missing ',' or ';'.
}
} // while
set1 = createset(SYM_IDENTIFIER, SYM_NULL);
set = uniteset(statbegsys, set1);
test(set, declbegsys, 7);
destroyset(set1);
destroyset(set);
}
while (inset(sym, declbegsys));
code[mk->address].a = cx;
mk->address = cx;
cx0 = cx;
gen(INT, 0, block_dx);
set1 = createset(SYM_SEMICOLON, SYM_END, SYM_NULL);
set = uniteset(set1, fsys);
statement(set);
destroyset(set1);
destroyset(set);
gen(OPR, 0, OPR_RET); // return
test(fsys, phi, 8); // test for error: Follow the statement is an incorrect symbol.
listcode(cx0, cx);
} // block
7 楼
rcdd [专家分:0] 发布于 2005-07-05 10:25:00
//////////////////////////////////////////////////////////////////////
int base(int stack[], int currentLevel, int levelDiff)
{
int b = currentLevel;
while (levelDiff--)
b = stack[b];
return b;
} // base
//////////////////////////////////////////////////////////////////////
// interprets and executes codes.
void interpret()
{
int pc; // program counter
int stack[STACKSIZE];
int top; // top of stack
int b; // program, base, and top-stack register
instruction i; // instruction register
printf("Begin executing PL/0 program.\n");
pc = 0;
b = 1;
top = 3;
stack[1] = stack[2] = stack[3] = 0;
do
{
i = code[pc++];
switch (i.f)
{
case LIT:
stack[++top] = i.a;
break;
case OPR:
switch (i.a) // operator
{
case OPR_RET:
top = b - 1;
pc = stack[top + 3];
b = stack[top + 2];
break;
case OPR_NEG:
stack[top] = -stack[top];
break;
case OPR_ADD:
top--;
stack[top] += stack[top + 1];
break;
case OPR_MIN:
top--;
stack[top] -= stack[top + 1];
break;
case OPR_MUL:
top--;
stack[top] *= stack[top + 1];
break;
case OPR_DIV:
top--;
if (stack[top + 1] == 0)
{
fprintf(stderr, "Runtime Error: Divided by zero.\n");
fprintf(stderr, "Program terminated.\n");
continue;
}
stack[top] /= stack[top + 1];
break;
case OPR_ODD:
stack[top] %= 2;
break;
case OPR_EQU:
top--;
stack[top] = stack[top] == stack[top + 1];
break;
case OPR_NEQ:
top--;
stack[top] = stack[top] != stack[top + 1];
case OPR_LES:
top--;
stack[top] = stack[top] < stack[top + 1];
break;
case OPR_GEQ:
top--;
stack[top] = stack[top] >= stack[top + 1];
case OPR_GTR:
top--;
stack[top] = stack[top] > stack[top + 1];
break;
case OPR_LEQ:
top--;
stack[top] = stack[top] <= stack[top + 1];
} // switch
break;
case LOD:
stack[++top] = stack[base(stack, b, i.l) + i.a];
break;
case STO:
stack[base(stack, b, i.l) + i.a] = stack[top];
printf("%d\n", stack[top]);
top--;
break;
case CAL:
stack[top + 1] = base(stack, b, i.l);
// generate new block mark
stack[top + 2] = b;
stack[top + 3] = pc;
b = top + 1;
pc = i.a;
break;
case INT:
top += i.a;
break;
case JMP:
pc = i.a;
break;
case JPC:
if (stack[top] == 0)
pc = i.a;
top--;
break;
} // switch
}
while (pc);
printf("End executing PL/0 program.\n");
} // interpret
8 楼
rcdd [专家分:0] 发布于 2005-07-05 10:25:00
//////////////////////////////////////////////////////////////////////
void main ()
{
FILE* hbin;
char s[80];
int i;
symset set, set1, set2;
printf("Please input source file name: "); // get file name to be compiled
scanf("%s", s);
if ((infile = fopen(s, "r")) == NULL)
{
printf("File %s can't be opened.\n", s);
exit(1);
}
phi = createset(SYM_NULL);
relset = createset(SYM_EQU, SYM_NEQ, SYM_LES, SYM_LEQ, SYM_GTR, SYM_GEQ, SYM_NULL);
// create begin symbol sets
declbegsys = createset(SYM_CONST, SYM_VAR, SYM_PROCEDURE, SYM_NULL);
statbegsys = createset(SYM_BEGIN, SYM_CALL, SYM_IF, SYM_WHILE, SYM_NULL);
facbegsys = createset(SYM_IDENTIFIER, SYM_NUMBER, SYM_LPAREN, SYM_NULL);
err = cc = cx = ll = 0; // initialize global variables
ch = ' ';
kk = MAXIDLEN;
getsym();
set1 = createset(SYM_PERIOD, SYM_NULL);
set2 = uniteset(declbegsys, statbegsys);
set = uniteset(set1, set2);
block(set);
destroyset(set1);
destroyset(set2);
destroyset(set);
destroyset(phi);
destroyset(relset);
destroyset(declbegsys);
destroyset(statbegsys);
destroyset(facbegsys);
if (sym != SYM_PERIOD)
error(9); // '.' expected.
if (err == 0)
{
hbin = fopen("hbin.txt", "w");
for (i = 0; i < cx; i++)
fwrite(&code[i], sizeof(instruction), 1, hbin);
fclose(hbin);
}
if (err == 0)
interpret();
else
printf("There are %d error(s) in PL/0 program.\n", err);
listcode(0, cx);
} // main END OF PL0.c
9 楼
lyid [专家分:0] 发布于 2005-07-13 15:48:00
程序编译时,有两个错:
一个在
void factor(symset fsys)
{
void expression();
int i;
symset set;
test(facbegsys, fsys, 24); // The symbol can not be as the beginning of an expression.
while (inset(sym, facbegsys))
{
if (sym == SYM_IDENTIFIER)
{
if ((i = position(id)) == 0)
{
error(11); // Undeclared identifier.
}
else
{
switch (table[i].kind)
{
mask* mk;
case ID_CONSTANT:
gen(LIT, 0, table[i].value);
break;
case ID_VARIABLE:
mk = (mask*) &table[i];
gen(LOD, level - mk->level, mk->address);
break;
case ID_PROCEDURE:
error(21); // Procedure identifier can not be in an expression.
break;
} // switch
}
getsym();
}
else if (sym == SYM_NUMBER)
{
if (num > MAXADDRESS)
{
error(25); // The number is too great.
num = 0;
}
gen(LIT, 0, num);
getsym();
}
else if (sym == SYM_LPAREN)
{
getsym();
set = uniteset(createset(SYM_RPAREN, SYM_NULL), fsys);
error~~~~~expression(set);~~~~~
destroyset(set);
if (sym == SYM_RPAREN)
{
getsym();
}
else
{
error(22); // Missing ')'.
}
}
test(fsys, createset(SYM_LPAREN, SYM_NULL), 23);
} // while
} // factor
中的expression(set);
错误为:function does not take 1 parameters
10 楼
lyid [专家分:0] 发布于 2005-07-13 15:54:00
另一个在main()中的exp = fopen("f:compiler:exp.txt", "r")
我将其该为
#include <fstream.h>
FILE* exp;
fstream file;
file.open("f:exp.txt");
就有错误提示,错误同上.
本人实在不理解,请指教,谢谢.
我来回复