编译原理 实验二 简单计算器的设计与实现

Posted _DiMinisH

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译原理 实验二 简单计算器的设计与实现相关的知识,希望对你有一定的参考价值。

实验二 简单计算器的设计与实现 

一、实验目的

  综合运行词法分析器、语法分析器等原理实现一个具有加、乘功能的简单计算器,该计算器满足乘法优先级高于加法优先级,且仅处理非负整数。

二、实验内容

  1. 对输入的符号串首先进行词法分析,提取操作数及操作符,以输出的单词符号为输入进行语法分析。
  2. 要求以算符优先分析的方法完成语法分析工作,识别输入串是否是文法描述语言的句子
  3. 对句子进行求值,求值方式可以是遍历语法树或者是建立一个逆波兰式,对逆波兰式进行求值。

三、实验要求

  1. 从文件读入算术表达式/或者从终端输入;
  2. 词法分析,用二元组表示输出结果;
  3. 语法分析,算符优先分析方法进行自下而上的语法分析并构造语法树;
  4. 识别出的句子进行求值,遍历语法树求值或者先建立逆波兰式再求值;

四、输出

P -> (E) | i
T -> T*F | F
E -> E+T | T
F -> PF | P
非终结符: P T E F 
终结符: ( ) i * +firstVt(E) : + , * ,, ( , i
firstVt(T) : * ,, ( , i
firstVt(F) :, ( , i
firstVt(P) : ( , i
lastVt(E) : + , * ,, ) , i
lastVt(T) : * ,, ) , i
lastVt(F) :, ) , i
lastVt(P) : ) , i
优先关系表:
- ( ) i * + ↑ # 
( < = < < < < - 
) - > - > > > > 
i - > - > > > > 
* < > < > > < > 
+ < > < < > < >< > < > > < > 
# < - < < < < = 


常量 : 6
界符 : (
运算符 : *
常量 : 5
运算符 : +
常量 : 4
界符 : )
带判断的产生式: i*(i+i)
规约串为: i
归约到: P
规约串为: i
归约到: P
规约串为: i
归约到: P
规约串为: P+P
归约到: P
规约串为: (P)
归约到: P
规约串为: P*P
归约到: P
恭喜你,该文法是算符优先文法
语法树:
i -> P
i -> P
i -> P
P+P -> P
(P) -> P
P*P -> P
表达式的值为: 54


下面是构造形象语法树:
是否进行手动构建 > 

五、代码 (使用Maven,因为用到了Lombok依赖)

词法分析器代码链接:词法分析器

下面是算符优先分析法代码
目前实现计算FirstVt和LastVt集合, 构造优先关系表, 规约过程,简单语法树

代码中有手动构建语法树,如果选择自动构建,输入n 或者 N即可

package main.experiment2;

import lombok.Getter;
import main.experiment1.Pair;
import main.experiment1.WordAnalysis;

import java.util.*;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

/**
 * @author Diminish
 * @version 1.0
 * @since 17
 */
@Getter
public class Grammar 

    /**
     * firstVt 集合
     * Key : 非终结符
     * Value : 集合内容
     * */
    private final Map<String, List<String>> firstTerminators = new TreeMap<>();

    /**
     * lastVt 集合
     * Key : 非终结符
     * Value : 集合内容
     * */
    private final Map<String, List<String>> lastTerminators = new TreeMap<>();

    /**
     * 非终结符集合
     * */
    private List<String> nonTerminators = new ArrayList<>();

    /**
     * 终结符集合
     * */
    private List<String> terminators = new ArrayList<>();

    /**
     * <p>语法</p>
     * */
    private final Map<String, List<String>> grammar = new HashMap<>();

    /**
     * 语法开始符号
     * */
    private String startTerminator = null;

    /**
     * 优先关系表
     * */
    private String[][] precedenceRelationList;

    /**
     * 语法树
     * */
    private Node root;

    /**
     * <p>默认语法:</p>
     *      <p>A -> A+B | B</p>
     *      <p>B -> B*C | C</p>
     *      <p>C -> i</p>
     * */
    Grammar () 
        grammar.put("A", List.of("A+B", "B"));
        grammar.put("B", List.of("C*C", "C"));
        grammar.put("C", List.of("i"));
        startTerminator = "A";
        initializeGrammar();
    

    /**
     * <p>构造指定语法</p>
     * @param start 每个句型的开始符号
     * @param generateExpression 每个开始符号对应的表达式
     * */
    Grammar (List<String> start, List<List<String>> generateExpression) 
        for (int i = 0; i < start.size(); i++) 
            grammar.put(start.get(i), generateExpression.get(i));
            if (startTerminator == null) 
                startTerminator = start.get(i);
            
        
        initializeGrammar();
    

    /**
     * 构造终结符 非终结符 firstVt lastVt集合
     * */
    private void initializeGrammar () 
        constructNonTerminator(this);
        constructTerminator(this);
        constructFirstTerminator();
        constructLastTerminator();
        initializePrecedenceRelationList();
        constructPrecedenceRelationList();
    

    /**
     * 打印输出语法
     * */
    public void showGrammar () 
        for (var i : grammar.entrySet()) 
            System.out.print(i.getKey() + " -> ");
            for (var v = 0 ; v < i.getValue().size(); v++) 
                if (v + 1 == i.getValue().size()) 
                    System.out.println(i.getValue().get(v));
                 else 
                    System.out.print(i.getValue().get(v) + " | ");
                

            
        
    

    /**
     * 打印输出非终结符
     * */
    public void showNonTerminator () 
        System.out.print("非终结符: ");
        for (var v : nonTerminators) 
            System.out.print(v + " ");
        
        System.out.println();
    

    /**
     * 打印输出终结符
     * */
    public void showTerminator () 
        System.out.print("终结符: ");
        for (var v : terminators) 
            System.out.print(v + " ");
        
        System.out.println();
    

    /**
     * 打印输出 firstVt集合
     * */
    public void showFirstTerminators () 
        var entryArrayList = sort(firstTerminators);
        for (var firstTerminator : entryArrayList) 
            System.out.print("firstVt(" + firstTerminator.getKey() + ")" + " : ");
            show(firstTerminator);
        
    

    /**
     * 打印输出 lastVt集合
     * */
    public void showLastTerminators () 
        var entryArrayList = sort(lastTerminators);
        for (var lastTerminator : entryArrayList) 
            System.out.print("lastVt(" + lastTerminator.getKey() + ")" + " : ");
            show(lastTerminator);
        
    

    private void show (Map.Entry<String, List<String>> lastTerminator) 
        int length = lastTerminator.getValue().size();
        for (int i = 0; i < length; i++) 
            if (i + 1 >= length) 
                System.out.print(lastTerminator.getValue().get(i));
             else 
                System.out.print(lastTerminator.getValue().get(i) + " , ");
            
        
        System.out.println();
    

    /**
     * 打印优先关系表
     * */
    public void showPrecedenceRelationList () 
        System.out.println("优先关系表:");
        for (String[] strings : precedenceRelationList) 
            for (int column = 0; column < precedenceRelationList.length; column++) 
                if (strings[column] == null) 
                    System.out.print("- ");
                 else 
                    System.out.print(strings[column] + " ");
                
            
            System.out.println();
        
        System.out.println("\\n");
    

    /**
     * 初始化优先关系表
     * */
    private void initializePrecedenceRelationList () 
        // 创建新的终结符集合, 加入 #
        var terminatorsWithSharp = new ArrayList<>(terminators);
        terminatorsWithSharp.add("#");
        int length = terminatorsWithSharp.size() + 1;
        precedenceRelationList = new  String[length][length];
        for (int line = 0; line < length; line++) 
            for (int column = 0; column < length; column++) 
                // (0, 0) 位置空出来
                if (line == 0 && column == 0) 
                    precedenceRelationList[line][column] = "-";
                    continue;
                
                if (line == 0 && line < terminatorsWithSharp.size()) 
                    precedenceRelationList[line][column] = terminatorsWithSharp.get(column - 1);
                 else if (column == 0 && column < terminatorsWithSharp.size()) 
                    precedenceRelationList[line][column] = terminatorsWithSharp.get(line - 1);
                
            
        
    

    /**
     * 构造优先关系表
     * */
    private void constructPrecedenceRelationList () 
        // 初始化优先关系表
        initializePrecedenceRelationList();
        //构造优先关系表
        constructList();
    

    private void constructList () 
        // 带#号的终结符符号集
        var terminatorsWithSharp = new ArrayList<>(terminators);
        terminatorsWithSharp.add("#");
        // 带#的语法
        var grammarWithSharp = new HashMap<>(grammar);
        grammarWithSharp.put("J", List.of("#" + startTerminator + "#"));
        for (var i : grammarWithSharp.entrySet()) 
            // 获取第一个句型的产生式
            var generateExpressions = i.getValue();
            // for循环遍历每一个候选式子
            for (var generateExpression : generateExpressions) 
                // 计算产生式的长度, 如果不为1, 则分析, 否则直接到下一个产生式
                if (!(generateExpression.length() <= 1)) 
                    // 计算等价
                    calculateEquality(generateExpression, terminatorsWithSharp);
                    // 计算小于
                    calculateLess(generateExpression, terminatorsWithSharp);
                    //计算大于
                    calculateGreater(generateExpression, terminatorsWithSharp);
                
            
        
    

    /**
     * 计算优先关系表中的等价关系
     * @param generateExpression 待判断的产生式
     * @param terminatorsWithSharp 带有#的终结符集合
     * */
    private void calculateEquality(String generateExpression, ArrayList<String> terminatorsWithSharp) 
        // 长度为2
        if (generateExpression.length() == 2) 
            for (int j = 0; j < generateExpression.length() - 1; j++) 
                // 判断 P -> ...ab...
                P_ab_(generateExpression, terminatorsWithSharp);
            
        
        // 产生式长度大于2 即3以上
        else 
            for (int j = 0; j < generateExpression.length() - 1; j++) 
                // 判断 P -> ...ab...
                P_ab_(generateExpression, terminatorsWithSharp);
                // 判断 P -> ...aAb...
                P_aQb_(generateExpression, terminatorsWithSharp);
            
        
    

    /**
     * 计算优先关系表中的低等关系
     * @param generateExpression 待判断的产生式
     * @param terminatorsWithSharp 带有#的终结符集合
     * */
    private void calculateLess(String generateExpression, ArrayList<String> terminatorsWithSharp) 
        for (int i = 0; i < generateExpression.length() - 1; i++) 
            // 判断 P -> ...aR...
            // 取第一个
            String a = generateExpression.substring(i, i + 1以上是关于编译原理 实验二 简单计算器的设计与实现的主要内容,如果未能解决你的问题,请参考以下文章

编译原理实验:实验一 简单词法分析程序设计(必修)(Python实现)

2021软件创新实验室暑假集训SpringMVC框架(设计原理简单使用源码探究)

编译原理LR语法分析器的设计与实现

编译原理LR语法分析器的设计与实现

编译原理LR语法分析器的设计与实现

编译原理:实验二 递归下降语法分析