实验 1 词法分析程序设计-编译原理(湖工大)

【实验目的】

(1)理解词法分析在编译程序中的作用 (2)加深对有穷自动机模型的理解 (3)掌握词法分析程序的实现方法和技术

【实验内容】

对一个简单语言的子集编制一个一遍扫描的词法分析程序。

【实验要求】

(1)待分析的简单语言的词法 

                1) 关键字 begin if then while do end 

                2) 运算符和界符 := + - * / < >= <> = ; ( ) #

                3) 其他单词是标识符(ID)和整形常数(NUM),通过以下正规式定义:                                         ID=letter(letter|digit)* NUM=digitdigit*

                4) 空格由空白、制表符和换行符组成。空格一般用来分隔 ID、NUM、运算符、界符和 关键字,词法分析阶段通常被忽略。

(2)各种单词符号对应的种别编码

(3)词法分析程序的功能

                输入:所给文法的源程序字符串

                输出:二元组(syn,token 或 sum)构成的序列。

                 syn 为单词种别码; token 为存放的单词自身字符串; sum 为整形常数。

【实验代码】

头文件.hpp

#ifndef TEST_HPP
#define TEST_HPP

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <cctype>

std::unordered_map<std::string, int> TOKEN_MAPPING = {
    {"begin", 1},
    {"if", 2},
    {"then", 3},
    {"while", 4},
    {"do", 5},
    {"end", 6},
    {"letter(letter|digit)*", 10},
    {"digitdigit*", 11},
    {"+", 13},
    {"-", 14},
    {"*", 15},
    {"/", 16},
    {":", 17},
    {":=", 18},
    {"<", 20},
    {"<>", 21},
    {"<=", 22},
    {">", 23},
    {">=", 24},
    {"=", 25},
    {";", 26},
    {"(", 27},
    {")", 28},
    {"#", 0}};

// 函数声明
bool isLetter(char c);
bool isDigit(char c);
bool isOperator(char c);
bool isDelimiter(char c);
bool isValidIdentifierChar(char c);
bool isAssignmentOperator(const std::string &token);

// 逻辑函数实现
void Scanner(std::string input)
{
    for (size_t i = 0; i < input.size(); ++i)
    {
        char c = input[i];
        if (isspace(c)) // Skip whitespace
            continue;
        else if (isLetter(c)) // Variable or keyword
        {
            std::string token = "";
            while (i < input.size() && isValidIdentifierChar(input[i]))
                token += input[i++];
            --i; // 循环中增加了i,这里需要减回来
            auto it = TOKEN_MAPPING.find(token);
            if (it != TOKEN_MAPPING.end())
                std::cout << "(" << it->second << ", " << token << ") ";
            else
                std::cout << "(" << TOKEN_MAPPING["letter(letter|digit)*"] << ", " << token << ") ";
        }
        else if (isDigit(c)) // Number
        {
            std::string token = "";
            while (i < input.size() && isDigit(input[i]))
                token += input[i++];
            --i; // 循环中增加了i,这里需要减回来
            std::cout << "(" << TOKEN_MAPPING["digitdigit*"] << ", " << token << ") ";
        }
        else if (isOperator(c) || c == ':') // Operator or start of assignment operator
        {
            std::string token = "";
            token += c;
            if (c == ':' && i + 1 < input.size() && input[i + 1] == '=')
                token += input[++i]; // 捕获 :=
            if (c == '<' || c == '>')
                if (i + 1 < input.size() && input[i + 1] == '=')
                    token += input[++i]; // Capture <= or >=
            auto it = TOKEN_MAPPING.find(token);
            if (it != TOKEN_MAPPING.end())
                std::cout << "(" << it->second << ", " << token << ") ";
        }
        else if (isDelimiter(c)) // Delimiter
        {
            std::string token = "";
            token += c;
            std::cout << "(" << TOKEN_MAPPING[token] << ", " << token << ") ";
        }
    }
    std::cout << "\nProgram ended." << std::endl;
}

// 函数定义
bool isLetter(char c)
{
    return std::isalpha(c);
}

bool isDigit(char c)
{
    return std::isdigit(c);
}

bool isOperator(char c)
{
    return c == '+' || c == '-' || c == '*' || c == '/' || c == '>' || c == '<';
}

bool isDelimiter(char c)
{
    return c == '(' || c == ')' || c == ';' || c == '#';
}

bool isValidIdentifierChar(char c)
{
    return isLetter(c) || isDigit(c);
}

bool isAssignmentOperator(const std::string &token)
{
    return token == ":=";
}

#endif // TEST_HPP

源文件.cpp

  • #include "test.hpp"
    #include <iostream>
    using namespace std;
    
    int main()
    {
        string prog;
        do
        {
            cout << "Please input string: ";
            getline(cin, prog);
            if (prog.length() >= 2 && prog[prog.length() - 1] != '#')
                cout << "\nInput string should end with '#'." << endl;
            else
                Scanner(prog);
        } while (prog.length() < 2 || prog[prog.length() - 1] != '#');
    
        return 0;
    }
    
    // begin x:=9;if x>0 then x:=2*x+1/3;end#

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 合肥工业大学编译原理实验1是一个词法分析程序实验,使用Python语言进行编写。 词法分析编译原理中的一个重要内容,主要负责将源代码文件中的字符序列分割成有意义的词法单元,如标识符、关键字、运算符、分隔符等,为后续的语法分析和语义分析做好准备。 Python语言由于其简洁易学和强大的功能,成为许多编译原理实验的首选语言之一。在这个实验中,我们将使用Python编写一个词法分析程序,实现对源代码的分析。 首先,我们需要读取源代码文件,将其转换为字符流,传递给词法分析程序程序会逐个读取字符,并根据事先定义好的正则表达式进行匹配,识别出相应的词法单元。 实验中可能会用到的一些正则表达式包括:匹配标识符的正则表达式、匹配关键字的正则表达式、匹配运算符的正则表达式、匹配数值常量的正则表达式等。 在识别出词法单元后,程序会生成一个词法单元表,记录下每个词法单元的类型和对应的值。该词法单元表将作为语法分析的输入。 在编写这个词法分析程序时,需要注意处理多种可能的错误情况,如不合法的字符、不符合规范的标识符等。可以通过添加捕获异常的机制来处理这些错误情况,并及时进行提示。 综上所述,通过本次实验,我们可以学习到编译原理词法分析的基本概念和原理,并通过实践来深入理解。通过使用Python语言编写词法分析程序,我们能够更好地掌握Python语言的特性和应用。 ### 回答2: 编译原理实验一是词法分析程序实验要求使用Python语言编写程序。本实验的主要目的是通过实现词法分析器,能够将输入的源代码分解成一个个的词法单元。在合肥工业大学编译原理实验一的词法分析程序实验中,我们需要实现以下功能: 1. 识别并分类各种类型的词法单元,比如标识符、数字、关键字、运算符、界符等。 2. 跳过空格、换行符和注释等不影响程序执行的字符。 3. 输出每个词法单元的类型和值,方便后续程序分析和处理。 为了完成这个实验,我们可以使用Python语言提供的字符串处理函数和正则表达式库来帮助我们实现上述功能。下面是一个简单的实现示例: ```python import re def lexer(code): # 定义正则表达式,用于识别各种类型的词法单元 keywords = ['if', 'else', 'while', 'for', 'int', 'float', 'char'] # 关键字 operators = ['+', '-', '*', '/', '=', '==', '!=', '<', '>', '<=', '>='] # 运算符 delimiters = [';', '(', ')', '{', '}'] # 界符 pattern_keywords = '|'.join(keywords) pattern_operators = '|'.join(re.escape(op) for op in operators) pattern_delimiters = '|'.join(re.escape(dl) for dl in delimiters) pattern = f'({pattern_keywords})|({pattern_operators})|({pattern_delimiters})|\w+|\d+' # 开始词法分析 tokens = re.findall(pattern, code) for token in tokens: if token[0]: print(f'关键字:{token[0]}') elif token[1]: print(f'运算符:{token[1]}') elif token[2]: print(f'界符:{token[2]}') elif token[3]: print(f'标识符:{token[3]}') elif token[4]: print(f'数字:{token[4]}') # 测试代码 code = ''' int main() { int a = 10; if (a > 0) { a = a - 1; } return 0; } ''' lexer(code) ``` 以上是一个简单词法分析程序实验的实现示例,通过使用正则表达式来识别各种词法单元,并打印出每个词法单元的类型和值。实验中可以根据具体需求扩代码,添加更多的词法单元类型和识别规则。 ### 回答3: 合肥工业大学编译原理实验1是关于词法分析程序实验词法分析是编译过程中的第一个步骤,主要任务是将源代码分解为一个个的词法单元。在这个实验中,使用Python编写词法分析程序。 在开始编写程序之前,首先需要明确程序的功能和输入输出要求。根据实验要求,我们需要编写一个可以识别并输出源代码中的各个词法单元的程序。 编写词法分析程序的基本思路如下: 1. 读取源代码文件,将其按照字符进行分解; 2. 针对每一个字符,判断其所属的词法单元类型; 3. 将每个词法单元及其类型输出。 在Python中,可以利用正则表达式来匹配词法单元的模式。通过定义适当的正则表达式,可以方便地判断当前字符所属的词法单元类型。可以考虑使用re模块来处理正则表达式。 实验的输入是一个源代码文件,首先需要使用Python的文件操作来读取源文件的内容。之后,可以利用re模块的正则表达式相关函数,对每个字符进行匹配和识别。最后,将每个词法单元及其类型输出到一个文件中。 编写完程序后,可以使用一些示例的源代码文件进行测试,验证程序的正确性。如果发现有问题,可以通过调试和修改代码来改进程序的逻辑和功能。 总之,合肥工业大学编译原理实验1词法分析程序实验使用Python编写,通过正则表达式对源代码进行分析和识别,并将每个词法单元及其类型输出到一个文件中。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值