编译原理 实验二 简单计算器的设计与实现
Posted _DiMinisH
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译原理 实验二 简单计算器的设计与实现相关的知识,希望对你有一定的参考价值。
实验二 简单计算器的设计与实现
一、实验目的
综合运行词法分析器、语法分析器等原理实现一个具有加、乘功能的简单计算器,该计算器满足乘法优先级高于加法优先级,且仅处理非负整数。
二、实验内容
1. 对输入的符号串首先进行词法分析,提取操作数及操作符,以输出的单词符号为输入进行语法分析。
2. 要求以算符优先分析的方法完成语法分析工作,识别输入串是否是文法描述语言的句子。
3. 对句子进行求值,求值方式可以是遍历语法树或者是建立一个逆波兰式,对逆波兰式进行求值。
三、实验要求
1. 从文件读入算术表达式/或者从终端输入;
2. 词法分析,用二元组表示输出结果;
3. 语法分析,算符优先分析方法进行自下而上的语法分析并构造语法树;
4. 识别出的句子进行求值,遍历语法树求值或者先建立逆波兰式再求值;
四、输出
P -> (E) | i
T -> T*F | F
E -> E+T | T
F -> P↑F | 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实现)