草庐IT

编译原理——词法分析器(C/C++代码实现)

小航同学吖 2023-06-28 原文

目录

0 实验目的:

1 实验要求:

2 实验内容:

3 实验思路:

4 实验代码:

5 实验结果:

6 实验总结:

7 实验程序以及实验报告下载链接:


0 实验目的:

设计、编制、实现并调试一个词法分析器,加深对词法分析的理解。


1 实验要求:

根据编译原理理论课所讲授的“单词的转换图”。如下图,编写识别单词的词法分析器,控制台输出识别出的每个单词。


2 实验内容:

1.待分析的简单的词法:

(1).关键字:

begin if then while do end 等等;

(2).运算法和界符:

:= + - * / < <= <> > >= = ; ( ) #

(3).其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:

ID = letter(letter|digit)*

NUM = digit digit*

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

2.各种单词符号对应的种别码:

各种单词符号对应的种别码
单词符号种别码单词符号种别码
begin117
if2:=18
then3<20
while4<>21
do5<=22
end6>23
letter(letter|digit)*10>=24
digit digit*11=25
+13;26
-14(27
*15)28
/16#

0

3.词法分析器的功能:
输入:所给文法的源程序字符串。
输出:二元组(syn,token,sum)构成的序列。
其中:syn为单词种别码;
           token为存放的单词自身字符串;
           sum为整型常数。
例如:对源程序begin a:=9 if a>b then x:=2*a+1/3; end的源文件,经过词法分析后输出如下序列:
(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)......

3 实验思路:

  1. 首先我们应该确认待分析的五类简单的单词字符(关键字,标识符,常数,运算符,界符)。同时,我们也要知道单词符号的种类值。
  2. 将整个程序分成五个部分:判断关键字函数,判断字母函数,判断数字函数,核心子程序(语法分析程序),主函数。
  3. 设一个token数组,接收控制台输入字符流,并送给语法分析程序。同时,设置一个存放关键字key的数组。语法分析程序读取每个字符并进行判断(字母或者下划线,符号,数字)
    (1).如果是字母或者下划线,读取字符,直到下一个字符不是字母、下划线或者数字,将这一串字符保存到数组。进而与关键字数组比较,确定是关键字还是标识符。
    (2).如果是数字,读取字符直到不是数字。
    (3).如果是运算符或者界符,读取字符,并超前读取一位字符,先确定没有争议的字符,接着判断有争议的字符,如果判断异常,则输出对应的返回值。
  4. 主函数调用核心子程序(语法分析程序),并按照(种别码,单词字符)的形式输出,结束程序。

4 实验代码:

#include <bits/stdc++.h>
using namespace std;
int isDigit();
int isAlpha();
int isKey();
void scan(int &attr, int &i, char s[],int &n); 
char iskey[6][50] = {"if", "then", "begin", "while", "do", "end"};
char token[50];
//主函数 
int main()
{
    char s[100];
    printf("请输入字符串(以#结尾)\n"); 
    int flag=0;
    while (scanf("%s", s))
    {
    	if(strcmp(s, "#") == 0)
    	break;
        int i = 0;
        int n=1;
        int attr;     
        if(flag==0)
        {
        	printf("(种别码,单词属性)\n");
        	flag=1;
		}
        while (i <strlen(s))
        {
            scan(attr, i, s,n);
            if(n==1)
            printf("(%d,%s)\n", attr, token);
        }
    }
    return 0;
}
int isAlpha(char ch)//判断是不是字母 
{
    if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
        return 1;
    else
        return 0;
}
int isKey(char s[])//判断关键字 
{
    for (int i = 0; i < 6; i++)
    {
        if (strcmp(s, iskey[i]) == 0)
        {
            return i + 1;
        }
    }
    return -1;
}
int isDigit(char ch)//判断是不是数字 
{
    if (ch >= '0' && ch <= '9')
        return 1;
    else
        return 0;
}
void scan(int &attr, int &i, char s[],int &n)//核心子程序(语法分析程序) 
{
    int temp = 0;
    if (s[i] == ' ')
        i++;
    if (isAlpha(s[i]))//开头是字母
    {
        while (isDigit(s[i]) || isAlpha(s[i]))
        {
            token[temp++] = s[i];
            i++;
        }
        token[temp] = '\0';
        attr = isKey(token);
        if (attr == -1)
        {
            attr = 10;
        }
    }
    else if (isDigit(s[i]))//开头是数字
    {
        while (isDigit(s[i]))
        {
            token[temp++] = s[i];
            i++;
        }
        token[temp] = '\0';
        attr = 11;
    }
    else//如果是运算符或者界符
    {
        switch (s[i])
        {
        case '+':
            attr = 13;
            token[0] = s[i];
            token[1] = '\0';
            break;
        case '-':
            attr = 14;
            token[0] = s[i];
            token[1] = '\0';
            break;
        case '*':
            attr = 15;
            token[0] = s[i];
            token[1] = '\0';
            break;
        case '/':
            attr = 16;
            token[0] = s[i];
            token[1] = '\0';
            break;
        case '=':
            attr = 25;
            token[0] = s[i];
            token[1] = '\0';
            break;
        case ';':
            attr = 26;
            token[0] = s[i];
            token[1] = '\0';
            break;
        case '(':
            attr = 27;
            token[0] = s[i];
            token[1] = '\0';
            break;
        case ')':
            attr = 28;
            token[0] = s[i];
            token[1] = '\0';
            break;
        case '#':
            attr = 0;
            token[0] = s[i];
            token[1] = '\0';
            break;
        }
        if (s[i] == ':')
        {
            token[temp++] = s[i];
            if (s[i + 1] == '=')
            {
                i++;
                token[temp++] = s[i];
                attr = 18;
            }
            else
            {
                attr = 17;
            }
            token[temp] = '\0';
        }
        if (s[i] == '<')
        {
            token[temp++] = s[i];
            if (s[i + 1] == '>')
            {
                i++;
                token[temp++] = s[i];
                attr = 21;
            }
            else if (s[i + 1] == '=')
            {
                i++;
                token[temp++] = s[i];
                attr = 22;
            }
            else
            {
                attr = 20;
            }
            token[temp] = '\0';
        }
        if (s[i] == '>')
        {
            token[temp++] = s[i];
            if (s[i + 1] == '=')
            {
                i++;
                token[temp++] = s[i];
                attr = 24;
            }
            else
            {
                attr = 23;
            }
            token[temp] = '\0';
        }
        i++;
    }
}

5 实验结果:


6 实验总结:

这个实验的要求不一样,如果你需要的不是这个,你可以稍微改一下,需要探讨的话可以与我私信。 

7 实验程序以及实验报告下载链接:

编译原理实验:包括实验一词法分析器,实验二进制分析,实验三语法分析器,实验四SLR语法分析器等其中含有实验报告,实验代码等等-C++文档类资源-CSDN文库https://download.csdn.net/download/qq_58773908/87356376

 

有关编译原理——词法分析器(C/C++代码实现)的更多相关文章

  1. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  2. ruby-on-rails - Rails 源代码 : initialize hash in a weird way? - 2

    在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has

  3. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  4. ruby-on-rails - 浏览 Ruby 源代码 - 2

    我的主要目标是能够完全理解我正在使用的库/gem。我尝试在Github上从头到尾阅读源代码,但这真的很难。我认为更有趣、更温和的踏脚石就是在使用时阅读每个库/gem方法的源代码。例如,我想知道RubyonRails中的redirect_to方法是如何工作的:如何查找redirect_to方法的源代码?我知道在pry中我可以执行类似show-methodmethod的操作,但我如何才能对Rails框架中的方法执行此操作?您对我如何更好地理解Gem及其API有什么建议吗?仅仅阅读源代码似乎真的很难,尤其是对于框架。谢谢! 最佳答案 Ru

  5. ruby - 模块嵌套代码风格偏好 - 2

    我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

  6. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  7. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  8. ruby - Sinatra set cache_control to static files in public folder编译错误 - 2

    我不知道为什么,但是当我设置这个设置时它无法编译设置:static_cache_control,[:public,:max_age=>300]这是我得到的syntaxerror,unexpectedtASSOC,expecting']'(SyntaxError)set:static_cache_control,[:public,:max_age=>300]^我只想将“过期”header设置为css、javaascript和图像文件。谢谢。 最佳答案 我猜您使用的是Ruby1.8.7。Sinatra文档中显示的语法似乎是在Ruby1.

  9. 程序员如何提高代码能力? - 2

    前言作为一名程序员,自己的本质工作就是做程序开发,那么程序开发的时候最直接的体现就是代码,检验一个程序员技术水平的一个核心环节就是开发时候的代码能力。众所周知,程序开发的水平提升是一个循序渐进的过程,每一位程序员都是从“菜鸟”变成“大神”的,所以程序员在程序开发过程中的代码能力也是根据平时开发中的业务实践来积累和提升的。提高代码能力核心要素程序员要想提高自身代码能力,尤其是新晋程序员的代码能力有很大的提升空间的时候,需要针对性的去提高自己的代码能力。提高代码能力其实有几个比较关键的点,只要把握住这些方面,就能很好的、快速的提高自己的一部分代码能力。1、多去阅读开源项目,如有机会可以亲自参与开源

  10. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

随机推荐