精华内容
下载资源
问答
  • 词法分析器实验报告

    2013-03-29 17:44:00
    词法分析器实验报告 1.实验平台: visualstudio2010 2.实验目的 设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。 3.数字状态转换图: 4本程序自行规定: (1)关键字"begin",...

    词法分析器实验报告

    1.实验平台:

    visual studio 2010

    2.实验目的

     设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。

    3.数字状态转换图:

    4本程序自行规定:

    (1)关键字"begin","end","if","then","else","while","write","read",

    "do", "call","const","char","until","procedure","repeat"

    (2)运算符:"+","-","*","/","="

    (3)界符:"{","}","[","]",";",",",".","(",")",":"

    (4)其他标记 如字符串,表示以字母开头的标识符。
    (5)空格、回车、换行符跳过。

    5.程序源代码:

    源文件主要放在三个文件中:stdafx.h主要存放头文件stdafx.cpp主要存放函数的定义Compilertest.cpp 主函数定义

    // stdafx.h : 标准系统包含文件的包含文件,

    // 或是经常使用但不常更改的

    // 特定于项目的包含文件

    #pragma once

    #include "targetver.h"

    #include <stdio.h>

    #include <tchar.h>

    #include <iostream>

    #include <fstream>

    #include <string>

    #include "compiler.h"

    using namespace std;

    int const keyLength=26;                     //定义关键字数组的大小

    int const OPLENGTH1=8;                      //定义运算符数组大小

    int const JLENGTH=9;                        //定义界符数组的大小

    int const BFLENGTH=640;                     //定义双缓冲数组大小

    //函数声明

    char firstRead();                           //首次读取

    char getChar();                             //读取一个字符

    bool isLetter(char C);                      //判断字符串

    bool isDigit(char C);                       //判断数字

    bool isUnderLine(char C);                   //判断是否为下划线

    bool isKeyLetter(string str);               //判断关键字

    bool isJieFu(char C);                       //判断界符

    bool isOperator(char C);                    //判断运算符

    void back();                                //当前指针向前退一个

    void myPrint(string s1,string s2);          //自定义文件输出函数

    char ciFaFenXi(char now);                   //词法分析函数

    void  readFBiao( );                         //读取符号表

    bool inGuanJianBiao(string fuhaobiao[2][600],string str);

    bool inBainLiangBiao(string fuhaobiao[2][600],string str);

    stdafx.cpp :

    // stdafx.cpp : 只包括标准包含文件的源文件

    // Compilertest.pch 将作为预编译头

    // stdafx.obj 将包含预编译类型信息

    #include "stdafx.h"

    char buffer1[BFLENGTH];     //双缓冲1

    char buffer2[BFLENGTH];     //双缓冲2

    //定义符号表的当前大小

    int fcount1=0;

    int fcount2=0;

    //定义关键字数组

    string keyStr[keyLength]={"cout","cin","this","if","else","while","true","false","iostream","new","main","infile","std","endl",

        "using","namespace","char","int","double","float","bool","return","include","public","class","void"};

    //定义变量

    char myOperator1[OPLENGTH1]={'>','<','+','-','*','/','=','!'};      //运算符数组

    char jiefu[JLENGTH]={'{','}','(',')',':',';','.','#',','};          //界符

    //定义文件读取,输出流变量

    ifstream infile("G://a.txt",ios::binary);

    ofstream outfile("G://b.txt",ios::binary);

    char now;                                                           //储存当前字符

    string token="";                                                    //用于存放字符串

    char *startP,*forwardP;                                             //定义开始和向前指针

    string fuhaobiao[2][600];                                           //定义一个符号表(存放标识符)

    //判断C是否为字母

    bool isLetter(char C){

        if ((C>='a'&&C<='z')||(C>='A'&&C<='Z')){

            return true;

        }

        else return false;

    }

    //判断是否为数字

    bool isDigit(char C){

        if(C>='0'&&C<='9'){

            return  true;

        }else 

            return false;

    }

    //判断是否为界符

    bool isJieFu(char C){

        

        for (int i=0;i<JLENGTH;i++){

            if (C==jiefu[i]){

                return true;

            }else 

                continue;

        }

        return false;

    }

    //判断是否为运算符

    bool isOperator(char C){

        for (int i=0;i<OPLENGTH1;i++){

            if (C==myOperator1[i]){

                return true;

            }else 

                continue;

        }

        return false;

    }

    //判断是否为下划线

    bool isUnderLine(char C){

        if(C=='_'){

            return  true;

        }else 

            return false;

    }

    //判断是否为系统关键字

    bool isKeyLetter(string str){

        for(int i=0;i<keyLength;i++){

            if (str==keyStr[i]){

                return true;

            }

        }

        return false;

    }

    //自定义输出函数

    void myPrint(string s1,string s2){

            if (!outfile){

        cout <<"文件打开失败"<<endl;

        exit(1);

        }

            

        cout<<"< "<<s1<<" , "<<s2<<" >\r\n"<<endl;    

        outfile<<"< "<<s1<<" , "<<s2<<" >\r"<<endl;

    }

    //定义遍历符号表函数

    void readFBiao(  ){

        for (int i=0;i<2;i++){

            if (i==0){       //遍历关键字符号表

                for (int j=0;j<fcount1;j++){

                cout<<fuhaobiao[i][j]<<endl;

                }

            }

            //变量符号表

            if (i==1){      //遍历变量符号表

                for (int j=0;j<fcount2;j++){

                    if (j==0){

                    cout<<"输出变量表中的内容!"<<endl;

                    }

                cout<<fuhaobiao[i][j]<<endl;

                }

            }   

        }

    }

    //定义查看是否存在符号表中的函数

    bool inGuanJianBiao(string fuhaobiao[2][600],string str){   

                for (int j=0;j<fcount1;j++){

                    if (str==fuhaobiao[0][j]){

                    return true;

                    }

                }

                return false;

    }

    bool inBainLiangBiao(string fuhaobiao[2][600],string str){  

                for (int j=0;j<fcount2;j++){

                    if (str==fuhaobiao[1][j]){

                    return true;

                    }

                }

                return false;

    }

    char firstRead(){

    buffer1[BFLENGTH-1]=EOF;

        buffer2[BFLENGTH-1]=EOF;

        if (!infile){

        cout <<"文件打开失败"<<endl;

        exit(1);

        }

        forwardP=buffer1;//让指针指向第一个缓冲区

        //把字符读入buffer1

        for(int i=0;i<BFLENGTH-2;i++){

            if(infile.get(buffer1[i])){

            }else{

                infile.close();

                buffer1[i]=EOF;

                break;

            }   

        }

        now= getChar();

        return now;

    }

    //定义词法分析函数

     char ciFaFenXi(char now){

        //循环获取

        while(1){

            while (now==' '){now=getChar(); }

            if (now=='\r'){                     //判断换行符

                now=getChar();

                if (now=='\n'){now=getChar();}          

                continue;

            }else if(now==EOF) {return EOF ;

            }else if (isLetter(now)){          //判断字符串

                token+=now;

                now=getChar();

                while(isLetter(now)||isDigit(now)||isUnderLine(now)){

                    token+=now;

                    now=getChar();

                }   

                if (isKeyLetter(token)){        //判断关键字类型

                    myPrint(token,"关键字");

                    if (!inGuanJianBiao( fuhaobiao,token)){

                    fuhaobiao[0][fcount1++]=token;    ///加入符号表中

                    }

                }else{

                    myPrint(token,"变量");

                    if (!inBainLiangBiao( fuhaobiao,token)){

                        fuhaobiao[1][fcount2++]=token; 

                    }

                }

                token="";

                return now;

            }else if (isDigit(now)){            //判断整数

                token+=now;

                now=getChar();

                while(isDigit(now)){

                    token+=now;

                    now=getChar();

                }

                if (now=='.'){                  //判断小数

                    token+=now;

                    now=getChar();

                    while(isDigit(now)){

                        token+=now;

                        now=getChar();

                    }

                    myPrint(token,"小数");

                    token="";

                    return now;

                }

                myPrint(token,"整数");

                token="";

               return now;

            }else if (isJieFu(now)){             //判断界符

                string result;

                myPrint(result.assign(1,now),"界符");

                now=getChar();

                return now;

            }else if (isOperator(now)){         //判断运算符

                token+=now;

                now=getChar();

                if (now=='='){

                    token+=now;

                    now=getChar();

                    myPrint(token,"双目运算符");

                    token="";

                    return now;

                }

                if(token!="!")

                myPrint(token,"单目运算符");

                else myPrint(token,"其他");

                token="";

                

                return now;

            }else {

                string result;

                myPrint(result.assign(1,now),"其他");

                now=getChar();

                return now;

            }

            return now;

        }

        infile.close();

    }

    //自定义getChar()函数,运用了双缓冲,有两个字符数组作为缓冲区

    char getChar(){

        char next;//定义储存下一个读入的字符    

        if(*forwardP==EOF){//如果到缓冲区末尾,但不知是哪个缓冲区尾

            if (forwardP==buffer1+BFLENGTH-1){//如果到了buffer1的末尾

                //读入buffer2

                for(int i=0;i<BFLENGTH-1;i++){

                    if(infile.get(buffer2[i])){

        

                    }else{

                        infile.close();

                        buffer2[i]=EOF;

                        break;

                        //exit(1);

                    }

                }

                forwardP=buffer2;

                getChar();

            

            }else if (forwardP==buffer2+BFLENGTH-1){//如果到了buffer2的末尾

                //读入buffer1

                for(int i=0;i<BFLENGTH-1;i++){

                    if(infile.get(buffer1[i])){

                    //cout<<buffer1[i]<<"";

                    }else{

                        //cout<<endl<<"The file is end!!!!!!!!!";

                        infile.close();

                        buffer1[i]=EOF;

                        break;

                        //exit(1);

                    }

                }

            

                forwardP=buffer1;

                getChar();

            

            }else{

                infile.close();     

                return EOF;

            //exit(1);

            }

        }else{

            if (*forwardP==EOF){

                exit(1);

            }

            next=*forwardP;//把他付给next

            //cout<<next;

            forwardP+=1;//向下走一个

            return next;

        }

    }

    //定义后退一个函数

    void back(){

        if(forwardP==buffer1){//如果当前指针指向buffer1的开头

            forwardP=buffer2+BFLENGTH-2;//转而指向buffer2的末尾

        }else if(forwardP==buffer2){

            forwardP=buffer1+BFLENGTH-2;//转而指向buffer1的末尾

        }else {

            forwardP-=1;

        }   }

    Compilertest.cpp主函数:

    // Compilertest.cpp : 定义控制台应用程序的入口点。

    //

    //@author lixingle

    //词法分析器小程序

    #include "stdafx.h"

    using namespace std;

    char nextC;

    int main(){

     nextC= firstRead();

     //调用词法分析函数  

      while(nextC!=EOF)

      nextC=ciFaFenXi(nextC);

     //遍历符号表

      cout <<"遍历符号表开始!"<<endl;

      readFBiao( );

      return 0;

    }

    4.测试结果:


    转载于:https://www.cnblogs.com/lixingle/archive/2013/03/29/3312993.html

    展开全文
  • 词法分析器,使用c++编写,编译原理词法分析器实验报告完整版
  • 编译原理_词法分析器实验报告编译原理_词法分析器实验报告
  • 编译原理词法分析器实验报告含源代码,还有状态转换图。C语言实现
  • 编译原理实验报告 题目 C_minus语言词法分析器 学 院计算机科学与技术 专 业 XXXXXXXXXXXXXXXX 学 号 XXXXXXXXXXXX 姓 名 XXXX 指导教师 XXXX 20xx年xx月xx日 C minus语言词法分析器 一实验目的 理解词法分析器的...
  • 用C语言编写一个PL/0词法分析器,为语法语义分析提供单词,使之能把输入的字符串形式的源程序分割成一个个单词符号传递给语法语义分析,并把分析结果(基本字,运算符,标识符,常数以及界符)输出。
  • 编译原理课程中词法分析器实验报告,含详细的源码及分析
  • JS词法分析器实验报告

    千次阅读 2016-10-19 15:34:26
    1.实验环境 ...用Javascipt实现词法分析器,首先是读取文件,然后把读入的字符转为数组形式,遍历数组。 如果读到字母,就读完余下连续的字母或数字,然后以此与关键字表中元素进行对比,如果是关键字

    1.实验环境

    Linux系统  WebStorm环境

    2.实验目的

    设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解

    3.单词分类表

    4.单词状态表

    5.算法描述

    用Javascipt实现词法分析器,首先是读取文件,然后把读入的字符转为数组形式,遍历数组。

    如果读到字母,就读完余下连续的字母或数字,然后以此与关键字表中元素进行对比,如果是关键字输出该关键字的序列号与关键字,如果不是关键字再与标示符中的元素对比,如果标示符中存在则输出该标示符的序列号与标示符,如果不存在则加入标示符数组且输出序列号与该字符。

    如果读到是数字则读完余下的数字,输出num与该数字。

    读到的若是符号则与符号数组对比输出该符号的序列号与符号。

    若不在以上的范围内则输出0。

    6.程序结构

    8.运行结果


    9.调试情况

    开始的时候在读文件时,读到里文件可是后面的代码调用文件为undefine,后来调试里很长时间才明白是出现异步情况,所以就修改了代码的整体结构,读完文件直接调用,都放在了一个循环里面。

    10.设计技巧及体会

    设计技巧:读到数据直接输出更为方便,放在数组里最后统一输出反而更麻烦而且容易出错。

    体会:写了很久的词法分析器,从开始的懵懵懂懂到现在已经彻底明白,写代码的过程中遇到了很多麻烦,从开始的读文件到遍历以及最后的输出都不是很顺利,一边边的测试打断点,最后总算完成,很开心。

    11.源程序清单


    代码文件:

    var fs = require('fs');
    function allNames() {
        var ch = '';
        var text;
        var sertID = ['var', 'function', 'if', 'else', 'return', 'true', 'false'];
        var dotID = [',', '(', ')', '{', '}','\'',':']
        var sertConst = [];
    
        fs.readFile('input.js', 'UTF-8', function (err, data) {
                text = data.toString().split('');
    
                for (var i = 0; i < text.length;) {
                    var strToken = '';
                    ch = text[i];
                    var tag = 0;
                    if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
    
                        while ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
                            strToken += ch;
                            i += 1;
                            ch = text[i];
                        }
    
                        for (var j = 0; j < sertID.length; j++) {
    
                            if (sertID[j] === strToken && tag === 0) {
                                console.log(strToken, 'sertID' + j)
                                tag = 1;
                            }
                        }
    
                        if (sertConst.length === 0 && tag === 0) {
                            sertConst.push(strToken);
                            console.log(strToken, 'sertConst' + 0)
                            tag = 1;
                        }
    
                        if (sertConst.length != 0 && tag === 0) {
                            for (var t = 0; t < sertConst.length; t++) {
    
                                if (sertConst[t] === strToken && tag === 0) {
                                    tag = 1;
                                    console.log(strToken, 'sertConst' + t)
                                    break;
                                }
                                else {
                                    sertConst.push(strToken);
                                    tag = 1;
                                    var put = sertConst.length - 1
                                    console.log(strToken, 'sertConst' + put)
                                    break;
                                }
                            }
                        }
                    }
                    else if (ch >= '0' && ch <= '9') {
                        while (ch >= '0' && ch <= '9') {
                            strToken += ch;
                            i += 1;
                            ch = text[i];
                        }
                        console.log(strToken, 'num')
                        tag = 1;
                    }
    
                    for (var d = 0; d < dotID.length; d++) {
                        if (dotID[d] === ch) {
                            console.log(ch, 'dotID' + d)
                            i++;
                            tag = 1;
                            break;
                        }
                    }
    
                    if (tag === 0) {
                        console.log('0');
                        i++;
                    }
    
    
                }
            }
        )
    }
    
    allNames()
    
    
    被读文件:
    function put(){
        return 'hello'
    }

    
    

    展开全文
  • c语言 词法分析器实验报告及源代码

    热门讨论 2011-05-03 20:36:58
    一个详细的由c++ 编写的c语言词法分析器实验报告,报告后附带有C++源代码。在vc++6.0 及visual studio 2010环境中调试通过的win32 应用程序。
  • 编译原理涉及词法分析,语法分析,语义分析及优化设计等各方面。...执行词法分析的程序称为词法分析器,也称为扫描器。词法分析是所有分析优化的基础,涉及的知识较少,如状态转换图等,易于实现。
  • 实验一、词法分析实验 商业软件工程专业 张树恒 201506110093 一、 实验目的 通过设计一个词法分析程序,对词法进行分析,加强对词法的理解,掌握对程序设计语言的分解和理解。 二、 实验内容和要求 在原程序中...

    实验一、词法分析实验

    商业软件工程专业   张树恒  201506110093

    一、        实验目的

    通过设计一个词法分析程序,对词法进行分析,加强对词法的理解,掌握对程序设计语言的分解和理解。

    二、        实验内容和要求

    在原程序中输入源代码

    • 对字符串表示的源程序 
    • 从左到右进行扫描和分解
    • 根据词法规则
    • 识别出一个一个具有独立意义的单词符号
    • 以供语法分析之用
    • 发现词法错误,则返回出错信息

    在源程序中,自动识别单词,把单词分为五种,并输出对应的单词种别码。

    1. 识别关键字:main if int for while do return break continue,该类的单词码为1.
    2. 识别标识符:表示各种名字,如变量名、数组名、函数名等,如char ch, int syn, token,sum,该类的单词码为2.
    3. 运算符:+、-、*、/、=、>、<、>=、<=、!=
    4.  分隔符:,、;、{、}、(、)
    5. 常数,如123,4587

    各种单词符号对应的种别码。

     

     

    输出形式:

    • 二元式

    –     (单词种别,单词自身的值)

    • 单词种别,表明单词的种类,语法分析需要的重要信息

    –     整数码

    • 关键字、运算符、界符:一符一码
    • 标识符:10, 常数:11
    • 单词自身的值

    –     标识符token、常数sum

    –     关键字、运算符、界符token

     

     

     

    三、        实验方法、步骤及结果测试

    1. 1.      源程序名:编译原理实验报告中源程序名算法分析.c

    可执行程序名:编译原理实验报告.exe

    1. 2.      原理分析及流程图

          

     

    1. 3.      主要程序段及其解释:

    import java.awt.*;

    import java.util.Scanner;

     

    /**

     * Created by s2002 on 2016/9/30.

     */

    public class com {

        public static void main(String[] args) {

     

            //限制字符串最大值

            final int MAX_LEN = 100;

     

            //关键字

            String[] key_word = new String[]{"begin","end","if","then","while","do"};

     

            //录入用户输入

            Scanner input = new Scanner(System.in);

            System.out.print("Please input a string <end with '#'>:");

            String uString = input.nextLine();

     

            char[] analyseData = new char[MAX_LEN];

     

            int index = 0, key = 0;

            List list = new List();

     

            do {

                String compareStr = null;

                char temp = uString.charAt(index);

                list = extactCharacters(temp, analyseData, key_word, uString, index, compareStr);

                if (list.getItemCount() == 0) {

                    index++;

                    continue;

                }

                // 规定List的第一个元素为index,第二个元素为key

                index = Integer.parseInt(list.getItem(0));

                key = Integer.parseInt(list.getItem(1));

                String words = list.getItem(2);

                System.out.println("< " + key + " ," + words + " >");

            } while (key != 0);

     

        }

     

     

        public static List extactCharacters(char temp, char[] analyseDate, String[] keywords, String uString, int index,

                                            String compareStr) {

     

            int keyID = -1, m = 0;

     

            List list = new List();

            //判断下一个读入的字符是否为空格,若读取到空格则跳过,提取下一个字符进行判断

            while (temp != ' ') {

                //判断当前字符是字母或者数字和字母的组合

                if (temp >= 'a' && temp <= 'z') {

                    m = 0;

     

                    // 当读取到不是大小写字母或者数字时候判断为一个单词读取完成

                    while (temp >= 'a' && temp <= 'z' || temp >= 'A' && temp <= 'Z' || temp >= '0' && temp <= '9') {

                        analyseDate[m++] = temp;

                        compareStr += temp + "";

                        temp = uString.charAt(++index);

                    }

     

                    // 与读取出来的字符判断是否为关键字

                    compareStr = compareStr.substring(4);

                    for (int i = 0; i < 6; i++) {

                        if (compareStr.equals(keywords[i])) {

                            keyID = i + 1;

                            list.add(index + "");

                            list.add(keyID + "");

                            list.add(compareStr);

                            return list;

                        }

                    }

     

                    //若为非关键字就当作为标识符

                    keyID = 10;

                    list.add(index + "");

                    list.add(keyID + "");

                    list.add(compareStr);

                    return list;

                }

     

                //判断当前字符是否为数字

                else if (temp >= '0' && temp <= '9') {

                    m = 0;

                    String tempTokens = null;

                    // 对后面的字符进行判断是否为数字

                    while (temp >= '0' && temp <= '9') {

                        analyseDate[m++] = temp;

                        tempTokens += temp;

                        temp = uString.charAt(++index);

                    }

                    // 不是数字则返回种别码,结束当前方法

                    keyID = 11;

                    tempTokens = tempTokens.substring(4);

                    list.add(index + "");

                    list.add(keyID + "");

                    list.add(tempTokens + "");

                    return list;

                }

                m = 0;

                //判断当前字符是否为其他关系运算符

                String token = null;

                switch (temp) {

                    case '<':

                        // String token = null;

                        analyseDate[m++] = temp;

                        token += temp;

                        if (uString.charAt(++index) == '=') {

                            analyseDate[m++] = temp;

                            keyID = 22;

                            token += uString.charAt(index++);

                        } else if (uString.charAt(++index) == '>') {

                            analyseDate[m++] = temp;

                            keyID = 21;

                            token += uString.charAt(index++);

                        } else {

                            keyID = 23;

                        }

                        list.add(index + "");

                        list.add(keyID + "");

                        token = token.substring(4);

                        list.add(token);

                        return list;

                    case '>':

                        analyseDate[m++] = temp;

                        token += temp;

                        if (uString.charAt(++index) == '=') {

                            keyID = 24;

                            analyseDate[m++] = temp;

                            token += uString.charAt(index++);

                        } else {

                            keyID = 20;

                        }

                        list.add(index + "");

                        list.add(keyID + "");

                        token = token.substring(4);

                        list.add(token);

                        return list;

                    case ':':

     

                        analyseDate[m++] = temp;

                        token += temp;

                        if (uString.charAt(++index) == '=') {

                            keyID = 18;

                            // analyseDate[m++] = temp;

                            analyseDate[m++] = uString.charAt(index);

                            token += uString.charAt(index++);

                        } else {

                            keyID = 17;

                        }

                        list.add(index + "");

                        list.add(keyID + "");

                        token = token.substring(4);

                        list.add(token);

                        return list;

                    case '*':

                        keyID = 13;

                        break;

                    case '/':

                        keyID = 14;

                        break;

                    case '+':

                        keyID = 15;

                        break;

                    case '-':

                        keyID = 16;

                        break;

                    case '=':

                        keyID = 25;

                        break;

                    case ';':

                        keyID = 26;

                        break;

                    case '(':

                        keyID = 27;

                        break;

                    case ')':

                        keyID = 28;

                        break;

                    case '#':

                        keyID = 0;

                        break;

                    default:

                        keyID = -1;

                        break;

                }

                analyseDate[m++] = temp;

                list.add(++index + "");

                list.add(keyID + "");

                list.add(temp + "");

                return list;

            }

            return list;

        }

    }

     

    1. 4.      运行结果及分析

    输入源代码:begin x:=0; end#

    符合个字符的单词码

     

     

    四、        实验总结

     

    学会编写一个简单的词法分析程序,学会了利用词法分析程序分析源代码,逐个单词进行分析拆分,把标识符,保留字区分,并且能识别出空格,并把数据能从文件中读出来,对代码的理解更加的深刻。

    转载于:https://www.cnblogs.com/Zhang-Shuheng/p/5961175.html

    展开全文
  • 可以包括任何你想用来分析的代码;我们这里包括了忽略所有注释中字符的功能,传送ID名称和字符串常量内容到主调函数和main函数的功能. (3)实现原理 程序中先判断这个句语句中每个单元为关键字、常数、运算符、界符,...
  • README 本篇文章仅供参考,严禁直接抄袭! 实验目的

    README

    本篇文章仅供参考,严禁直接抄袭!

    一、 实验目的

    1. 巩固有限自动机理论与正规文法、正规式三者之间的关系和相关的知识点;
    2. 了解词法分析器具体的实现方法及所用算法的原理;
    3. 编写相关的词法分析程序实现对C++语言程序文件的部分词法分析;

    二、 实验环境

    1. 开发环境:

    • OS:macOS Sierra 10.12.5
    • 语言:C++
    • 编译器:Xcode 8.3.3
    • 作图:ProccessOn

    2. 运行环境

    • Windows、macOS或者Linux;

    三、 实验内容

    1. 主要内容

    编写代码实现一个词法分析程序,可以对C++语言中的 .cpp 或者 .h 文件中的部分单词,如关键字、操作运算符、界符、标识符、字符串、整数、浮点数、注释等进行识别并提取出相关的单词,形成token序列,并对一些可能出现的错误进行相应的处理。

    2. 主要功能

    • 读写文件:该词法分析器可以读取指定的文件,进行词法分析过程,并将得到的词法分析的token流在控制台中打印出来并写到词法分析程序根目录下的输出文件中;
    • 程序预处理:删除无用的空白字符、回车字符以及其他非实质性字符,删除两种形式的注释;
    • 词法分析:该词法分析器逐个扫描读进的文件字符流,然后进行相应的词法分析。通过扫描,找出相应的单词以及其相应的种别码,形成token序列,为输出到语法分析器中做准备;
    • 错误报告:报告词法检查中遇到的错误以及错误出现的行数,错误包括浮点数小数点错误、数字中混杂字母、字符位数过多、字符丢失单引号、字符串丢失双引号、注释格式不正确、标识符命名错误等等;

    3. 种别码

    单词符号 种别码
    main 1
    if 2
    else 3
    while 4
    do 5
    for 6
    int 7
    double 8
    float 9
    char 10
    long 11
    short 12
    enum 13
    static 14
    bool 15
    void 16
    switch 17
    case 18
    break 19
    continue 20
    signed 21
    unsigned 22
    return 23
    default 24
    const 25
    union 26
    struct 27
    auto 28
    include 29
    define 30
    class 31
    virtual 32
    friend 33
    public 34
    private 35
    protected 36
    this 37
    false 38
    true 39
    try 40
    catch 41
    throw 42
    goto 43
    using 44
    template 45
    new 46
    namespace 47
    operator 48
    register 49
    inline 50
    + 51
    - 52
    ++ 53
    54
    * 55
    / 56
    % 57
    < 58
    <= 59
    > 60
    >= 61
    = 62
    == 63
    != 64
    << 65
    >> 66
    && 67
    || 68
    ! 69
    ^ 70
    , 71
    ; 72
    . 73
    { 74
    } 75
    [ 76
    ] 77
    ( 78
    ) 79
    # 80
    \ 81
    ? 82
    标识符表 83
    字符常量表 84
    字符串常量表 85
    整数常量表 86
    浮点数常量表 87

    其中,1~50为基本关键字、51~70为操作运算符、71~82为界符。

    4. DFA

    DFA1DFA2

    5. 设计思路

    1. 打开源文件,读取文件内容,直至遇上‘$’文件结束符,然后读取结束。
    2. 对读取的文件进行预处理,从头到尾进行扫描,去除 // 和 /* */ 的内容,以及一些无用的、影响程序执行的符号如换行符、回车符、制表符等。
    3. 接下来对源文件从头到尾进行扫描。从头开始扫描,这个时候分析程序首先去除开头的所有空格,直到扫描出的字符不是空格。然后判断当前字符是不是字母,若是则进行标识符和保留字的识别;若这个字符是数字,则进行数字的判断;若是界符则直接收集;若是操作运算符则进行操作运算符的判断;若是单引号则进行字符判断;若是双引号则进行字符串判断。若是将所有可能都走了一遍还是没有知道它是谁,则认定为错误符号,输出该错误符号,然后结束。每次成功识别了一个单词后,单词都会存在token[ ]中。然后确定这个单词的种别码,最后进行下一个单词的识别。
    4. 主控程序主要负责对每次识别的种别码syn进行判断,对于不同的种别做出不同的反应。如对于识别符则将其插入标识符表中;对于保留字则输出该保留字的种别码等等。直至遇到 syn = 0 ,程序结束。

    6. 主要数据结构

    名称 类型 描述
    reserveWords const static string* 存放C++部分关键字
    operators const static string* 存放C++部分操作运算符
    delimiters const static string* 存放C++部分界符
    identitierTable vector<string> 存放标识符
    charTable vector<string> 存放字符常量
    stringTable vector<int> 存放字符串常量
    intTable vector<int> 存放整数常量
    floatTable vector<float> 存放浮点数常量

    7. 主要算法

    RE to NFA to DFA to DFA’

    四、 实验结果

    程序1:

    include <iostream>
    
    /*
     让n+1并返回
     */
    int inc(int n)
    {
        return ++n;
    }
    
    int main()
    {
        //声明三个变量
        int x = inc(0);
        string y = "test!";
        float z = 6.66;
        
        return 0;
    }
    

    输出1:
    <include , 29> ----- 关键字
    << , 58> ----- 操作运算符
    <iostream , 83> ----- 标识符
    <> , 60> ----- 操作运算符
    <int , 7> ----- 关键字
    <inc , 83> ----- 标识符
    <( , 78> ----- 界符
    <int , 7> ----- 关键字
    <n , 83> ----- 标识符
    <) , 79> ----- 界符
    <{ , 74> ----- 界符
    <return , 23> ----- 关键字
    <++ , 53> ----- 操作运算符
    <n , 83> ----- 标识符
    <; , 72> ----- 界符
    <} , 75> ----- 界符
    <int , 7> ----- 关键字

    五、 遇到的问题及解决方法

    问题:程序预处理之后进行词法分析的时候,一直提示“错误的数字”等错误。
    解决方法:经过排查之后发现是程序在预处理的时候将所有空格都删除了,导致所有词素都连在了一起,所以一直报错。修改预处理部分使得空格不会被删除之后发现程序即可正常运行了。

    六、 实验感想

    在本次实验中,我使用C++实现了C++语言的子集的词法分析器。通过本次实验,我对词法分析的流程有了更为清晰的认识,也对课本上所学的知识有了更为深刻的理解,同时也懂得了许多在课堂上没有学到的关于编译的新知识。但总体来看本次完成的词法分析器还是比较低级的,本想可以做到提示错误并作出相应的错误处理,可是写到一半的时候才发现预处理的时候已经吧所有换行符删除了,所以这部分功能无法实现,以后若有机会的话我会将本次实验结果加以改善!

    展开全文
  • 设计模式之访问者模式 前面介绍的词法分析器、语法分析器、语义分析器和代码生成器中有多次遍历语法树的过程,然而每次遍历这棵语法树都会进行不同的处理动作,对这棵语法树也要进行进一步的处理。这是如何实现的呢...
  • 如果真正想了解后面链接和执行参看<> 1.3 编译程序的结构 1.3.1 编译程序总框 编译程序的设计: 词法分析器-语法分析器-语义分析器与中间代码生成-优化器-目标代码生成器 其中贯穿整个过程的还有表格管理和出错处理...
  • 编译器前端部分 前端包括词法分析器(Scanner)、词法解析器(Parser)、语义规则(Semantic Elaboration),其中程序代码是一串字符流的形式进入词法分析器的,拆分出来的有意义的单元进入词法解析器中,但词法...
  • 编译原理实验词法分析器实现,里面有整个项目文件,还有实验报告。cg平台测试满分,vs编译器也是可以通过编译的,其他编译器可能需要改一下,不会改的私信我。
  • 实用标准文档 编译原理实验报告 题目 C_minus 语言词法分析器 装 订 线 学 院 计算机科学与技术 专 业 xxxxxxxxxxxxxxxx 学 号 xxxxxxxxxxxx 姓 名 xxxx 指导教师 xxxx 20xx 年 xx 月 xx 日 文案大全 实用标准文档 C...
  • 精品文档 装订线 装 订 线 编译原理实验报告 题目 C_minus语言词法分析器 学 院 计算机科学与技术 专 业 xxxxxxxxxxxxxxxx 学 号 xxxxxxxxxxxx 姓 名 xxxx 指导教师 xxxx 20xx年xx月xx日 C_minus语言词法分析器 一...
  • 实验词法分析器的设计 一、实验目的 理解并掌握词法分析的原理与方法,能够使用某种语言实现词法分析程序。 二、实验要求 选用某种语言(如 C/C++)实现词法分析程序。词法分析程序的主要任务如下: 1. 识别...
  • 实验报告词法分析器 一些基本概念: lex:词法分析器的自动产生系统 lex.exe将lex源程序转换成lex.yy.c文件(由命令flex xxx.lex执行) 编译lex.yy.c生成可执行文件,该可执行文件即可将源语言程序切割为单词符号...
  • 词法分析实验报告

    2020-11-08 09:35:02
    或者调研词法分析程序的自动生成工具LEX或FLEX,设计并实现一个能够输出单词序列的词法分析器。 (2) 通过设计调试词法分析程序,实现从源程序中分出各种单方法;加深对课堂教学的理解;提高词法分析方法的实践能力...

空空如也

空空如也

1 2 3 4 5 6
收藏数 119
精华内容 47
关键字:

词法分析器实验报告