【编译原理】基于词法分析器的LL1语法分析器

【避雷】实验课打分离谱,同学一次性LL1语法分析器及参考我博客的同学分数还比我高,狠狠避雷

【编译原理】基于词法分析器的LL1语法分析器

实验要求

设计一个满足以下要求的⽂法:
(1)识别只包含变量声明语句和执行语句程序段的语法结构合法性;
(2)变量声明中只使用int,char,float 3类基本类型;
(3)变量声明中允许初始化,每一个数据类型可以声明多个变量;
(4)执行语句只包括:表达式语句、if语句、while语句;
(5)可以有多条变量声明语句和执行语句;
(6)没有函数声明,所有语句都在同一 个函数体内。
(7)表达式是以=、+、-、*、/、>、<为运算符,常数、变量标识符为操作数,并带圆括号的式子。

对满足以上要求的文法构造其相应分析表(LL或LR);对于给定输⼊符号串,能检查其是否语法正确;若有错,显示出错语句所在行及简单错误信息。
注意:要求以词法分析的结果,即单词表中的编码为输入内容。

评分标准

①分析表是否是自动生成;
②是否能识别多条语句;
③是否能识别声明语句;
④是否能识别执行语句,包括if、while、表达式语句;
⑤每个错误是否有错误提示,包括错误所在行、错误信息;
⑥错误提示信息是否区分不同类别;

源码

grammarAnalysis.py

import re

# 词法分析
class MyToken:
    def __init__(self, MyType, seman, MyStr):
        self.MyType = MyType
        self.seman = seman
        self.MyStr = MyStr

    def __str__(self):
        s = self.MyStr.replace('\n','')
        return "token.class:  {:5}\t\tstr:  {:10}\tseman:\t{} \t".format(self.MyType, s, self.seman)


# 单词集状态列表
states = ['if', 'else', 'for', 'while', 'break', 'return', 'continue', 'float', 'int', 'char', '标识符',
          '正整数、正实数、零', '+', '-',
          '*', '/', '%', '>', '>=', '<', '<=', '!=', '==', '!', '&', '|', ',', '=', '[', ']', '(', ')', '{', '}', ';',
          '.', '\\', '#']
choiceStatec = [13, 14, 15, 16, 17, 18, 20, 24, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36]  # 用于防止while循环中出现多次elif
inputs = []  # 输入的字符



tokens = []  # 单词表
NameL = []  # 名字表
ConstL = []  # 常数表



i = 0
line = 1



# 将文件内容提取到inputs
def codeToInputs(sourceCodes):
    for line in sourceCodes:
        for char in line:
            inputs.append(char)
            if char == '#':
                return


# 判断是否为字母
def isLetter(char):
    pattern = r"[a-zA-Z]"
    return bool(re.match(pattern, char))


# 判断是否为数字
def isDigit(char):
    pattern = r"[0-9]"
    return bool(re.match(pattern, char))


# 普通的字符识别
def isC(char, state):
    tokens.append(MyToken(state, "^", char))


def choiceState(char):  # 选择单字符对应状态
    state = 0
    if char in states:
        for k in range(len(states)):
            if states[k] == char:  # 判断单个字符
                if char in ['>', '<', '!', '=', '&', '|', '\\'] and inputs[i] in ['=', '&', '|', 'n']:  # 如果是双字符
                    state = 19
                else:
                    state = k + 1
    else:
        state = 0
    return state


def error():
    print(f"第{
     line}行---未知字符错误")
    exit(0)


# 词法分析
def nextToken():
    global i
    global line
    name = ""
    char = inputs[i]
    i += 1
    while char == ' ' or char == '\n' or char == '\t':  # 如果是空就跳过
        if char == '\n':
            line += 1
        char = inputs[i]
        i += 1
        if char == '#':
            i -= 1
    global state
    state = 0
    while True:

        if state == 0:  # 选择
            if char == '#':
                i -= 1
                state = 38
                continue
            if char == '/' and (inputs[i] == '/' or inputs[i] == '*'):  # 注释
                state = 42
                continue
            if choiceState(char) != 0:  # 判断后面的单字符,获取状态
                state = choiceState(char)
                i -= 1
                continue
            if char == "i":
                state = 1
            elif char == "e":
                state = 2
            elif char == 'f':
                state = 3
            elif char == 'w':
                state = 4
            elif char == 'b':
                state = 5
            elif char == 'r':
                state = 6
            elif char == 'c':
                state = 7
            elif isDigit(char):  # 数字
                state = 12
            elif isLetter(char):  # 字符串
                i -= 1
                state = 11

            else:
                error()  # 非法字符报错
                i -= 1
                state = 38
        elif state == 1:  # if

            if inputs[i] == 'f':  # 判断第二个是否为f
                if isDigit(inputs[i + 1]) or isLetter(inputs[i + 1]):  # 标识符
                    i -= 1
                    state = 11
                else:
                    m = MyToken(1, "^", "if")  # 在单词表和名字表加入
                    tokens.append(m)
                    state = 38

            elif inputs[i] == 'n':  # 判断第二个是否为n
                i += 1
                if inputs[i] == 't':
                    if isDigit(inputs[i + 1]) or isLetter(inputs[i + 1]):  # 标识符
                        i -= 2
                        state = 11
                    else:
                        m = MyToken(9, "^", "int")  # 在单词表和名字表加入
                        tokens.append(m)
                        state = 38
                else:
                    if isDigit(inputs[i]) or isLetter(inputs[i]):  # 标识符
                        i -= 2
                        state = 11
                    else:
                        m = MyToken(11, "^", "in")  # 在单词表和名字表加入
                        tokens.append(m)
                        state = 38
                        i -= 1
            else:  # 以i开头的标识符
                i -= 1
                state = 11

        elif state == 2:  # else
            if ''.join(inputs[i:i + 3]) == 'lse':
                if isDigit(inputs[i + 3]) or isLetter(inputs[i + 3]):
                    i -= 1
                    state = 11
                else:
                    m = MyToken(2, "^", "else")  # 在单词表和名字表加入
                    tokens.append(m)
                    state = 38
                    i += 2
            
  • 8
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值