编译原理 实验一:简单词法分析

一、实验目的

了解词法分析程序的基本构造原理,掌握词法分析程序的手工构造方法。

二、实验内容

1、了解编译程序的词法分析过程。

2、根据PASCAL语言的说明语句形式,用手工方法构造一个对说明语句进行词法分析的程序。该程序能对从键盘输入或从文件读入形如:

“const count=10,sum=81.5, char1=’f’, string1=”hj”,max=169;”

的常量说明串进行处理,分析常量说明串中各常量名、常量类型及常量值,并统计各种类型常量个数。

三、实验要求

1、输入的常量说明串,要求最后以分号作结束标志;

2、根据输入串或读入的文本文件中第一个单词是否为“const”判断输入串或文本文件是否为常量说明内容;

3、识别输入串或打开的文本文件中的常量名。常量名必须是标识符,定义为字母开头,后跟若干个字母,数字或下划线;

4、根据各常量名紧跟等号“=”后面的内容判断常量的类型。其中:字符型常量定义为放在单引号内的一个字符;字符串常量定义为放在双引号内所有内容;整型常量定义为带或不带+、- 号,不以0开头的若干数字的组合;实型常量定义为带或不带+、- 号,不以0开头的若干数字加上小数点再后跟若干数字的组合;

5、统计并输出串或文件中包含的各种类型的常量个数;

6、以二元组(类型,值)的形式输出各常量的类型和值;

7、根据常量说明串置于高级语言源程序中时可能出现的错误情况,模仿高级语言编译器对不同错误情况做出相应处理;

import sys
import re

keywords = ['const']


def to_split(str):
    str = str.strip()
    f = 0
    while True:
        if str[-1] == ';':
            str = str[:-1]
            f = 1
        else:
            if f == 1:
                break
            else:
                print("末尾缺少;\n")
            sys.exit()


    # str_list = str.split(',')
    all = re.finditer(',[^\"\'=]{1,100}=', str)
    list_dou = []
    for i in all:
        list_dou.append(i.span()[0])
    str2 = list(str)
    a = ""
    for i in range(len(str)):
        if i in list_dou:
            a = a + '!@#123$%^&*'
        else:
            a = a + str[i]
    str = a.split('!@#123$%^&*')
    return str

def get_type(str):
    str = str.strip()
    global int_num
    global char_num
    global string_num
    global float_num

    name_word = ""
    type_word = ""
    value_word = ""

    # p判断是否有 = 号,如果有的话输出下标
    index_dengyu = str.find("=")
    if index_dengyu == -1:
        print("缺少 = \n")
        sys.exit()
    #  = 号左右分割
    str_left = str[:index_dengyu].strip()
    str_right = str[index_dengyu + 1:].strip()
    #  = 号左分割成单词

    # =左边按空格分隔,去掉列表里面的'',然后判断
    str_left_list = str_left.split(' ')
    temp = []
    for i in str_left_list:
        if i != '':
            temp.append(i)
    str_left_list = temp

    if len(str_left_list) == 1:
        name_word = str_left_list[0]
        # 判断第一个是否为字母
        if name_word[0].isalpha() is False:
            print("%s(错误!变量名首字母不为字母!)\n" % str_left_list[0])
            return 0
    elif len(str_left_list) == 2:
        if str_left_list[0] in keywords:
            name_word = str_left_list[1]
            if name_word[0].isalpha() is False:
                print("%s(错误!变量名首字母不为字母!)\n" % str_left_list[1])
                return 0
        else:
            print("%s 不是关键字!\n" % str_left_list[0])
            sys.exit();

    # 格式
    if str_right[0] == '.':
        type_word = "float"
        float_num = float_num + 1
        value_word = str_right
    elif str_right[0] == '\'' and str_right[-1] == '\'':
        if len(str_right) != 3:
            print("%s(错误!字符串格式错误!)\n" % name_word)
            return 0
        type_word = "char"
        char_num = char_num + 1
        value_word = str_right
    else:
        try:
            try:
                type_word = "integer"
                value_word = int(str_right)
                int_num = int_num + 1
            except:
                type_word = "float"
                value_word = float(str_right)
                float_num = float_num + 1
        except:
            if str_right[0] != '\"' and str_right[-1] != '\"':
                print("%s(错误!字符串格式错误!)\n" % name_word)
                return 0
            type_word = "string"
            string_num = string_num + 1
            value_word = str_right
    print("%s(%s,%s)\n" % (name_word, type_word, value_word))


str = """
const count1 = 2180,sum1 = 6881.655,char1='f',
count2=65,max1=169,char2='@',sum2=.0815,str1="\"cds f 89h\"",
max2=1.6229,str2="good jbhn";

"""

str_list = to_split(str)

int_num = 0
char_num = 0
string_num = 0
float_num = 0

# str_list = ["const count1 = 2180"]
for i in str_list:
    get_type(i)
print(("int_num = %s,char_num = %s,string_num = %s,float_num = %s\n" \
       % (int_num, char_num, string_num, float_num)))

 

你可能感兴趣的:(python,课程设计)