回 帖 发 新 帖 刷新版面

主题:请高手帮帮忙!对PL/0语言及其编译器进行扩充和修改(有源代码)

《编译原理》要求你对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个回复)

沙发


附源程序:

/************  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


板凳

/************  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 楼

/************  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 楼

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 楼

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 楼

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 楼

//////////////////////////////////////////////////////////////////////
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 楼

//////////////////////////////////////////////////////////////////////
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 楼

程序编译时,有两个错:
一个在
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 楼

另一个在main()中的exp = fopen("f:compiler:exp.txt", "r")
我将其该为
#include <fstream.h>
FILE* exp;
fstream file;
file.open("f:exp.txt");
就有错误提示,错误同上.


本人实在不理解,请指教,谢谢.

我来回复

您尚未登录,请登录后再回复。点此登录或注册