编译原理——词法分析

编译原理实验——词法分析

  • 写出某个语言的词法分析程序,要求能识别出关键字,标识符,常数,运算符和分界符等常用语言单词符号

简单来说:词法分析就是能将一个程序每个单词符号识别出来,然后标记上特定的标识码。

  • 输入:程序文本
  • 输出:二元序列(单词,种别码)

本次识别语言种别码如下

单词符号种别码单词符号种别码
int1=11
long2if12
start3then13
end4endif13
ID5,15
NUM6;16
+7==17
-8<18
*9>19
/10error0

词法分析流程图和状态转换图略,词法分析实际上只要能识别出单词符号然后标记上对应的种别码就行。
首先是待分析程序 test.txt文件

start 
	int a,b,c,d,e;
	a = 3; b = 6;
	if b<c then c=c-3;endif;
end

词法分析程序如下:
C++版

#include <iostream>
#include <fstream>
#include <string>
#include<algorithm>
#include <map>


using namespace std;
map<string,int> key_Iden;

void init()
{
    /*初始化*/
    key_Iden["int"]=1;
    key_Iden["long"]=2;
    key_Iden["start"]=3;
    key_Iden["end"]=4;
    key_Iden["ID"]=5;
    key_Iden["NUM"]=6;
    key_Iden["+"]=7;
    key_Iden["-"]=8;
    key_Iden["*"]=9;
    key_Iden["/"]=10;
    key_Iden["="]=11;
    key_Iden["if"]=12;
    key_Iden["then"]=13;
    key_Iden["endif"]=14;
    key_Iden[","]=15;
    key_Iden[";"]=16;
    key_Iden["=="]=17;
    key_Iden["<"]=18;
    key_Iden[">"]=19;

}

void print(string sflag,string st)
{
    cout<<"("<<key_Iden[sflag]<<"  "<<st<<")"<<endl;
}

void scanner(string line)
{
    init();
    cout<<line<<endl;
    int p=0,endp = line.length(),l=0;
    char s[10]="",ch;
    while(p<endp)
    {
        ch=line[p];l=0;
        int iflag = 0;
        while((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9'))
        {
            //合法可用字符,读取完整
            iflag=1;
            s[l++]=ch;
            p++;
            ch=line[p];
        }
        if(iflag) //检查是否为标识符或
        {
            s[l]='\0';
            string st=s;
            if(key_Iden[st]==0)
            {
                //非关键字
                string sflag;
                if(s[0]>='a'&&s[0]<='z')
                {
                    print("ID",st);
                }
                else
                {
                    int flag=1;
                    for(int i=0; i<l&&flag; i++)
                    {
                        if(s[i]<'0'||s[i]>'9')
                            flag=0;
                    }
                    if(flag)
                        print("NUM",st);
                    else
                        print("error",st);
                }

            }
            else
            {
                //关键字
                print(st,st);
            }
        }
        if(ch!=' ')
        {
            string str[2];int i=-1;
            str[0]=line.substr(p,1);
            str[1]=line.substr(p,2);
            if(key_Iden[str[1]]){
                i=1;p+=2;
            }else{
                if(key_Iden[str[0]])
                    i=0;
                p++;
            }
            if(i!=-1)
                print(str[i],str[i]);
            else if(p<endp)
                print("error", str[0]);
        }else{
            p++;
        }
    }
}

string  Replace(string line)//预处理,将无用标识替换为空格
{
    replace(line.begin(),line.end(),'\t',' ');
    return line;
}

int main()
{

    ifstream infile("test.txt");
    string line="";
    string t;
    if(infile.is_open())
    {
        while(getline(infile,t))
        {
            line += t;
        }
        line=Replace(line);
        scanner(line);
    }
    else
    {
        cout<<"文件打开失败"<<endl;
    }
    return 0;
}

c++版的就需要我们自己一个个读取字符,然后凑对识别,代码逻辑主要在scanner函数那里。

python版

import os
import re

key_Iden = {
    'int': 1, 'long': 2, 'start': 3, 'end': 4,
    'ID': 5, 'NUM': 6, 'if': 12, 'then': 13, 'endif': 14, 'error': 0
}

key_sym = {
    '+': 7, '-': 8, '*': 9, '==': 17,
    '/': 10, '=': 11, ',': 15, ';': 16, '<': 18, '>': 19,
}
sym_id = []  # 词法分析结果集

def init(file):
    """
    初始化,符号替换,分割
    """
    # 回车换行tap替换
    s = file.replace('\r', ' ')
    s = s.replace("\t", ' ')
    s = s.replace('\n', ' ')
    # 运算符和边界替换
    for i in [i for i in list(key_sym.keys()) if i != '=']:
        s = s.replace(i, ' '+i+' ')
    st = s.split(' ')
    st = [i for i in st if i != '']
    new_st = []
    for i in st:
        if i != '==' and '=' in i:
            new_st += re.split(r'(=)', i)
        else:
            new_st.append(i)
    return [i for i in new_st if i != '']


def scanner(file):
    st = init(file)
    for i in st:
        if i in key_Iden:
            sym_id.append([i, key_Iden[i]])
        elif i in key_sym:
            sym_id.append([i, key_sym[i]])
        else:
            if i.isdigit():
                sym_id.append([i, key_Iden['NUM']])
            elif i.isalnum() and i[0].isalpha():
                sym_id.append([i, key_Iden['ID']])
            else:
                sym_id.append([i, key_Iden['error']])

if __name__ == '__main__':
	 with open("test.txt", encoding='utf-8') as f:
        print("待分析程序")
        scanner(f.read())
        print("< %5s|%3s >"%("符号","内码值"))
        for i in sym_id:
            print("< %6s | %2s >"%(i[0],i[1]))

结果都是一样的,python更暴力一点,首先直接搜索符号然后替换字符串,最后直接切割,标识。当然C++也可以使用已有的string类函数,效果应该差不多。
在这里插入图片描述

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值