精华内容
下载资源
问答
  • 给定算术表达式的DFA图,利用Java语言构建Trie树,实现对输入文法的判断
  • 大作业时做的一个java编译原理课程设计,需要的朋友可以参考,包括词法分析,语法分析,四元式以及汇编代码的生成
  • 利用Java编写词法分析器,从文件cifafx.txt中读取程序,并对程序进行词法分析。
  • 编译原理实验要求的用java实现对语句词法分析和语法分析(LL1文法)输出相应的分析结果
  • 编译原理 递归向下 词法分析器 Java实现 编译原理实验二
  • 编译原理课程设计,用java实现简单的计算器功能以及SQL语法分析功能,有具体代码的实现~很实在哦~在JCCreator中可运行成功~
  • Java语言实现编译原理中词法分析器,可以对关键字,运算符,分界符,标识符,常数,无识别符等类型进行识别。可以通过文件输入或者控制台进行输出
  • java程序编译原理实验

    2008-03-19 00:09:27
    java程序编译原理实验
  • 现代编译器 虎书 编译原理 不用多说了,学编译原理都知道
  • 通过JAVA实现SLR1的分析过程

    【问题描述】

        设计一个给定LR分析表和一个句子,能由依据LR分析表输出与句子对应的LR分析表。

    【基本要求】

      动态模拟算法的基本功能是:


    输出句子对应的LR分析表。

    【测试数据】

    句子:i*i+i

    LR分析表


    运行结果:


    本人通过java语言实现了SLR1文法的分析过程,具体的代码已经打包长传:http://download.csdn.net/detail/tab_yls/9833715

    展开全文
  • java实现的词法分析器(编译原理

    热门讨论 2009-04-19 22:50:52
    通过java实现编译原理中的词法分析功能主要包括: 1).识别简单语言的单词符号 2.识别简单语言的基本字、标识符、无符号整数、运算符和界符 例如: 输入: x:=9; if x>0 then x:=2*x+1/3 fi #(可以文件方式读入) ...
  • 编译原理语法分析
  • 主要实现以下四个题目: 题目一:基于语法制导翻译的表达式转换编译器 题目二:说明语句的词法分析器 题目三:基于预测分析方法的表达式语法分析器 题目四:基于算符优先分析方法的表达式语法分析器
  • JAVA编译原理大作业之可编程计算器,适用于编译原理
  • java编译原理

    千次阅读 2018-03-27 16:47:31
    4.Java编译原理1.javac是什么?(1)javac是一种编译器,能够将一种语言规范转换成另一种用语言规范,通常编译器是将便于人们理解的语言规范成机器容易理解的语言规范。(2)javac的任务就是将java源代码语言转换成jvm...
    4.Java编译原理


    1.javac是什么?
    (1)javac是一种编译器,能够将一种语言规范转换成另一种用语言规范,通常编译器是将便于人们理解的语言规范成机器容易理解的语言规范。
    (2)javac的任务就是将java源代码语言转换成jvm能够识别的语言,然后jvm将jvm语言再转化成当前机器能够识别的语言(这样使得对开发者屏蔽与机器相关的细节,并且使得语言的执行与平台无关)
    2.javac编译器的基本结构
    (1)步骤:
    <1>读取源码,进行词法分析。也就是找出源码字节中的关键字,识别出合法的关键字,最后得出一些规范化的Token(中文意思是“标记“、”象征”等)流。
    <2>对Token流进行语法分析,检查关键词的组合是否符合语法,最后得到抽象的语法树(语法树是吧语言的主要此法用一个结构化的形式组合在一起)
    <3>进行语法分析,把难懂的,复杂的语法转化成更加简单的的语法(对计算机来说),最后得到一个注解过后的抽象语法树
    <4>通过字节码生成器将经过注解的抽象语法树生成字节码
    (2)Javac的四大模块:词法分析器、语法分析器、语义分析器和代码生成器
    3.javac工作原理分析:(以openjdk源码为例)
    (1)词法分析器:
    其分析结果就是将这个类中的所有关键字匹配到Token类中的任何一项,最终得到Token流
    <1>javac是如何分辨出一个个的Token?
    javac进行词法分析时会根据java语言规范来控制什么顺序,在什么地方应该出现什么Token(如对package的读取,package语法规范上应该是第一个token,那么在构造javacParser的时候将读取这第一个token,然后往下就是读取IDENTIFIER即是用户定义的名称,在读取类名时如果遇到Token.Dot也就是‘.’将继续往下读,直到读得完成类名即遇到Token.SEMI(“;”)为止)。也就是说,读取每一个Token是由javacParser规定的而Token流的顺序是符合java语言规范的
    <2>如何得知当前读到的Token是Token中的那一项,package就是Token.PACKAGE?
    如何确定字符组合是一个Token的规则实在Scanner的nextToken方法中确定的,每调用该方法一次就会构造一个Token,并且这些Token必然是Token中的任一个项。java中锁由的字符集合都能找到Token中对应的项,Keywords类负责把每个字符集合对应到Token集合中,每一个字符集合都有一个Name对象,而Keywords会先把Token.name转化成Name对象,然后建立token和name的对应关系并保存在key数组中,而其他字符集将对应到Token.Identifier(用户定义的标识?)中。(也就是关键字会有对应表,指定关键字的字符集会对应到对应的Token中,而没找到的将当作用户自定义的Identifier)
    (2)语法分析器
    语法分析器就是将Token流组装成更加结构化的语法树,也就是将一个个的单词组装成语法树
    <1>每个语法树上的语法节点都是JCTree的实例,语法树的一些规则如下:
    [1]每个节点都会实现一个xxtree接口,该接口继承自com.sun.source.tree.Tree。如IfTree语法节点表示一个if类型表达式
    [2]每个节点都是com.sun.tools.javac.tree.JCTree的子类并实现[1]中提及的接口,这个类的类名类似于JCxxx类,
    [3]所有的JCxxx类都作为一个静态内部类定义在JCTree类中
    <2>JCTree类中有如下三个重要的属性项
    [1]Tree tag:每个节点都会用一个整形属性表示,别且每个节点的类型的数值都是前一个节点的类型数值加一(也就是这个属性代表节点的类型,并且类型的数值是上一个节点类型的数值加一?)
    [2]pos:表示语法节点在源文件中的起始位置,文件的起始位置为0,-1的话表示不存在
    [3]type:表示这个语法节点是什么类型,如int、float还是String
    <3>按照顺序(与上述token流的顺序相关,也就是使用java语言规范控制顺序?)读取各个语法树(子树?)及其中的节点,最后把这些子树加到顶层语法节点之下,也就是以package作为pid并且持有JCClassDecl语法节点的集合JCCompilationUnit
    (3)语义分析器
    <1>通过语法分析器获得的语法树还是十分粗糙的,还需要给类添加默认的构造器,检查变量使用前是否已经初始化...等操作(检查是否有语法错误在这一步?),而这些操作将由语义分析器完成
    <2>具体实现:
    [1]主要由com.sun.tools.javac.comp.Enter类实现将java类中的符号(关于符号:转载的一句话——“在java代码中,一个类可能使用另外类或者接口的字段或者调用另外一个类的方法。在编译的时候,class文件中是通过叫做"符号引用"的方式来实现的”。)输入到符号表中:第一步将所有类中出现的符号输入到自身的符号表,并将类符号、类的参数类型符号(泛型参数类型)、超类符号,继承类型符号和继承的接口类型符号都存储到一个未处理列表中。第二步将这个未处理列表中的所有类都解析到各自的符号列表中。
    [2]另外一种的Enter类还会为类 添加默认的构造函数
    [3]处理注解
    [4]检查语义的合法性和进行逻辑判断,如:变量的类型是否匹配,变量在使用前是否初始化,能够推导出泛型方法的参数类型,字符串常量的合并(常量折叠,会将一个字符串常量中的多个字符串合并成一个,如语句“String 是= “aa”+“bb”; “在语义转换后会变成” String s ="aabb"; “,所以写代码的时候多个常量字符串相加的代码其实会被优化成一个字符串而不会产生多个)等
    [5]数据流分析:如检查变量使用前是否正确赋值(这里对比[4]主要是像String一样的对象引用是否赋值,估计上面是针对int等基础类型?),final变量是否不会被重复赋值,方法的返回值类型是否确定,检查异常是否已捕获或向上抛出,是否存在不会被执行的语句,消除无效语句(如永远为false的判断),解除语法糖(如foreach改为标准for循环,变量的自动转换如Integer等基本类型的封装类型与基本类型的赋值操作改为标准的操作内部类的转换(内部类名改为”外部类名$内部类名“),arsert语法的转换等等)
    (4)代码生成器
    <1>负责将结构化的语义树生成最终的java字节码
    <2>生成java字节码主要经过两个步骤:
    [1]将java 方法中的代码块 转成符合JVM语法的命令形式,jvm的所有操作都是基于栈的,所有操作都必须经过出栈和进栈来完成
    [2]按照jvm的文件组织格式将字节码输出到以class文扩展名的文件中
    4.设计模式解释之访问者模式
    <1>其实上述的此法分析器、语法分析器,语义分析器,代码生成器等都会多次遍历语法树,并进行处理,这其实是访问这模式
    <2>访问这模式的设计初衷是为了将稳定的数据结构和变化多端的对数据结构的操作解耦。
    <3>转载资料:“
    访问者模式是一种将算法与对象结构分离的 软件设计模式
    这个模式的基本想法如下:首先我们拥有一个由许多 对象 构成的对象结构,这些对象的 都拥有一个accept 方法 用来接受访问者对象;访问者是一个接口,它拥有一个visit方法,这个方法对访问到的对象结构中不同类型的元素作出不同的反应;在对象结构的一次访问过程中,我们遍历整个对象结构,对每一个元素都实施accept方法,在每一个元素的accept方法中 回调 访问者的visit方法,从而使访问者得以处理对象结构的每一个元素。我们可以针对对象结构设计不同的实在的访问者类来完成不同的操作。
    展开全文
  • Java编译原理

    千次阅读 2015-09-03 13:36:27
    Java编译原理 1. 关于动态加载机制 学习Java比C++更容易理解OOP的思想,毕竟C++还混合了不少面向过程的成分。很多人都能背出来Java语言的特点,所谓的动态加载机制等等。当然概念往往是先记住而后消化的,可有...
    http://wenku.baidu.com/view/f9b1734b87c24028915fc3a3.html

    Java编译原理

    1. 关于动态加载机制

    学习Java比C++更容易理解OOP的思想,毕竟C++还混合了不少面向过程的成分。很多人都能背出来Java语言的特点,所谓的动态加载机制等等。当然概念往往是先记住而后消化的,可有多少人真正去体会过动态加载的机制,试图去寻找过其中的细节呢? 提供大家一个方法:
    在命令行窗口运行Java程序的时候,加上这个很有用的参数:

    java verbose *.class

    这样会清晰的打印出被加载的类文件,大部分是jdk自身运行需要的,最后几行会明显的看到自己用到的那几个类文件被加载进来的顺序。即使你声明了一个类对象,不实例化也不会加载,说明只有真正用到那个类的实例即对象的时候,才会执行加载。这样是不是大家稍微能明白一点动态加载了呢?^_^

    2. 关于寻找class文件原理

    建议大家在入门的时候在命令行窗口编译和运行,不要借助JCreator或者Eclipse等IDE去帮助做那些事情。尝试自己这样做:
    javac -classpath yourpath *.java
    java -classpath yourpath *.class
    也许很多人都能看懂,设置classpath的目的就是告诉编译器去哪里寻找你的class文件. 不过至少笔者今日才弄懂JVM去查询类的原理,编译器加载类要依靠classloader, 而classloader有3个级别,从高到低分别是BootClassLoader(名字可能不准确) , ExtClassLoader, AppClassLoader.

    这3个加载器分别对应着编译器去寻找类文件的优先级别和不同的路径:BootClassLoader对应jre/classes路径,是编译器最优先寻找class的地方。ExtClassLoader对应jre/lib/ext路径,是编译器次优先寻找class的地方,AppClassLoader对应当前路径,所以也是编译器默认找class的地方

    其实大家可以自己写个程序简单的测试,对任何class,例如A, 调用new A().getClass().getClassLoader().toString() 打印出来就可以看到,把class文件放在不同的路径下再次执行,就会看到区别。特别注意的是如果打印出来是null就表示到了最高级 BootClassLoader, 因为它是C++编写的,不存在Java对应的类加载器的名字。

    寻找的顺序是一种向上迂回的思想,即如果本级别找不到,就只能去本级别之上的找,不会向下寻找。不过似乎从Jdk1.4到Jdk1.6这一特点又有改变,没有找到详细资料。所以就不举例子了。告诉大家设计这种体系的是Sun公司曾经的技术核心宫力先生,一个纯种华人哦!

    这样希望大家不至于迷惑为什么总报错找不到类文件,不管是自己写的还是导入的第三方的jar文件(J2ee中经常需要导入的)。

    3. 关于jdk和jre

    大家肯定在安装JDK的时候会有选择是否安装单独的jre,一般都会一起安装,我也建议大家这样做。因为这样更能帮助大家弄清楚它们的区别:

    Jre 是java runtime environment, 是java程序的运行环境。既然是运行,当然要包含jvm,也就是大家熟悉的虚拟机啦,还有所有java类库的class文件,都在lib目录下打包成了jar。大家可以自己验证。至于在windows上的虚拟机是哪个文件呢? 学过MFC的都知道什么是dll文件吧,那么大家看看jre/bin/client里面是不是有一个jvm.dll呢?那就是虚拟机。

    Jdk 是java development kit,是java的开发工具包,里面包含了各种类库和工具。当然也包括了另外一个Jre. 那么为什么要包括另外一个Jre呢?而且jdk/jre/bin同时有client和server两个文件夹下都包含一个jvm.dll。 说明是有两个虚拟机的。这一点不知道大家是否注意到了呢?

    相信大家都知道jdk的bin下有各种java程序需要用到的命令,与jre的bin目录最明显的区别就是jdk下才有javac,这一点很好理解,因为 jre只是一个运行环境而已。与开发无关,正因为如此,具备开发功能的jdk自己的jre下才会同时有client性质的jvm和server性质的 jvm, 而仅仅作为运行环境的jre下只需要client性质的jvm.dll就够了。

    记得在环境变量path中设置jdk/bin路径麽?这应该是大家学习Java的第一步吧, 老师会告诉大家不设置的话javac和java是用不了的。确实jdk/bin目录下包含了所有的命令。可是有没有人想过我们用的java命令并不是 jdk/bin目录下的而是jre/bin目录下的呢?不信可以做一个实验,大家可以把jdk/bin目录下的java.exe剪切到别的地方再运行 java程序,发现了什么?一切OK!

    那么有人会问了?我明明没有设置jre/bin目录到环境变量中啊?

    试想一下如果java为了提供给大多数人使用,他们是不需要jdk做开发的,只需要jre能让java程序跑起来就可以了,那么每个客户还需要手动去设置环境变量多麻烦啊?所以安装jre的时候安装程序自动帮你把jre的java.exe添加到了系统变量中,验证的方法很简单,大家看到了系统环境变量的 path最前面有“%SystemRoot%\system32;%SystemRoot%;”这样的配置,那么再去Windows/system32下面去看看吧,发现了什么?有一个java.exe。

    如果强行能够把jdk/bin挪到system32变量前面,当然也可以迫使使用jdk/jre里面的java,不过除非有必要,我不建议大家这么做。使用单独的jre跑java程序也算是客户环境下的一种测试。

    这下大家应该更清楚jdk和jre内部的一些联系和区别了吧?

    鉴于上回写的一点感想大家不嫌弃,都鼓励小弟继续写下去,好不容易等到国庆黄金周,实习总算有一个休息的阶段,于是这就开始写第二篇了。希望这次写的仍然对志同道合的朋友们有所帮助。上回讲了Java动态加载机制、classLoader原理和关于jdk和jre三个问题。这次延续着讲一些具体的类库。

    1. 关于集合框架类

    相信学过Java的各位对这个名词并不陌生,对 java.util.*这个package肯定也不陌生。不知道大家查询API的时候怎么去审视或者分析其中的一个package,每个包最重要的两个部分就是interfaces和classes,接口代表了它能做什么,实现类则代表了它如何去做。关注实现类之前,我们应该先理解清楚它的来源接口,不管在j2se还是j2ee中,都应该是这样。那么我们先看这三个接口:List、Set、Map。

    也许有些人不太熟悉这三个名字,但相信大部分人都熟悉ArrayList,LinkedList,TreeSet,HashSet,HashMap, Hashtable等实现类的名字。它们的区别也是满容易理解的,List放可以重复的对象集合,Set放不可重复的对象组合,而Map则放 这样的名值对, Key不可重复,Value可以。这里有几个容易混淆的问题:

    到底Vector和ArrayList,Hashtable和HashMap有什么区别?
    很多面试官喜欢问这个问题,其实更专业一点应该这样问:新集合框架和旧集合框架有哪些区别?新集合框架大家可以在这些包中找since jdk1.2的,之前的如vector和Hashtable都是旧的集合框架包括的类。那么区别是?

    a. 新集合框架的命名更加科学合理。例如List下的ArrayList和LinkedList
    b. 新集合框架下全部都是非线程安全的。建议去jdk里面包含的源代码里面自己去亲自看看vector和ArrayList的区别吧。当然如果是jdk5.0之后的会比较难看一点,因为又加入了泛型的语法,类似c++的template语法。

    那么大家是否想过为什么要从旧集合框架默认全部加锁防止多线程访问更新到新集合框架全部取消锁,默认方式支持多线程?(当然需要的时候可以使用collections的静态方法加锁达到线程安全)
    笔者的观点是任何技术的发展都未必是遵循它们的初衷的,很多重大改变是受到客观环境的影响的。大家知道Java的初衷是为什么而开发的麽?是为嵌入式程序开发的。记得上一篇讲到classLoader机制麽?那正是为了节约嵌入式开发环境下内存而设计的。而走到今天,Java成了人们心中为互联网诞生的语言。互联网意味着什么?多线程是必然的趋势。客观环境在变,Java技术也随着飞速发展,导致越来越脱离它的初衷。据说Sun公司其实主打的是J2se,结果又是由于客观环境影响,J2se几乎遗忘,留在大家谈论焦点的一直是j2ee。

    技术的细节这里就不多说了,只有用了才能真正理解。解释这些正是为了帮助大家理解正在学的和将要学的任何技术。之后讲j2ee的时候还会再讨论。

    多扯句题外话:几十年前的IT巨人是IBM,Mainframe市场无人可比。微软如何打败IBM?正是由于硬件飞速发展,对个人PC的需求这个客观环境,让微软通过OS称为了第二个巨人。下一个打败微软的呢?Google。如何做到的?如果微软并不和IBM争大型机,Google借着互联网飞速发展这个客观环境作为决定性因素,避开跟微软争OS,而是走搜索引擎这条路,称为第3个巨人。那么第4个巨人是谁呢?很多专家预言将在亚洲或者中国出现, Whatever,客观环境变化趋势才是决定大方向的关键。当然笔者也希望会出现在中国。

    2. 关于Java设计模式

    身边的很多在看GOF的23种设计模式,似乎学习它无论在学校还是在职场,都成了一种流行风气。我不想列举解释这23种Design Pattern, 我写这些的初衷一直都是谈自己的经历和看法,希望能帮助大家理解。
    首先我觉得设计模式只是对一类问题的一种通用解决办法,只要是面向对象的编程预言都可以用得上这23种。理解它们最好的方法就是亲自去写每一种,哪怕是一个简单的应用就足够了。如果代码实现也记不住的话,记忆它们对应的UML图会是一个比较好的办法,当然前提是必须了解UML。

    同时最好能利用Java自身的类库帮助记忆,例如比较常用的观察者模式,在java.util.*有现成的Observer接口和Observable这个实现类,看看源代码相信就足够理解观察者模式了。再比如装饰器模式,大家只要写几个关于java.io.*的程序就可以完全理解什么是装饰器模式了。有很多人觉得刚入门的时候不该接触设计模式,比如图灵设计丛书系列很出名的那本《Java设计模式》,作者: Steven John Metsker,大部分例子老实说令现在的我也很迷惑。但我仍然不同意入门跟学习设计模式有任何冲突,只是我们需要知道每种模式的概念的和典型的应用,这样我们在第一次编写 FileOutputStream、BufferedReader、PrintWriter的时候就能感觉到原来设计模式离我们如此之近,而且并不是多么神秘的东西。

    另外,在学习某些模式的同时,反而更能帮助我们理解java类库的某些特点。例如当你编写原型(Prototype)模式的时候,你必须了解的是 java.lang.Cloneable这个接口和所有类的基类Object的clone()这个方法。即深copy和浅copy的区别:

    Object.clone()默认实现的是浅copy,也就是复制一份对象拷贝,但如果对象包含其他对象的引用,不会复制引用,所以原对象和拷贝共用那个引用的对象。

    深copy当然就是包括对象的引用都一起复制啦。这样原对象和拷贝对象,都分别拥有一份引用对象。如果要实现深copy就必须首先实现 java.lang.Cloneable接口,然后重写clone()方法。因为在Object中的clone()方法是protected签名的,而 Cloneable接口的作用就是把protected放大到public,这样clone()才能被重写。

    那么又有个问题了?如果引用的对象又引用了其他对象呢?这样一直判断并复制下去,是不是显得很麻烦?曾经有位前辈告诉我的方法是重写clone方法的时候直接把原对象序列化到磁盘上再反序列化回来,这样不用判断就可以得到一个深copy的结果。如果大家不了解序列化的作法建议看一看 ObjectOutputStream和ObjectInputStream

    归根结底,模式只是思想上的东西,把它当成前人总结的经验其实一点都不为过。鼓励大家动手自己去写,例如代理模式,可以简单的写一个Child类, Adult类。Child要买任何东西由Adult来代理实现。简单来说就是Adult里的buy()内部实际调用的是Child的buy(),可是暴露在main函数的却是Adult.buy()。这样一个简单的程序就足够理解代理模式的基本含义了。
    展开全文
  • 编译原理实验LL分析法,Java实现,包括实验报告。
  • java实现的一个Tiger语言编译器,拥有彩色显示功能和动态编辑功能
  • 编译原理语义分析java实现,最新版本~~支持c
  • 这是我大四上学期选修的课程编译原理的实验代码,即使用Java实现PL/0语言的编译器. 功能还不是很完善,但是大体框架已经有了,在添加些代码,多使用一些符合PL/0语法的程序测试一下,修改一些bug,那么它就是一个完美的PL/...
  • 编译原理课程设计,小型编译器的Java实现,包含一课程设计报告
  • 编译原理课程实验题目,实现Java语言词法分析器的功能,包括图形用户界面,可以打开指定的文件,可以保存相应的分析结果。
  • java 词法分析 编译原理 java 词法分析 编译原理 输入要分析的语句(可导入文件) 输出Token表和错误数
  • 编译原理java实现词法分析器

    万次阅读 多人点赞 2017-10-30 13:49:04
    1、闲话最近在学编译原理,需要用语言实现一个词法分析器,其实挺简单的,主要涉及一些语言字符串操作处理,如果会正则表达式的话,感觉实现这个会很简单,但是我并不会啊,然后自己用java实现了,也算是加强了对...

    1、闲话

    最近在学编译原理,需要用语言实现一个词法分析器,其实挺简单的,主要涉及一些语言字符串操作处理,如果会正则表达式的话,感觉实现这个会很简单,但是我并不会啊,然后自己用java实现了,也算是加强了对java的一些字符操作方法的使用。

    实现这个分析器,算法上基本上没什么难度,但是其中涉及的一些逻辑上的思考,说白了就是这么多种情况,有写情况还有交叉部分,你怎么让自己不绕进去,并且用代码实现自己的对这个问题思路。

    那么闲话就说到这,具体我怎么想的,怎么处理的看下面

    2、问题要求

    一、 实验目的

    设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。

    二、 实验内容

    2.1 待分析的简单词法

    (1)关键字:所有的关键字都是小写
    begin if then while do end

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

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

    ID = letter (letter | digit)*
    NUM = digit digit*

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

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

    这里写图片描述

    2.3 词法分析程序的功能:

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


    3、思维导图

    先上思维导图, 根据思维导图看看我是怎么想这个问题的。

    这里写图片描述


    4、代码实现

    关键代码:

        /**
         * 将按间隔符分好的list进行判断,判断是否是合法的子串
         * @param list
         * @return
         */
        @SuppressWarnings("rawtypes")
        public List<Map> GetStringAndSortNum(String[] list) {
            char firstChar;//用于记录第一个首字符
            String keyword="",sortNum="";//需要输出返回的关键字,种别码
            String cType,word;//第一个首字符的类型
    
            //mlist用于返回整个List判断完成后的含有的字符和种别码
            List<Map> mList=new ArrayList<Map>();
    
            for(int i=0;i<list.length;i++){
                Map<String,String>map=new HashMap<String,String>();//m用于保存最后返回的已经判别成功的字和种别码
                //word代表需要进行处理判断的字
                word=list[i];
                //判断word是不是空的串,因为有可能根据空格分割的串中有空的换行符或者空串,不进行处理
                if(word==""||word==null||word.trim()=="")continue;
    
                firstChar=word.charAt(0);
                //获取这个字符的类型
                cType=GetCharType(firstChar);
    
                if(cType=="letter"){
                    if(firstChar=='w'||firstChar=='i'||firstChar=='b'||firstChar=='d'||firstChar=='e'||firstChar=='t'){
                        //获得keyword词
                        Map<String,String>m=new HashMap<String,String>();//m用于保存最后返回的已经判别成功的字和种别码
                        m=GetKeyWord(word);
                        //取出m的值,如果是关键字
                        if(m!=null){
                            keyword=m.get("keyword");
                            sortNum=m.get("sortNum");
                        }
                        //不是关键字,但是包含关键字的前一个字符串
                        else{
                            if(IsID(word)){
                                keyword=word;
                                sortNum=g.getSortNum("ID")+"";
                            }
                            else{
                                System.out.println("这个"+word+"不是合法的ID字符,所在的位置在:第"+(i+1)+"个单词");
                            }
                        }
                    }
                    else{//首字母为字符,但是需要进一步判断是不是合法的ID
                        if(IsID(word)){
                            keyword=word;
                            sortNum=g.getSortNum("ID")+"";
                        }
                        else{
                            System.out.println("这个"+word+"不是合法的ID字符,所在的位置在:第"+(i+1)+"个单词");
                        }
                    }
                }
                if(cType=="digit"){
                    if(IsNum(word)){
                        keyword=word;
                        sortNum=g.getSortNum("NUM")+"";
                    }
                    else{
                        System.out.println("这个"+word+"不是合法的NUM字符,所在的位置在:第"+(i+1)+"个单词");
                    }
                }
                if(cType=="opts"){
                    //获取这个word的长度,如果是一个进行单运算符的判断,如果是2进行多运算符的判断
                    int len=word.length();
                    if(len==1){
                        if(IsSingleOpt(word)){
                            keyword=word;
                            sortNum=g.getSortNum(word)+"";
                        }
                        else if(IsEndOpt(word)){
                            keyword=word;
                            sortNum=g.getSortNum(word)+"";
                        }
                        else{
                            System.out.println("这个"+word+"不是合法的NUM字符,所在的位置在:第"+(i+1)+"个单词");
                        }
                    }
                    else if(len==2){
                        if(IsDoubleOpt(word)){
                            keyword=word;
                            sortNum=g.getSortNum(word)+"";
                        }
                        else{
                            System.out.println("这个"+word+"不是合法的NUM字符,所在的位置在:第"+(i+1)+"个单词");
                        }
                    }
                    else{
                        System.out.println("这个"+word+"不是合法的NUM字符,所在的位置在:第"+(i+1)+"个单词");
                    }
                }
                if(keyword.equals("")||sortNum.equals("")||keyword==""||sortNum=="")
                    continue;
                else{
                    map.put("keyword", keyword);
                    map.put("sortNum", sortNum);
                    mList.add(map); 
                    keyword="";
                    sortNum="";
                }
            }
            return mList;
        }
    

    代码实现后的运行效果:

    这里写图片描述

    测试用的文件:

    begin x := 9 ; if x > 9 then x := 2 * x + 1 / 3
    x = 3 ;
    begin
    $y := 2
    if x == $y :
    y = qqwe221 ;
    

    其实看起来很复杂的一个词法分析器,当真正借组思维导图或者其他的流程图表示出来的时候,实现思路在脑子里就会很清晰,自己下一步要干嘛,怎么实现,当自己想到这些的时候,可以用自己喜欢的形式记录下来,这样实现起来就只需要用代码把自己的思路复现即可。

    养成一种编程的习惯有时候比掌握一门语言对自己更有利。

    本词法分析器的源码和测试文件均放在github上,需要的请自行进行查看。
    https://github.com/Ashplumage/Compile-principle

    展开全文
  • 编译原理,词法分析,java, 附带图像界面,完全分析
  • 编译原理语义分析java实现 语义分析 歧义分析
  • 编译原理实验java

    2018-01-09 22:55:35
    编译原理实验,包括词法分析,语法分析,中间代码生成等。java实现,采用递归下降的方法。
  • 编译原理课程实验题目,实现了C语言、Java语言词法分析器的功能,包括图形用户界面,可以打开指定的文件,可以保存相应的分析结果。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 207,081
精华内容 82,832
关键字:

Java实现编译原理