草庐IT

实验一 词法分析器+【编译原理】

日星月云 2023-04-20 原文

实验一 词法分析器+【编译原理】

前言

2023-4-2 20:04:46

以下内容源自《【编译原理】》
仅供学习交流使用

推荐

实验一 词法分析器【编译原理】

实验一 词法分析器+

书接上文

要求:代码的高级功能

更多的关键字(运算符)
需要编写keywords.txt

更多的常数(科学计数法 浮点数 字符串常量)
需要重写analyzer

更多的功能(过滤无效字符、数值转换、宏展开、预包含处理)
需要重写analyzer

还有
出错位置没有行数
需要修改loadInput()逻辑
使其每读入一行,就进行语法分析处理
并且需要row行数属性来配合

下面实现C语言的词法分析

keywords.txt

除了32个关键字,还有用户预编译单词
并把34种运算符拆开为符号
有可能仍有遗漏

1      include
2      define
3      ifdef
4      ifndef
5      auto
6      break
7      case
8      char
9      const
10     continue
11     default
12     do
13     double
14     else
15     enum
16     extern
17     float
18     for
19     goto
20     if
21     int
22     long
23     register
24     return
25     short
26     signed
27     sizeof
28     static
29     struct
30     switch
31     typedef
32     union
33     unsigned
34     void
35     volatile
36     while

此处没有了

identifierList
constantList

operators.txt

新建一个运算符表

注意:
虽然有重复的但是他们的功能不一样
需要根据上下文环境确定具体功能

1         #
2         $
345         \
6         {
7         }
8         ;
9         (
10        )
11        [
12        ]
13        ->
14        .
15        !
16        ~
17        ++
18        --
19        +
20        -
21        *
22        &
23        *
24        /
25        %
26        +
27        -
28        <<
29        >>
30        <
31        <=
32        >
33        >=
34        ==
35        !=
36        &
37        ^
38        |
39        &&
40        ||
41        ?
42        :
43        =
44        +=
45        -=
46        *=
47        /=
48        %=
49        <<=
50        >>=
51        &=
52        ^=
53        |=
54        ,

测试

package s1;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class SeniorLexicalAnalyzer extends AbstractLexicalAnalyzer{

    public List<Symbol> operatorList=new ArrayList<>();//运算符表

    //创建关键字表 根据表3.1实现
    {
        File file = new File("operators.txt");
        if (file.exists()) {
            System.out.println("operators.txt文件存在");
            System.out.println("读取文件,加载运算符表");
            loadOperatorList();
        } else {
            System.out.println("operators.txt文件不存在");
            System.out.println("采用默认的运算符表");
            initOperatorList();
        }
    }

    //读取operators.txt文件的内容加载到operatorList中
    public void loadOperatorList() {
        try {
            BufferedReader reader = new BufferedReader(new FileReader("operators.txt"));
            String line;
            while ((line = reader.readLine()) != null) {
                String[] arr = line.split("\\s+");
                operatorList.add(new Symbol(Integer.parseInt(arr[0]), arr[1]));
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //默认的运算符表
    public void initOperatorList(){
        keywordList.add(new Symbol(1,"="));
        keywordList.add(new Symbol(2,"+"));
        keywordList.add(new Symbol(3,"*"));
        keywordList.add(new Symbol(4,"**"));
        keywordList.add(new Symbol(5,","));
        keywordList.add(new Symbol(6,"("));
        keywordList.add(new Symbol(7,")"));
    }

    //重写 状态转移图实现
    @Override
    public void analyzer() {

    }

    //测试词法分析器
    private void testAnalyzers(){

    }

    //重写出错处理,跳过1下,继续分析
    @Override
    public void procError(){
        System.out.println("词法分析出错"+"\n"+"出错位置为"+position);
        System.out.println("跳过错误,继续分析");
        position++;
        if(ch!=EOF){
            ch=' ';
        }
    }
    //测试关键词表的赋值
    private void testKeywordList(){

        for (Symbol s:keywordList) {
            System.out.println(s);
        }
    }
    
    //测试运算符表的赋值
    private void testOperatorList(){
        for (Symbol s:operatorList) {
            System.out.println(s);
        }
    }


    public static void main(String[] args) {
        SeniorLexicalAnalyzer lex = new SeniorLexicalAnalyzer();
        //测试
        lex.testKeywordList();
        lex.testOperatorList();

        //测试
//        new SeniorLexicalAnalyzer().testAnalyzers();
    }
}

重申:
关键词表中的code没有什么意义
只有单词表中的code有意义
所以运算符表中就没有设置code

测试结果

keywords.txt文件存在
读取文件,加载关键词表
operators.txt文件存在
读取文件,加载运算符表
Symbol{id=1, value='include', code=0}
Symbol{id=2, value='define', code=1}
Symbol{id=3, value='ifdef', code=2}
Symbol{id=4, value='ifndef', code=3}
Symbol{id=5, value='auto', code=4}
Symbol{id=6, value='break', code=5}
Symbol{id=7, value='case', code=6}
Symbol{id=8, value='char', code=7}
Symbol{id=9, value='const', code=8}
Symbol{id=10, value='continue', code=9}
Symbol{id=11, value='default', code=10}
Symbol{id=12, value='do', code=11}
Symbol{id=13, value='double', code=12}
Symbol{id=14, value='else', code=13}
Symbol{id=15, value='enum', code=14}
Symbol{id=16, value='extern', code=15}
Symbol{id=17, value='float', code=16}
Symbol{id=18, value='for', code=17}
Symbol{id=19, value='goto', code=18}
Symbol{id=20, value='if', code=19}
Symbol{id=21, value='int', code=20}
Symbol{id=22, value='long', code=21}
Symbol{id=23, value='register', code=22}
Symbol{id=24, value='return', code=23}
Symbol{id=25, value='short', code=24}
Symbol{id=26, value='signed', code=25}
Symbol{id=27, value='sizeof', code=26}
Symbol{id=28, value='static', code=27}
Symbol{id=29, value='struct', code=28}
Symbol{id=30, value='switch', code=29}
Symbol{id=31, value='typedef', code=30}
Symbol{id=32, value='union', code=31}
Symbol{id=33, value='unsigned', code=32}
Symbol{id=34, value='void', code=33}
Symbol{id=35, value='volatile', code=34}
Symbol{id=36, value='while', code=35}
Symbol{id=1, value='#', code=0}
Symbol{id=2, value='$', code=0}
Symbol{id=3, value='‘', code=0}
Symbol{id=4, value='“', code=0}
Symbol{id=5, value='\', code=0}
Symbol{id=6, value='{', code=0}
Symbol{id=7, value='}', code=0}
Symbol{id=8, value=';', code=0}
Symbol{id=9, value='(', code=0}
Symbol{id=10, value=')', code=0}
Symbol{id=11, value='[', code=0}
Symbol{id=12, value=']', code=0}
Symbol{id=13, value='->', code=0}
Symbol{id=14, value='.', code=0}
Symbol{id=15, value='!', code=0}
Symbol{id=16, value='~', code=0}
Symbol{id=17, value='++', code=0}
Symbol{id=18, value='--', code=0}
Symbol{id=19, value='+', code=0}
Symbol{id=20, value='-', code=0}
Symbol{id=21, value='*', code=0}
Symbol{id=22, value='&', code=0}
Symbol{id=23, value='*', code=0}
Symbol{id=24, value='/', code=0}
Symbol{id=25, value='%', code=0}
Symbol{id=26, value='+', code=0}
Symbol{id=27, value='-', code=0}
Symbol{id=28, value='<<', code=0}
Symbol{id=29, value='>>', code=0}
Symbol{id=30, value='<', code=0}
Symbol{id=31, value='<=', code=0}
Symbol{id=32, value='>', code=0}
Symbol{id=33, value='>=', code=0}
Symbol{id=34, value='==', code=0}
Symbol{id=35, value='!=', code=0}
Symbol{id=36, value='&', code=0}
Symbol{id=37, value='^', code=0}
Symbol{id=38, value='|', code=0}
Symbol{id=39, value='&&', code=0}
Symbol{id=40, value='||', code=0}
Symbol{id=41, value='?', code=0}
Symbol{id=42, value=':', code=0}
Symbol{id=43, value='=', code=0}
Symbol{id=44, value='+=', code=0}
Symbol{id=45, value='-=', code=0}
Symbol{id=46, value='*=', code=0}
Symbol{id=47, value='/=', code=0}
Symbol{id=48, value='%=', code=0}
Symbol{id=49, value='<<=', code=0}
Symbol{id=50, value='>>=', code=0}
Symbol{id=51, value='&=', code=0}
Symbol{id=52, value='^=', code=0}
Symbol{id=53, value='|=', code=0}
Symbol{id=54, value=',', code=0}

词法分析器的状态转移图

C语言的标识符由字母、数字、下划线组成,并且首字母不能是数字(美元符号$也可以作为标识符)

C语言的常量

C语言中的运算符大全(内附优先级表)

代码实现

最后

祝大家逢考必过
点赞收藏关注哦

有关实验一 词法分析器+【编译原理】的更多相关文章

  1. 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.

  2. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  3. .net - 是否有 Ruby .NET 编译器? - 2

    是否有适用于Ruby语言的.NETFramework编译器?我听说过DLR(动态语言运行时),这是否将使Ruby能够用于.NET开发? 最佳答案 IronRuby是Microsoft支持的项目,建立在动态语言运行时之上。 关于.net-是否有Ruby.NET编译器?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/199638/

  4. python - 使用 Python、Ruby 和 Perl 重新编译 MacPort 版本的 MacVim - 2

    关闭。这个问题是off-topic.它目前不接受答案。想改进这个问题吗?Updatethequestion所以它是on-topic用于堆栈溢出。关闭10年前。ImprovethisquestionLinux专家正在转向Mac(10.8)。因为我懒...我使用MacPorts安装MacVim。它似乎安装没有错误。我只需要mvim中的python、ruby和perl支持。$/opt/local/bin/mvim--version|egrep'patches|python|ruby|perl'Includedpatches:1-244,246-646+multi_lang-mzscheme+

  5. ruby - 为什么 `middleman serve` 有效,但是 `middleman build` 编译这个 Sass 失败? - 2

    当我刚刚运行middleman时服务,all.css编译得很好,只包含对+box-shadow(none)的调用:/*line1,/home/yang/asdf/source/stylesheets/content.css.sass*/div{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}但是当我构建网站时,我得到了这个Sass/Compass错误:$middlemanbuildSlim::EmbeddedEngineisdeprecated,itiscalledSlim::EmbeddedinSlim2.0

  6. ruby - 有没有办法在 Ruby 中执行编译时类型检查? - 2

    我知道Ruby是动态和强类型的,但据我所知,由于每个参数缺少显式类型表示法(或契约),当前语法不允许在编译时检查参数类型。如果我想执行编译时类型检查,我有哪些(实际成熟的)选项?更新我的意思是类型检查类似于典型的静态类型语言。比如C。例如,C函数表示每个参数的类型,编译器检查传入的参数是否正确。voidfunc1(structAAAaaa){structBBBbbb;func1(bbb);//Wrongtype.Compiletimeerror.}作为另一个例子,Objective-C通过放置显式类型信息来做到这一点。-(id)method1:(AAA*)aaa{BBB*bbb=[[A

  7. ruby - Ruby 将来可以编译并更快吗? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭7年前。ImprovethisquestionC、Java、C#和Python都是从头编译的。感谢Facebook,PHP现在也可以编译并可以在HHVM上运行,从而提高程序的性能。Ruby不可编译并且比上述语言慢。Ruby有没有可能在未来被编译(就像PHP和HHVM一样)?或者可能有一些原因不能做到?

  8. ruby - 有没有办法让文件夹包含在生产构建中但不让 jekyll 编译它? - 2

    我认为最好的例子是images/文件夹或node_modules/用于将图像和依赖项包含在最终构建中,而无需花费很长时间编译。编辑:抱歉没有具体说明,但我很清楚keep_files和exclude两者都对我的情况没有帮助。exclude从编译和站点构建中排除文件夹和文件,并且每次都需要额外的流水线工具来手动移动它们。keep_files要求文件首先存在于最终构建中,这对于某些生产环境(GitHub的gh-pages等)是不可能的 最佳答案 你可能想看看这个:ExcludingadirectoryfromJekyllwatchP.S.

  9. ruby - 我如何将 Ripper 的 AST 重新编译回 Ruby 代码? - 2

    Ripper是Ruby1.9附带的解析库。它将Ruby代码转换为AST,如下所示:ppRipper.sexp("deffoo;yield:a;return1end")#=>[:program,[[:def,[:@ident,"foo",[1,4]],[:params,nil,nil,nil,nil,nil],[:bodystmt,[[:yield,[:args_add_block,[[:symbol_literal,[:symbol,[:@ident,"a",[1,16]]]]],false]],[:return,[:args_add_block,[[:@int,"1",[1,26]]

  10. ruby - 编译 Ruby 内联 C 代码 - 解决错误 - 2

    我正在尝试获取此Ruby内联C代码http://pastie.org/2825882上类。该代码在vanillaC中运行,但在这里我收到错误和警告。是什么导致了这个错误?./backtrack_inline.rb:67:error:lvaluerequiredasunary'&'operand另外,为什么会出现以下错误?./backtrack_inline.rb:73:error:toofewargumentstofunction'backtrack'检查生成的C代码(http://pastie.org/2826036)我没有发现参数有任何问题。但我也收到以下警告:./backtrac

随机推荐