哈工大软件学院编译原理实验1——词法分析

这次实验被“过来人”们定位非常easy,实验内容例如以下:

-----------------------------------------------------------------------------------

对例如以下工作进行展开描写叙述

(1) 给出语言的词法规则描写叙述

· 标识符、keyword、整常数、字符常数、浮点常数

· 单界符:+,-,×,;,…

· 双界符:/*,:=,>=,<=,!=,…

· 凝视

(2) 针对这样的单词的状态转换图和程序框图

(3) 核心数据结构的设计

如符号表、keyword等

(4) 错误处理

错误的位置及类型等

-----------------------------------------------------------------------------------

这次实验我是用python写了一个简单的C语言的词法分析器,词法分析器的编写有非常多种方式,比方能够用正則表達式编写,也能够用LEX工具自己主动生成,当然,也能够用比較朴素的方式——基于有穷自己主动机(Finite Automata,FA),也即基于有穷自己主动机的状态转移来编敲代码。

说起这个有穷自己主动机(Finite Automata,FA),真心感觉是个好东西,分析问题简单清晰,并且非常直观。记得对有穷自己主动机有感性认识是在上学期考试分数并不高的《计算机网络》课上,全龙哥讲那个RDT协议的不同版本号的时候,用这个自己主动机来表明遇到不同情况时发送端和接收端要採取的行动。

自己主动机的形式化定义:

M=(Q,Σ,δ,q0,F)

? Q→有穷状态集

? Σ→有穷输入字母表

? δ→从Q×Σ→2Q的映射函数(2Q是Q的幂集

? q0∈Q,是唯一的初态

? F →终态集合,是Q的子集

这里说说我个人的理解。对有穷自己主动机的形式化定义的理解比較重要的是上述第三条说明的理解:δ→从Q×Σ→2Q的映射函数。也即这个δ定义了某个详细FA的状态间转移关系,或者说定义了某个FA的状态间转移的规则。所谓状态的幂集就是状态集Q的全部子集构成的集族。则这句话的字面意思是:状态集和字母表的笛卡尔乘积到状态集的幂集的映射函数。

比方:M1 = (Q,Σ,δ,q0,F),当中Q = {q,q0,q1,q2...,qn},又((q,a) , {q1,q2,q3})∈δ,也即δ((q,a)) = {q1,q2,q3}。则说明自己主动机M1有一个状态q,q在遇到字母a的时候,自己主动机状态可能跳转到q1,q2,q3三个状态。自己主动机又分为有穷自己主动机和无穷自己主动机两种,这里不再赘述。

有穷自己主动机能够用状态图直观表示,样例见下文中图。

至于词法分析的一些基本知识,简单叙述一下:

-----------------------------------------------------------------------------------

定义:

词法分析器的功能输入源程序,依照构词规则分解成一系列单词符号。单词是语言中具有独立意义的最小单位,包含keyword、标识符、运算符、界符和常量等

(1) keyword 是由程序语言定义的具有固定意义的标识符。比如,Pascal 中的begin,end,if,while都是保留字。这些字通常不用作一般标识符。

(2) 标识符 用来表示各种名字,如变量名,数组名,过程名等等。

(3) 常数  常数的类型一般有整型、实型、布尔型、文字型等。

(4) 运算符 如+、-、*、/等等。

(5) 界符  如逗号、分号、括号、等等。

输出:

词法分析器所输出单词符号经常表示成例如以下的二元式:

(单词种别,单词符号的属性值)

单词种别通经常使用整数编码。标识符一般统归为一种。常数则宜按类型(整、实、布尔等)分种。keyword可将其全体视为一种。运算符可採用一符一种的方法。界符一般用一符一种的方法。对于每一个单词符号,除了给出了种别编码之外,还应给出有关单词符号的属性信息。单词符号的属性是指单词符号的特性或特征。

演示样例:

比方例如以下的代码段:

while(i>=j) i--;

经词法分析器处理后,它将被转为例如以下的单词符号序列:

   <while, _>
   <(, _>
   <id, 指向i的符号表项的指针>
   <>=, _>
   <id, 指向j的符号表项的指针>
   <), _>
   <id, 指向i的符号表项的指针>
   <--, _>
   <;, _>

词法分析分析器作为一个独立子程序:

词法分析是编译过程中的一个阶段,在语法分析前进行。词法分析作为一遍,能够简化设计,改进编译效率,添加?编译系统的可移植性。也能够和语法分析结合在一起作为一遍,由语法分析程序调用词法分析程序来获得当前单词供语法分析使用。

-----------------------------------------------------------------------------------

我写的这个词法分析器,不是非常健全,尤其是错误处理机制,像在字符串识别中,‘ab‘是C语言中不合法的char变量,可是我的词法分析器不能推断出错误,会死循环;此外,仅仅能识别出有限的keyword、有限形式的字符串(相信读者看懂我的状态机就知道哪里有限了),因为时间不够了,我不想再改了,以下贴出代码,供大家參考。

对了,贴代码之前,先说说我的词法分析器的状态机的设计。

我对“数字”的词法分析用了一个状态机,包含浮点数、整形数,状态机例如以下:

对“字符(串)”的识别用了一个状态机,包含keyword、char、以及char *,例如以下:

当然,对C语言的凝视的识别也用了一个状态机,必须先把源代码中的凝视cut掉才干进行分析,例如以下:

我对运算符的识别(包含双目和单目)没有採用明显的状态机,都是直接分析推断的,实际从某种意义上来讲对它们的分析也是採用了状态机的原理,仅仅是状态机结构比較简单,就没再显式用state表示,它们的状态机实际上例如以下:

以下上代码:

Scanner.py,作为主模块来运行:

‘‘‘
Created on 2012-10-18

@author: liushuai
‘‘‘
import string
import Category
import FileAccess

_currentIndex = 0
_Tokens = []
_prog = ""
_categoryNo = -1

_stateNumber = 0
_stateString = 0
_potentialNumber = ""
_potentialString = ""

def readComments(prog):
    ‘‘‘Read the comments of a program‘‘‘
    state = 0
    currentIndex, beginIndex, endIndex = (0, 0, 0)
    commentsIndexs = []
    for c in prog:
        if state == 0:
            if c == ‘/‘:
                beginIndex = currentIndex
                state = 1
            else:
                pass
        elif state == 1:
            if c == ‘*‘:
                state = 2
            else :
                state = 0
        elif state == 2:
            if c == ‘*‘:
                state = 3
            else:
                pass
        elif state == 3:
            if c == ‘*‘:
                pass
            elif c == ‘/‘:
                endIndex = currentIndex
                commentsIndexs.append([beginIndex, endIndex])
                state = 0 #set 0 state
            else:
                state = 2
        currentIndex += 1
    return commentsIndexs

def cutComments(prog, commentsIndexs):
    ‘‘‘cut the comments of the program prog‘‘‘
    num = len(commentsIndexs)
    if num == 0:
        return prog
    else :
        comments = []
        for i in xrange(num):
            comments.append(prog[commentsIndexs[i][0]:commentsIndexs[i][1] + 1])
        for item in comments:
            prog = prog.replace(item, "")
        return prog

def scan(helper):
    ‘‘‘scan the program, and analysis it‘‘‘
    global _stateNumber, _stateString, _currentIndex, _Tokens, _prog, _categoryNo, _potentialNumber, _potentialString
    currentChar = _prog[_currentIndex]
    ######################################CHAR STRING######################################
    if currentChar == ‘\‘‘ or currentChar == ‘\"‘ or currentChar in string.letters + "_$\\%\@"  or (currentChar in string.digits and _stateString != 0):
        if _stateString == 0:
            if currentChar == ‘\‘‘:
                _potentialString = "%s%s" % (_potentialString, currentChar)
                _stateString = 1
                _currentIndex += 1
            elif currentChar == "\"":
                _potentialString = "%s%s" % (_potentialString, currentChar)
                _stateString = 2
                _currentIndex += 1
            elif currentChar in string.letters + "$_":
                _potentialString = "%s%s" % (_potentialString, currentChar)
                _stateString = 7
                _currentIndex += 1
            else:
                _currentIndex += 1
                _stateNumber = 10
        elif _stateString == 1:
            if currentChar in string.letters + "#[email protected]%":
                _potentialString = "%s%s" % (_potentialString, currentChar)
                _stateString = 3
                _currentIndex += 1
            elif currentChar == ‘\\‘:
                _potentialString = "%s%s" % (_potentialString, currentChar)
                _stateString = 9
                _currentIndex += 1
            else:
                _currentIndex += 1
                _stateNumber = 10
        elif _stateString == 2:
            if currentChar in string.letters + "\\% ":
                _potentialString = "%s%s" % (_potentialString, currentChar)
                _stateString = 4
                _currentIndex += 1
            else:
                _currentIndex += 1
                _stateNumber = 10
        elif _stateString == 3:
            if currentChar == ‘\‘‘:
                _potentialString = "%s%s" % (_potentialString, currentChar)
                _stateString = 5
                _currentIndex += 1
            else:
                _currentIndex += 1
                _stateNumber = 10
        elif _stateString == 4:
            if currentChar == ‘\"‘:
                _potentialString = "%s%s" % (_potentialString, currentChar)
                _stateString = 6
                _currentIndex += 1
            elif currentChar in string.letters + "\\% ":
                _potentialString = "%s%s" % (_potentialString, currentChar)
                _stateString = 4
                _currentIndex += 1
            else:
                _currentIndex += 1
                _stateNumber = 10
        elif _stateString == 7:
            if currentChar in string.digits + string.letters + "$_":
                _potentialString = "%s%s" % (_potentialString, currentChar)
                _stateString = 8
                _currentIndex += 1
            else:
                _currentIndex += 1
                _stateNumber = 10
        elif _stateString == 8:
            if currentChar in string.digits + string.letters + "$_":
                _potentialString = "%s%s" % (_potentialString, currentChar)
                _stateString = 8
                _currentIndex += 1
            else:
                _currentIndex += 1
                _stateNumber = 10
        elif _stateString == 9:
            if currentChar in [‘b‘, ‘n‘, ‘t‘, ‘\\‘, ‘\‘‘, ‘\"‘]:
                _potentialString = "%s%s" % (_potentialString, currentChar)
                _stateString = 3
                _currentIndex += 1
            else:
                _currentIndex += 1
                _stateNumber = 10
        else:
            _currentIndex += 1
    ######################################  NUMBERS  ######################################
    elif currentChar in string.digits + ".":
        if _stateNumber == 0:
            if currentChar in "123456789":
                _potentialNumber = "%s%s" % (_potentialNumber, currentChar)
                _stateNumber = 6
                _currentIndex += 1
            elif currentChar == ‘0‘:
                _potentialNumber = "%s%s" % (_potentialNumber, currentChar)
                _stateNumber = 4
                _currentIndex += 1
            else:
                _stateNumber = 8
                _currentIndex += 1
        elif _stateNumber == 4:
            if currentChar == ‘.‘:
                _potentialNumber = "%s%s" % (_potentialNumber, currentChar)
                _stateNumber = 5
                _currentIndex += 1
            else:
                _stateNumber = 8
                _currentIndex += 1
        elif _stateNumber == 5:
            if currentChar in string.digits:
                _potentialNumber = "%s%s" % (_potentialNumber, currentChar)
                _stateNumber = 7
                _currentIndex += 1
            else:
                _stateNumber = 8
                _currentIndex += 1
        elif _stateNumber == 6:
            if currentChar in string.digits:
                _potentialNumber = "%s%s" % (_potentialNumber, currentChar)
                _stateNumber = 6
                _currentIndex += 1
            elif currentChar == ‘.‘:
                _potentialNumber = "%s%s" % (_potentialNumber, currentChar)
                _stateNumber = 5
                _currentIndex += 1
            else:
                _stateNumber = 8
                _currentIndex += 1
        elif _stateNumber == 7:
            if currentChar in string.digits:
                _potentialNumber = "%s%s" % (_potentialNumber, currentChar)
                _stateNumber = 7
                _currentIndex += 1
            else:
                _stateNumber = 8
                _currentIndex += 1
        else:
            _currentIndex += 1
    ######################################OTEAR OPERATERS######################################
    else:
        if _stateNumber == 6 or _stateNumber == 4:
            helper.outPutToken(_potentialNumber, "INT", Category.IdentifierTable["INT"])
        elif _stateNumber == 7:
            helper.outPutToken(_potentialNumber, "FLOAT", Category.IdentifierTable["FLOAT"])
        elif _stateNumber != 0:
            helper.outPutToken("ERROR NUMBER", "None", "None")
        _stateNumber = 0
        _potentialNumber = ""

        if _stateString == 7 or _stateString == 8:
            if _potentialString in Category.KeyWordsTable:
                helper.outPutToken(_potentialString, _potentialString.upper(), Category.IdentifierTable[_potentialString.upper()])
            else:
                helper.outPutToken(_potentialString, "IDN" , Category.IdentifierTable["IDN"])
                helper.setSymbolTable(_potentialString, "IDN" , Category.IdentifierTable["IDN"])
        elif _stateString == 5:
            helper.outPutToken(_potentialString, "CHAR", Category.IdentifierTable["CHAR"])
        elif _stateString == 6:
            helper.outPutToken(_potentialString, "CHAR *", Category.IdentifierTable["CHAR *"])
        elif _stateString != 0:
            helper.outPutToken("ERROR STRING", "None", "None")
        _stateString = 0
        _potentialString = ""

        if currentChar == " ":
            _currentIndex += 1
        elif currentChar == ‘>‘:
            _currentIndex += 1
            currentChar = _prog[_currentIndex]
            if currentChar == "=":
                helper.outPutToken(">=", ">=", Category.IdentifierTable[">="])
                _currentIndex += 1
            else :
                helper.outPutToken(">", ">", Category.IdentifierTable[">"])
        elif currentChar == ‘<‘:
            _currentIndex += 1
            currentChar = _prog[_currentIndex]
            if currentChar == "=":
                helper.outPutToken("<=", "<=", Category.IdentifierTable["<="])
                _currentIndex += 1
            else :
                helper.outPutToken("<", "<", Category.IdentifierTable["<"])
        elif currentChar == ‘+‘:
            _currentIndex += 1
            currentChar = _prog[_currentIndex]
            if currentChar == ‘+‘:
                helper.outPutToken("++", "++", Category.IdentifierTable["++"])
                _currentIndex += 1
            else :
                helper.outPutToken("+", "+", Category.IdentifierTable["+"])
        elif currentChar == ‘-‘:
            _currentIndex += 1
            currentChar = _prog[_currentIndex]
            if currentChar == ‘-‘:
                helper.outPutToken("--", "--", Category.IdentifierTable["--"])
            else:
                helper.outPutToken("-", "-", Category.IdentifierTable["-"])
        elif currentChar == ‘=‘:
            _currentIndex += 1
            currentChar = _prog[_currentIndex]
            if currentChar == ‘=‘:
                helper.outPutToken("==", "==", Category.IdentifierTable["=="])
                _currentIndex += 1
            else :
                helper.outPutToken("=", "=", Category.IdentifierTable["="])
        elif currentChar == ‘!‘:
            _currentIndex += 1
            currentChar = _prog[_currentIndex]
            if currentChar == ‘=‘:
                helper.outPutToken("!=", "!=", Category.IdentifierTable["!="])
                _currentIndex += 1
            else :
                helper.outPutToken("!", "!", Category.IdentifierTable["!"])
        elif currentChar == ‘&‘:
            _currentIndex += 1
            currentChar = _prog[_currentIndex]
            if currentChar == ‘&‘:
                helper.outPutToken("&&", "&&", Category.IdentifierTable["&&"])
                _currentIndex += 1
            else :
                helper.outPutToken("&", "&", Category.IdentifierTable["&"])
        elif currentChar == ‘|‘:
            _currentIndex += 1
            currentChar = _prog[_currentIndex]
            if currentChar == ‘|‘:
                helper.outPutToken("||", "||", Category.IdentifierTable["||"])
                _currentIndex += 1
            else :
                helper.outPutToken("|", "|", Category.IdentifierTable["||"])
        elif currentChar == ‘*‘:
            helper.outPutToken("*", "*", Category.IdentifierTable["*"])
            _currentIndex += 1
        elif currentChar == ‘/‘:
            helper.outPutToken("/", "/", Category.IdentifierTable["/"])
            _currentIndex += 1
        elif currentChar == ‘;‘:
            helper.outPutToken(";", ";", Category.IdentifierTable[";"])
            _currentIndex += 1
        elif currentChar == ",":
            helper.outPutToken(",", ",", Category.IdentifierTable[","])
            _currentIndex += 1
        elif currentChar == ‘{‘:
            helper.outPutToken("{", "{", Category.IdentifierTable["{"])
            _currentIndex += 1
        elif currentChar == ‘}‘:
            helper.outPutToken("}", "}", Category.IdentifierTable["}"])
            _currentIndex += 1
        elif currentChar == ‘[‘:
            helper.outPutToken("[", "[", Category.IdentifierTable["["])
            _currentIndex += 1
        elif currentChar == ‘]‘:
            helper.outPutToken("]", "]", Category.IdentifierTable["]"])
            _currentIndex += 1
        elif currentChar == ‘(‘:
            helper.outPutToken("(", "(", Category.IdentifierTable["("])
            _currentIndex += 1
        elif currentChar == ‘)‘:
            helper.outPutToken(")", ")", Category.IdentifierTable[")"])
            _currentIndex += 1

if __name__ == ‘__main__‘:
    helper = FileAccess.FileHelper("H://test.c", "H://token.txt", "H://symbol_table.txt")
    prog = helper.readProg()
    print prog
    comments = readComments(prog)
    _prog = cutComments(prog, comments)
    print _prog
    while _currentIndex < len(_prog):
        scan(helper)
    helper.closeFiles()

Category.py,这个模块里面定义了一些C语言中的keyword、运算符等等,是种别码表:

‘‘‘
Created on 2012-10-18

@author: liushuai
‘‘‘
IdentifierTable = {"INT":1,"FLOAT":2,"CHAR":3,"IDN":4,"WHILE":5,"FOR":6,"DO":7,"BREAK":31,"CONTINUE":32,"CHAR *":33,"IF":37,
                   "*":8,"/":9,"+":10,"-":11,">":12,"<":13,"=":14,
                   "++":15,"--":16,"==":17,"!=":18,">=":19,"<=":20,
                   "&&":28,"||":29,"!":30,"&":35,"|":36,
                   ";":21,",":34,
                   "{":22,"}":23,"[":24,"]":25,"(":26,")":27}
KeyWordsTable = ("int", "float", "char", "while", "for", "do","break","continue","char *","if")

FileAccess.py,里面定义了一个类用来进行对文件的操作,比如输出Token序列以及符号表到文件:

‘‘‘
Created on 2012-10-23

@author: liushuai
‘‘‘

import Category

class FileHelper(object):
    def __init__(self,progPath,tokenPath,symbolTablePath):
        self.progPath = progPath
        self.tokenPath = tokenPath
        self.symbolTablePath = symbolTablePath

        self.tokenFp = open(self.tokenPath,"w")
        self.symbolTableFp = open(self.symbolTablePath,"w")

        self.symbolTable = {}.fromkeys(Category.KeyWordsTable) #initialize symbol table
        print self.symbolTable

    def readProg(self):
        ‘‘‘read the program into the RAM‘‘‘
        fp = open(self.progPath, "r+")
        prog = ""
        for eachLine in fp.readlines():
            #print eachLine
            prog = "%s%s" % (prog, eachLine.strip())
        fp.close()
        return prog

    def outPutToken(self,tokenSelf,tokenInner,tokenNo):
        ‘‘‘output token into a file‘‘‘
        self.tokenFp.write("(" + tokenInner + "," + tokenSelf + ")" + "\n")
        print "(" + tokenInner + "," + tokenSelf + ")"

    def setSymbolTable(self,tokenSelf,tokenInner,tokenNo):
        ‘‘‘output symbol into symbol table‘‘‘
        if not self.symbolTable.has_key(tokenSelf):
            self.symbolTable[tokenSelf] = None

    def writeSymbolToFile(self):
        for k in self.symbolTable:
            self.symbolTableFp.write(k + "\n")

    def closeFiles(self):
        ‘‘‘close token Files‘‘‘
        self.writeSymbolToFile()
        if self.tokenFp != None:
            self.tokenFp.close()
        if self.symbolTableFp != None:
            self.symbolTableFp.close()

以下是我的測试C语言程序:

int main ()
{
    char  str[10000];
    int num[30]={0};
    char std[28]={"abcdefghijklmnopqrstuvwxyz"};
    int i,j,temp;
    float test=-0.34;
    float test1=23.45;

    char tom;
    for (i=0;i<1000;i++)             /*字符的读入*/
    {
        str[i]=getchar();
        if (str[i]==‘\n‘)
        break;
    }
    for (i=0;i<10000;i++)             /*字符的统计数量*/
    {
        if (str[i]==‘\n‘)
        break;
        j=str[i] - 97; /*-97 or sth - 97?*/
        num[j]++;
    }
    for (i=0;i<27;i++)              /*字符的按出现频率排序*/
    {
        for (j=i+1;j<26;j++)
        {
            if (num[j]>num[i])
            {
                temp=num[j];
                num[j]=num[i];
                num[i]=temp;

                tom=std[j];
                std[j]=std[i];
                std[i]=tom;
            }
        }
    }
    for (i=0;i<27;i++)                     /*字符的按字母表顺序排序*/
    {
        for (j=i+1;j<26;j++)
        {
            if (num[i]==num[j])
            {
                if (std[j]<std[i])
                {
                    tom=std[j];
                    std[j]=std[i];
                    std[i]=tom;
                }
            }
        }
    }
    for (i=0;i<29;i++)
    {
        if (num[i]==0)
        break;
    }

}

最后脚本输出例如以下:

Token.txt:

Symbol_table.txt:

这次实验就算做完了。

尽管完毕的非常水,可是正确情况下的输出还是令人惬意的,词法分析完事后,等着句法分析调用它的输出结果吧。对了,至于符号表在整个编译阶段的作用,龙书第一版2.4节和6.7节有介绍,请读者查阅。

写的非常水非常水,如有不足,欢迎指正。

哈工大软件学院编译原理实验1——词法分析

时间: 2024-09-28 17:10:05

哈工大软件学院编译原理实验1——词法分析的相关文章

编译原理实验之词法分析

能识别小数,科学记数法表示的数. 不多解释,代码先上: #include <cstdio> #include <iostream> #include <string> #include <cstring> #include <algorithm> #include <cctype> #include <fstream> #include <map> #include <cstdlib> #inclu

编译原理实验代码(词法分析,语法分析,中间代码生成)

花了一天写出的程序没有顾及很多层面,但对于理解基本的实验道理和交上实验还是有点帮助的.代码实现了基于有限自动机的词法分析,采用递归下降分析法和EBNF文法实现语法分析并生成中间代码. lexAnalysis.h /* * lexAnalysis.h * * Created on: 2014-12-2 * Author: liuqiushan */ #ifndef LEXANALYSIS_H_ #define LEXANALYSIS_H_ #include <stdio.h> #include

Java 实现《编译原理》简单词法分析功能

Java 实现<编译原理>简单词法分析功能 简易词法分析功能 要求及功能 (1)读取一个 txt 程序文件(最后的 # 作为结束标志,不可省去) { int a, b; a = 10; if(a>=1){ b = a + 20; } } (2)词法识别分析表 单词类别|单词自身值|内部编码 -|-|- 关键字| int.for.while.do.return.break.continue| 1 标识符| 除关键字外的以字母开头,后跟字母.数字的字符序列| 2 常数| 无符号整型数| 3

编译原理 实验3 语法分析

语法分析 一. 实验目的 算术表达式的文法可以是(你可以根据需要适当改变): E→E+E|E-E|E*E|E/E|(E)|i 根据算符优先分析法,将表达式进行语法分析,判断一个表达式是否正确. 二. 实验环境 操作系统:window xp 编写环境:visual c++ 编写语言:c语言 三. 实验内容 程序输入/输出示例: 如参考C语言的运算符.输入如下表达式(以分号为结束)和输出结果: (1)10; 输出:正确 (2)1+2; 输出:正确 (3)(1+2)/3+4-(5+6/7); 输出:正

吉首大学_编译原理实验题_基于预測方法的语法分析程序的设计【通过代码】

一.实验要求 实验二 基于预測方法的语法分析程序的设计 一.实验目的 了解预測分析器的基本构成及用自顶向下的预測法对表达式进行语法分析的方法,掌握预測语法分析程序的手工构造方法. 二.实验内容 1.了解编译程序的基于预測方法的语法分析过程. 2.依据预測分析原理设计一个基于预測方法的语法分析程序. 三.实验要求 对给定文法G[S]: S->AT       A->BU     T->+AT|$      U->*BU|$    B->(S)|m 当中,$表示空串. 1.推断上

编译原理实验二:LL(1)语法分析器

一.实验要求 不得不想吐槽一下编译原理的实验代码量实在是太大了,是编译原理撑起了我大学四年的代码量... 这次实验比上次要复杂得多,涵盖的功能也更多了,我觉得这次实验主要的难点有两个(其实都是难点...): 1. 提取左公因子或消除左递归(实现了消除左递归) 2. 递归求First集和Follow集 其它的只要按照课本上的步骤顺序写下来就好(但是代码量超多...),下面我贴出实验的一些关键代码和算法思想. 二.基于预测分析表法的语法分析 2.1 代码结构 2.1.1  Grammar类    功

编译原理 实验1 PL/0语言词法分析

PL/0语言词法分析 一. 实验目的 通过完成词法分析程序,了解词法分析的过程.编制一个读单词程序,对PL/0语言进行词法分析,把输入的字符串形式的源程序分割成一个个单词符号,即基本保留字.标识符.常数.运算符.界符五大类. 二. 实验环境 操作系统:window xp 编写环境:visual c++ .c-free.turbo c 编写语言:c语言 分析语言:PL/0 三. 实验内容 对PL/0语言进行词法分析,把输入的字符串形式的源程序分割成一个个单词符号,其词法描述如下: (1) 关键字:

编译原理 - 实验三 - 递归下降语法分析器的调试及扩展

一. 语法分析介绍 语法分析是编译过程的核心部分,它的主要任务是按照程序语言的语法规则,从由词法分析输出的源程序符号串中识别出各类语法成分,同时进行语法检查,为语义分析和代码生成做准备.执行语法分析任务的程序叫语法分析程序或语法分析器. 二. 所实现的语义分析和代码生成程序能处理什么语句 (1)简单变量的声明语句 (2)表达式语句 (3)if语句. (4)while语句 (5)for语句 (6)write语句 (7)read语句 (8)do语句. (9)处理过程调用和返回 三.实验过程 ①用VC

编译原理小作业词法分析程序

词法分析程序所参照的编码如70页表3.3 (<编译技术>张莉等著.--北京:高等教育出版社,2016.9.ISBN: 978-7-04-046317-0) 用Java语言实现如下: 1 import java.io.IOException; 2 import java.util.Arrays; 3 import java.util.HashMap; 4 import java.util.Map; 5 6 class Code{ 7 public static final int BEGINSY