编译原理大作业(用java编写小型GCC 编译器)

以前只用编译器编译程序,现在学完编译原理这门课以后,通过编译大作业,我对编译器的工作原理有了比较清晰的认识

编译器的工作原理

编译器 (Compiler) 是一种将由一种语言编写的程序转换为另一种编程语言的可执行程序. 现代软件对于编译器的需求远甚从前, 究其原因很简单: 作为中间层, 编译器是构建更高层抽象的基础设施. 编译器意欲将人类可阅读的高阶代码, 翻译为机器能运行的低阶代码.

现代编译器的主要工作流程为: 源代码(source code)→ 预处理器(preprocessor)→ 编译器(compiler)→ 汇编程序(assembler)→ 目标代码(object code)→ 链接器(Linker)→ 可执行文件(executables)1.

其中, 编译器位于一个最重要的位置: 将源码转为汇编(上文提到的css, js也可认为是一种汇编).

  1. 词法分析

词法分析器根据词法规则识别出源程序中的各个记号(token),每个记号代表一类单词(lexeme)。源程序中常见的记号可以归为几大类:关键字、标识符、字面量和特殊符号。词法分析器的输入是源程序,输出是识别的记号流。词法分析器的任务是把源文件的字符流转换成记号流。本质上它查看连续的字符然后把它们识别为“单词”。

  1. 语法分析

语法分析器根据语法规则识别出记号流中的结构(短语、句子),并构造一棵能够正确反映该结构的语法树。

  1. 语义分析

语义分析器根据语义规则对语法树中的语法单元进行静态语义检查,如果类型检查和转换等,其目的在于保证语法正确的结构在语义上也是合法的。

  1. 中间代码生成

中间代码生成器根据语义分析器的输出生成中间代码。中间代码可以有若干种形式,它们的共同特征是与具体机器无关。最常用的一种中间代码是三地址码,它的一种实现方式是四元式。三地址码的优点是便于阅读、便于优化。

  1. 中间代码优化

优化是编译器的一个重要组成部分,由于编译器将源程序翻译成中间代码的工作是机械的、按固定模式进行的,因此,生成的中间代码往往在时间和空间上有很大浪费。当需要生成高效目标代码时,就必须进行优化。

  1. 目标代码生成

目标代码生成是编译器的最后一个阶段。在生成目标代码时要考虑以下几个问题:计算机的系统结构、指令系统、寄存器的分配以及内存的组织等。编译器生成的目标程序代码可以有多种形式:汇编语言、可重定位二进制代码、内存形式。

7 符号表管理

符号表的作用是记录源程序中符号的必要信息,并加以合理组织,从而在编译器的各个阶段能对它们进行快速、准确的查找和操作。符号表中的某些内容甚至要保留到程序的运行阶段。

8 出错处理

用户编写的源程序中往往会有一些错误,可分为静态错误和动态错误两类。所谓动态错误,是指源程序中的逻辑错误,它们发生在程序运行的时候,也被称作动态语义错误,如变量取值为零时作为除数,数组元素引用时下标出界等。静态错误又可分为语法错误和静态语义错误。语法错误是指有关语言结构上的错误,如单词拼写错、表达式中缺少操作数、begin和end不匹配等。静态语义错误是指分析源程序时可以发现的语言意义上的错误,如加法的两个操作数中一个是整型变量名,而另一个是数组名等。

编译大作业:

LL1文法:

1、 文法开始:

S->void main(){A}

2、 声明:

X->YZ;

Y->int|char|bool

Z->UZ’

Z’->,Z|U?>idU′U′?>=L|

3、 赋值:

R->id=L;

4、 算术运算:

L->TL’

L’->+L|-L|T?>FT′T′?>?T|/T|

F->(L)

F->id|num

O->++|–|Q?>idO|

5、 布尔运算

E->HE’

E’->&&E|H?>GH′H′?>||HH′?>

G->FDF

D-><|>|==|!=

G->(E)

G->!E

5、控制语句

B->if (E){A}else{A}

B->while(E){A}

B->for(YZ;G;Q){A}

6、功能函数

B->printf(P);

B->scanf(id);

P->id|ch|num

7、复合语句

A->CA

C->X|B|R

A->$

1、构造LL1属性翻译文法

构造LL1属性翻译文法即在原有LL1文法基础上加上动作符号,并给非终结符和终结符加上一定属性,给动作符号加上语义子程序。对原有LL1文法改进的地方如下:

1、 赋值:

产生式 语义子程序

R->@ASS_R id [email protected] EQ; @ASS{R.VAL=id并压入语义栈}

@EQ{RES=R.VAL,OP=’=’,ARG1=L.VAL,

new fourElement(OP,ARG1,/, RES)}

U->@ASS_UidU’ {U.VAL=id并压入语义栈}

U’->=L|[email protected]_U’ {RES=U.VAL,OP=’=’,ARG1=L.VAL,new fourElement(OP,ARG1,/, RES)}

2、 算术运算:

产生式 语义子程序

L->TL’@ADD_SUB {If(OP!=null) RES= NEWTEMP; L.VAL=RES,并压入语义栈;New fourElement(OP, T.VAL;,L’VAL, RES),

}

L’->[email protected] {OP=+,ARG2=L.VAL}

L’->[email protected] {OP=-,ARG2=L.VAL}

L’->$

T->FT’@DIV_MUL { if (OP !=null) RES= NEWTEMP;T.VAL=RES;

new FourElement(OP,F.VAL,ARG2, RES)

else ARG1=F.VAL; }

T’->/[email protected] {OP=/,ARG2=T.VAL}

T’->[email protected] {OP=,ARG2=T.VAL}

T’->F?>(L)@VOLF.VAL?>L.VALF?>@ASSFnum|idF.VAL=num|idQ?>idO|

O->@SINGLE_OP++|– {OP=++|–}

3、 布尔运算

产生式 语义子程序

G->[email protected]{OP=D.VAL;ARG1=F(1).VAL;ARG2=F(2).VAL,RES=NEWTEMP;

New fourElement(OP,F.VAL,ARG2, RES );G.VAL=RES并压入语义栈}

D->@COMPARE_OP<|>|==|!={D.VAL=<|>|==|!=,并压入语栈}

4、 控制语句

产生式 语义子程序

B->if (G)@IF_FJ{A}@IF_BACKPATCH_FJ @IF_RJ else{A}@IF_BACKPATCH_RJ

@IF_FJ{OP=”FJ”;ARG1=G.VAL;RES=if_fj, New fourElement(OP,ARG1,/, RES ),将其插入到四元式列表中第i个}

@IF_BACKPATCH_FJ{回填前面假出口跳转四元式的跳转序号, BACKPATCH (i,if_fj)}

B->while(G)@WHILE_FJ{A}@[email protected]_BACKPATCH_FJ {参照if else}

B->for(YZ;[email protected]_FJ;Q){[email protected]}@[email protected]_BACKPATCH_FJ {参照if else }

@SINGLE {ARG1=id;RES=NEWTEMP;New fourElement(OP,ARG1,/,RES)}

说明:

(1)、R.VAL表示符号R的值,VAL是R的一个属性,其它类似。

(2)、NEWTEMP()函数:每调用一次生成一个临时变量,依次为T1,T2,…Tn。

(3)、BACKPATCH (int i,int res):回填函数,用res回填第i个四元式的跳转地址。

(4)、new fourElement(String OP,String ARG1,String ARG2,String RES ):生成一个四元式

(OP,ARG1,ARG2,RES)

主界面代码

package gui;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;

import javax.swing.*;
import compiler.*;

public class MainFrame extends JFrame {

    TextArea sourseFile;//用来显示源文件的文本框
    String soursePath;// 源文件路径
    String LL1Path;
    String wordListPath;
    String fourElementPath;
    LexAnalyse lexAnalyse;

    Parser parser;
    public MainFrame() {
        this.init();
    }

    public void init() {

        Toolkit toolkit = Toolkit.getDefaultToolkit();
        Dimension screen = toolkit.getScreenSize();
        setTitle("向贤章C语言小型编译器");
        setSize(750, 480);
        super.setResizable(false);
        super.setLocation(screen.width / 2 - this.getWidth() / 2, screen.height
                / 2 - this.getHeight() / 2);
        this.setContentPane(this.createContentPane());
    }

    private JPanel createContentPane() {
        JPanel p = new JPanel(new BorderLayout());
        p.add(BorderLayout.NORTH, createUpPane());
        p.add(BorderLayout.CENTER, createcCenterPane());
        p.add(BorderLayout.SOUTH, creatBottomPane());
        // p.setBorder(new EmptyBorder(8,8,8,8));
        return p;
    }

    private Component createUpPane() {
        JPanel p = new JPanel(new FlowLayout());
        final FilePanel fp = new FilePanel("选择待分析文件");
        //final FilePanel fp1 = new FilePanel("xiang");
        JButton button = new JButton("确定");
        button.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                String text;
                try {
                    soursePath = fp.getFileName();
                    text = readFile(soursePath);
                    sourseFile.setText(text);

                } catch (IOException e1) {
                    e1.printStackTrace();
                }            

            }
        });
        p.add(fp);
        //p.add(fp1);
        p.add(button);
        return p;
    }

    private Component createcCenterPane() {
        JPanel p = new JPanel(new BorderLayout());
        JLabel label = new JLabel("源文件如下:");
        sourseFile = new TextArea();
        sourseFile.setText("");
        p.add(BorderLayout.NORTH, label);
        p.add(BorderLayout.CENTER, sourseFile);
        return p;
    }

    private Component creatBottomPane() {
        JPanel p = new JPanel(new FlowLayout());
        JButton bt1 = new JButton("词法分析");
        JButton bt2 = new JButton("语法分析");
        JButton bt4 = new JButton("中间代码生成");
        JButton bt5 = new JButton("目标代码生成");
        bt1.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    lexAnalyse=new LexAnalyse(sourseFile.getText());
                    wordListPath = lexAnalyse.outputWordList();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                InfoFrame inf = new InfoFrame("词法分析", wordListPath);

                inf.setVisible(true);
            }
        });
        bt2.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
            lexAnalyse=new LexAnalyse(sourseFile.getText());
            parser=new Parser(lexAnalyse);
                try {
                    parser.grammerAnalyse();
                    LL1Path= parser.outputLL1();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                InfoFrame inf = new InfoFrame("语法分析", LL1Path);
                inf.setVisible(true);
            }
        });

        bt4.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    lexAnalyse=new LexAnalyse(sourseFile.getText());
                    parser=new Parser(lexAnalyse);
                    parser.grammerAnalyse();
                    fourElementPath=parser.outputFourElem();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                InfoFrame inf = new InfoFrame("中间代码生成", fourElementPath);
                inf.setVisible(true);
            }
        });
        bt5.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    lexAnalyse=new LexAnalyse(sourseFile.getText());
                    parser=new Parser(lexAnalyse);
                    parser.grammerAnalyse();
                    fourElementPath=parser.outputFourElem();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                huibian inf = new huibian("目标代码生成", fourElementPath);
                inf.setVisible(true);
            }
        });

        p.add(bt1);
        p.add(bt2);
        //p.add(bt3);
        p.add(bt4);
        p.add(bt5);
        return p;
    }

    public static String readFile(String fileName) throws IOException {
        StringBuilder sbr = new StringBuilder();
        String str;
        FileInputStream fis = new FileInputStream(fileName);
        BufferedInputStream bis = new BufferedInputStream(fis);
        InputStreamReader isr = new InputStreamReader(bis, "UTF-8");
        BufferedReader in = new BufferedReader(isr);
        while ((str = in.readLine()) != null) {
            sbr.append(str).append(‘\n‘);
        }
        in.close();
        return sbr.toString();
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MainFrame mf = new MainFrame();
        //TinyCompiler tinyCompiler = new TinyCompiler();
        //mf.tinyCompiler = tinyCompiler;
        mf.setVisible(true);
    }
}

class FilePanel extends JPanel {
    FilePanel(String str) {
        JLabel label = new JLabel(str);
        JTextField fileText = new JTextField(35);
        JButton chooseButton = new JButton("浏览...");
        this.add(label);
        this.add(fileText);
        this.add(chooseButton);
        clickAction ca = new clickAction(this);
        chooseButton.addActionListener(ca);
    }

    public String getFileName() {
        JTextField jtf = (JTextField) this.getComponent(1);
        return jtf.getText();
    }

    // 按钮响应函数
    private class clickAction implements ActionListener {
        private Component cmpt;

        clickAction(Component c) {
            cmpt = c;
        }

        public void actionPerformed(ActionEvent event) {
            JFileChooser chooser = new JFileChooser();
            chooser.setCurrentDirectory(new File("."));
            int ret = chooser.showOpenDialog(cmpt);
            if (ret == JFileChooser.APPROVE_OPTION) {
                JPanel jp = (JPanel) cmpt;
                JTextField jtf = (JTextField) jp.getComponent(1);//获取zujian
                jtf.setText(chooser.getSelectedFile().getPath());
            }
        }
    }
}

词法分析:

语法分析

中间代码生成

目标代码生成

时间: 2024-10-18 04:43:16

编译原理大作业(用java编写小型GCC 编译器)的相关文章

编译原理大作业暂存

#include"scanner.h" typedef double(*FuncPtr)(double); //语法树的节点 struct ExprNode //type of syntax tree's node { enum Token_Type OpCode; //PLUS MINUS DIV POWER FUNC CONST_ID union { struct{ExprNode *Left,*Right;}CaseOperator; struct{ExprNode *Child

编译原理课程作业1 消除无用产生式

前言: 一年前在知乎上看到一个回答,答主说自己学了两天Python,用十几个小时做完了全部的编译原理课程作业,当时吓傻了我,现在看来,虽然两天学会比不上,但Python做课程作业的速度简直是快,课程作业1里我还傻傻的用list的extend和append,加上set函数,到第二次作业里我才发现, 没有什么结构体是一个list不能解决的,如果有,那就再套一个list 课程作业题: 消除无用产生式 # -*- coding: utf-8 -*- class Solution: def __init_

编译原理第一次作业

一.编译原理是什么?原理我们的计算机系的一门课程,它在我们的科学发展中起到了很重要的作用,也可以说是计算机系统的核心部分之一.它运用编译器.编译系统将我们的语言和计算机的语言进行转换等.内容包括语言和文法.词法分析.语法分析.语法制导翻译.中间代码生成.存储管理.代码优化和目标代码生成. 二.学习编译原理有什么好处? 1.语法分析,语义分析,和代码优化的知识,还有技巧,思想能让我终生受益. 2.我得以学习大量优美的算法,并得以欣赏理论和实践在编译器开发中如何美妙地结合在一起. 3.我可以了解怎样

编译原理-第二章 一个简单的语法指导编译器-2.4 语法制导翻译

语法制导翻译: 定义:语法制导翻译是通过向一个文法的产生式附加一些规则或程序片段而得到的 功能:给定词法单元流,通过向一个文法产生式附加一些语义动 作,语法制导分析产生语法分析树,并实现翻译动作 相关概念: 属性:表示与某个程序构造相关的任意的量,因为用文法符号(终结符号或非终结符号)来表示程序构造,所以可将属性的概念从程序构造扩展到表示这些构造的文法符号上 综合属性:如果某个属性在语法分析树节点N上的值由N的子节点和N本身的属性值确定,则该属性为综合属性,其性质为只需对语法分析树进行一次自底向

编译原理小作业词法分析程序

词法分析程序所参照的编码如70页表3.3 (<编译技术>张莉等著.--北京:高等教育出版社,2016.9.ISBN: 978-7-04-046317-0) 用Java语言实现如下: 1 import java.io.IOException; 2 import java.util.Arrays; 3 import java.util.HashMap; 4 import java.util.Map; 5 6 class Code{ 7 public static final int BEGINSY

编译原理课程作业2

NFA匹配字符串,突然意识到可以用多层的list,然后整个作业就没有难度了,递归部分一直错我都怀疑人生了,结果发现是类里的递归声明要加类名.. # -*- coding: utf-8 -*- import sys class io(): """read the NFA from file""" def __init__(self,strlist): self.strlist = strlist def i(self): if(len(sys.ar

软件工程课后作业——用JAVA编写的随机产生30道四则运算

1 package com.java.sizeyunsuan; 2 3 public class lianxi { 4 String f() 5 { 6 int i=(int)(Math.random()*10); 7 int j=(int)(Math.random()*10); 8 if(i>=j) 9 { 10 int temp=i; 11 i=j; 12 j=temp; 13 } 14 return(i+"/"+j); 15 } 16 public static void

[编译原理]用BDD方式开发lisp解释器(编译器)|开发语言java|Groovy|Spock

lisp是一门简单又强大的语言,其语法极其简单: (+ 1 2 ) 上面的意思 是:+是方法或函数,1 ,2 是参数,fn=1+2,即对1,2进行相加求值,结果是:3 双括号用来提醒解释器开始和结束. 之前在iteye写过一篇文章来简单介绍怎么写lisp的解释器: http://gyc567.iteye.com/blog/2242960 同时也画了一张草图来说明: 因为lexer(词法分析器)主要工作就是把程序的字符串表达式转化为tokens.(Pair),以下是百科对词法分析的说明: 词法分析

编译原理语法分析实验(Java实现)

import java.util.Stack; public class LL1 { //加入同步符号的LL(1)分析表 private String [][] analysisTable = new String[][]{ {"TZ","","","TZ","synch","synch"}, {"","+TZ","",&quo