头歌编译原理实验1《 第1关:词法分析程序设计与实现》

AC CODE

c++ 复制代码
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
char prog[1000], token[20];
char ch;
int syn, p, m = 0, n, row = 1, sum = 0;
// 扩充关键字表
const char* rwtab[10] = { "if","int","for","while","do","return","break","continue", "using", "namespace" };
const char* rwtab1[8] = { "main","a","b","c","d","e","f","g" };

void scaner()
{
    // 初始化token数组
    for (n = 0; n < 20; n++) token[n] = '\0';
    // 跳过空白字符
    while (p < strlen(prog) && (prog[p] == ' ' || prog[p] == '\t' || prog[p] == '\n'))
    {
        if (prog[p] == '\n')
            row++;
        p++;
    }
    if (p >= strlen(prog))
    {
        syn = 0;
        return;
    }
    ch = prog[p++];

    // 进行标示符或者关键字的识别
    if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
    {
        m = 0;
        while ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'))
        {
            token[m++] = ch;
            if (p >= strlen(prog))
                break;
            ch = prog[p++];
        }
        token[m] = '\0';
        if (p < strlen(prog))
            p--;
        syn = 2;
        for (n = 0; n < 10; n++) // 更新关键字表长度
        {
            if (strcmp(token, rwtab[n]) == 0)
            {
                syn = 1;
                break;
            }
        }
    }
    // 进行数字的识别
    else if (ch >= '0' && ch <= '9')
    {
        sum = 0;
        while (ch >= '0' && ch <= '9')
        {
            sum = sum * 10 + (ch - '0');
            if (p >= strlen(prog))
                break;
            ch = prog[p++];
        }
        if (p < strlen(prog))
            p--;
        syn = 3;
    }
    // 进行其他字符的识别
    else
    {
        switch (ch)
        {
        case '<':
            m = 0;
            token[m++] = ch;
            if (p < strlen(prog) && prog[p] == '<')
            {
                token[m++] = prog[p++];
                syn = 4;
            }
            else
            {
                syn = 4;
                p--;
            }
            break;
        case '>':
            m = 0;
            token[m++] = ch;
            if (p < strlen(prog) && prog[p] == '=')
            {
                token[m++] = prog[p++];
                syn = 4;
            }
            else
            {
                syn = 4;
                p--;
            }
            break;
        case ':':
            m = 0;
            token[m++] = ch;
            if (p < strlen(prog) && prog[p] == '=')
            {
                token[m++] = prog[p++];
                syn = 4;
            }
            else
            {
                syn = 4;
                p--;
            }
            break;
        case '*':
            syn = 4;
            token[0] = ch;
            break;
        case '/':
            syn = 4;
            token[0] = ch;
            if (p < strlen(prog) && prog[p] == '/') {
                token[1] = '/';
                syn = 5; // 注释符号作为界符处理
                p++;
            }
            break;
        case '+':
            syn = 4;
            token[0] = ch;
            break;
        case '-':
            syn = 4;
            token[0] = ch;
            break;
        case '=':
            syn = 4;
            token[0] = ch;
            break;
        case ';':
            syn = 5;
            token[0] = ch;
            break;
        case ',':
            syn = 5;
            token[0] = ch;
            break;
        case '(':
            syn = 5;
            token[0] = ch;
            break;
        case ')':
            syn = 5;
            token[0] = ch;
            break;
        case '{':
            syn = 5;
            token[0] = ch;
            break;
        case '}':
            syn = 5;
            token[0] = ch;
            break;
        case '#':
            syn = 0;
            token[0] = ch;
            break;
        case '"':
            syn = 5;
            token[0] = ch;
            break;
        default:
            syn = -1;
            break;
        }
    }
}

int main()
{
    // 输入
    p = 0;
    cout << "Please input string:" << endl;
    do
    {
        cin.get(ch);
        prog[p++] = ch;
    } while (ch != '#');
    prog[p] = '\0';
    p = 0;

    // 输出
    do
    {
        scaner();
        switch (syn)
        {
        case 0:
            break;
        case 3:
            cout << "(" << syn << "," << sum << ")" << endl;
            break;
        case -1:
            cout << "Error in row " << row << "!" << endl;
            break;
        default:
            cout << "(" << syn << "," << token << ")" << endl;
            break;
        }
    } while (syn != 0);
    return 0;
}    

题目描述

5.3 词法分析器设计与实现实验报告

任务描述

本实验旨在加深对词法分析器工作流程的理解,掌握基础词法分析实现方法,使用编程语言编写简易词法分析程序,完成对简单代码段的字符扫描、单词拆分与类型识别,实现自动化词法检测与错误提示。

相关知识

词法分析的基本知识

词法分析器(Lexer)是编译过程的首个核心模块,核心作用为从左至右逐字符扫描源程序字符流,依据编程语言构词规则,拆分并识别独立单词符号。

核心功能:

  1. 顺序读取源程序字符流,过滤空白符、换行等无效字符;
  2. 识别具有独立语义的单词单元;
  3. 输出单词分类结果,或反馈词法错误信息。

单词符号五大分类:

  1. 标识符:以字母开头,由字母、数字组成,用于定义变量、函数名;
  2. 关键字(基本字) :语言预定义保留字,如ifintwhile,不可自定义使用;
  3. 常数:包含整型、实型等数值常量;
  4. 运算符 :算术、关系、逻辑运算符(+>=&& 等);
  5. 界符 :语句分隔符号,如;(){},

词法分析统一采用二元式存储格式(单词种别码,单词属性值),通过数字编码区分单词类型,为后续语法分析提供标准化数据。

实验步骤

  1. 定义符号规则与关键字表

    预先定义系统关键字集合、合法运算符、界符集合,划分三类识别逻辑:关键字/标识符识别、数字识别、特殊符号识别。

  2. 分类编写单词识别逻辑

  • 字母开头字符:持续读取后续字母与数字,拼接完整单词,遍历关键字表匹配,区分关键字自定义标识符
  • 数字开头字符:连续读取数字字符,拼接完整数值,判定为常数;
  • 特殊符号字符:通过分支判断,区分单字符、双字符运算符与各类界符,完成符号归类。
  1. 源程序读取与逐行扫描

    读取完整源代码存入字符数组,设置位置指针逐字符遍历,自动过滤空格、换行,循环调用扫描函数,直至读取结束符。

  2. 结果输出与错误处理

    识别合法单词后,以(种别码, 单词值)格式输出;对非法字符、格式错误内容,输出行数与错误提示,保证程序持续运行。

编程要求

基于给定 C/C++ 代码框架,补全三大核心模块:

  1. 关键字与标识符识别代码块;
  2. 数字常量识别代码块;
  3. 运算符、界符等特殊字符识别代码块;
    编译运行程序,实现对测试代码的全自动词法分析,保证识别结果准确、错误提示有效。

测试说明

测试输入

cpp 复制代码
using namespace std;
int main()
{
    int year;
    cout << "hello" << endl;
    return 0;
}
#

运行要求

程序逐一对代码内关键字、标识符、常数、运算符、界符进行拆分,输出标准化二元式结果,正确区分各类单词种别,无程序崩溃、无识别遗漏。


相关推荐
二哈赛车手8 小时前
新人笔记---ApiFox的一些常见使用出错
java·笔记·spring
xian_wwq11 小时前
【学习笔记】AGC协调控制系统概述
笔记·学习
x_yeyue11 小时前
三角形数
笔记·算法·数论·组合数学
憧憬成为java架构高手的小白12 小时前
docker学习笔记(基于b站多个视频学习)【未完结】
笔记·学习
RainCity13 小时前
Java Swing 自定义组件库分享(七)
java·笔记·后端
東隅已逝,桑榆非晚13 小时前
字符函数和字符串函数
c语言·笔记
Upsy-Daisy14 小时前
AI Agent 项目学习笔记(七):RAG 高级扩展——过滤检索、PgVector 与云知识库
人工智能·笔记·学习
智者知已应修善业15 小时前
【51单片机LED闪烁10次数码管显示0-9】2023-12-14
c++·经验分享·笔记·算法·51单片机
智者知已应修善业15 小时前
【51单片机2按键控制1个敞亮LED灯闪烁和熄灭】2023-11-3
c++·经验分享·笔记·算法·51单片机
w20180017 小时前
二年级下册语文看图写话作文:蛋壳的奇妙之旅
笔记