use of priv.bajdcc.LALR1.syntax.rule.Rule in project jMiniLang by bajdcc.
the class NPA method generateNPA.
/**
* 产生下推自动机
*/
private void generateNPA() {
/* 下推自动机状态 */
ArrayList<NPAStatus> NPAStatusList = new ArrayList<>();
/* 文法自动机状态 */
ArrayList<NGAStatus> NGAStatusList = new ArrayList<>();
/* 下推自动机边(规则映射到NGA边) */
HashMap<Rule, ArrayList<NGAEdge>> ruleEdgeMap = new HashMap<>();
/* 遍历每条规则 */
for (Entry<RuleItem, NGAStatus> entry : mapNGA.entrySet()) {
RuleItem key = entry.getKey();
NGAStatus value = entry.getValue();
/* 保存规则 */
arrRuleItems.add(key);
/* 搜索当前规则中的所有状态 */
ArrayList<NGAStatus> CurrentNGAStatusList = getNGAStatusClosure(new BreadthFirstSearch<>(), value);
/* 搜索所有的边 */
for (NGAStatus status : CurrentNGAStatusList) {
/* 若边为非终结符边,则加入邻接表,终结符->带终结符的所有边 */
status.outEdges.stream().filter(edge -> edge.data.kAction == NGAEdgeType.RULE).forEach(edge -> {
Rule rule = edge.data.rule.rule;
if (!ruleEdgeMap.containsKey(rule)) {
ruleEdgeMap.put(rule, new ArrayList<>());
}
ruleEdgeMap.get(rule).add(edge);
});
}
/* 为所有的NGA状态构造对应的NPA状态,为一一对应 */
for (NGAStatus status : CurrentNGAStatusList) {
/* 保存NGA状态 */
NGAStatusList.add(status);
/* 新建NPA状态 */
NPAStatus NPAStatus = new NPAStatus();
NPAStatus.data.label = status.data.label;
NPAStatus.data.iRuleItem = arrRuleItems.indexOf(key);
NPAStatusList.add(NPAStatus);
}
}
/* 遍历所有NPA状态 */
for (int i = 0; i < NPAStatusList.size(); i++) {
/* 获得NGA状态 */
NGAStatus ngaStatus = NGAStatusList.get(i);
/* 获得NPA状态 */
NPAStatus npaStatus = NPAStatusList.get(i);
/* 获得规则 */
RuleItem ruleItem = arrRuleItems.get(npaStatus.data.iRuleItem);
/* 检查是否为纯左递归,类似[A::=Aa]此类,无法直接添加纯左递归边,需要LA及归约 */
if (!isLeftRecursiveStatus(ngaStatus, ruleItem.parent)) {
/* 当前状态是否为初始状态且推导规则是否属于起始规则(无NGA入边) */
boolean isInitRuleStatus = initRule == ruleItem.parent;
/* 若是,则将当前状态对应的NPA状态加入初始状态表中 */
if (ngaStatus.inEdges.isEmpty() && isInitRuleStatus) {
arrInitStatusList.add(npaStatus);
}
/* 建立计算优先级使用的记号表,其中元素为从当前状态出发的Rule或Token边的First集(LA预查优先) */
HashSet<Integer> tokenSet = new HashSet<>();
/* 遍历文法自动机的所有边 */
for (NGAEdge edge : ngaStatus.outEdges) {
switch(edge.data.kAction) {
case EPSILON:
break;
case RULE:
/* 判断边是否为纯左递归 */
if (!isLeftRecursiveEdge(edge, ruleItem.parent)) {
for (RuleItem item : edge.data.rule.rule.arrRules) {
/* 起始状态 */
NGAStatus initItemStatus = mapNGA.get(item);
/* 判断状态是否为纯左递归 */
if (!isLeftRecursiveStatus(initItemStatus, item.parent)) {
/* 添加Shift边,功能为将一条状态序号放入堆栈顶 */
NPAEdge npaEdge = connect(npaStatus, NPAStatusList.get(NGAStatusList.indexOf(initItemStatus)));
npaEdge.data.handler = edge.data.handler;
npaEdge.data.action = edge.data.action;
npaEdge.data.kAction = NPAEdgeType.SHIFT;
npaEdge.data.inst = NPAInstruction.SHIFT;
npaEdge.data.errorJump = NPAStatusList.get(NGAStatusList.indexOf(edge.end));
/* 为移进项目构造LookAhead表,LA不吃字符,只是单纯压入新的状态(用于规约) */
npaEdge.data.arrLookAhead = new HashSet<>();
npaEdge.data.arrLookAhead.addAll(item.setFirstSetTokens.stream().filter(exp -> !tokenSet.contains(exp.id)).map(exp -> exp.id).collect(Collectors.toList()));
}
}
// 将当前非终结符的所有终结符First集加入tokenSet,以便非终结符的Move的LA操作(优先级)
tokenSet.addAll(edge.data.rule.rule.arrTokens.stream().map(exp -> exp.id).collect(Collectors.toList()));
}
break;
case TOKEN:
/* 添加Move边,功能为吃掉(匹配)一个终结符,若终结符不匹配,则报错(即不符合文法) */
NPAEdge npaEdge = connect(npaStatus, NPAStatusList.get(NGAStatusList.indexOf(edge.end)));
npaEdge.data.handler = edge.data.handler;
npaEdge.data.action = edge.data.action;
npaEdge.data.kAction = NPAEdgeType.MOVE;
npaEdge.data.iToken = edge.data.token.id;
npaEdge.data.iHandler = arrActions.indexOf(edge.data.action);
npaEdge.data.errorJump = npaEdge.end;
/* 根据StorageID配置指令 */
if (edge.data.iStorage != -1) {
npaEdge.data.inst = NPAInstruction.READ;
// 参数
npaEdge.data.iIndex = edge.data.iStorage;
} else {
npaEdge.data.inst = NPAInstruction.PASS;
}
/* 修改TokenSet */
if (tokenSet.contains(edge.data.token.id)) {
/* 使用LookAhead表 */
npaEdge.data.arrLookAhead = new HashSet<>();
} else {
tokenSet.add(edge.data.token.id);
}
break;
default:
break;
}
}
/* 如果当前NGA状态是结束状态(此时要进行规约),则检查是否需要添加其他边 */
if (ngaStatus.data.bFinal) {
if (ruleEdgeMap.containsKey(ruleItem.parent)) {
/* 遍历文法自动机中附带了当前推导规则所属规则的边 */
ArrayList<NGAEdge> ruleEdges = ruleEdgeMap.get(// 当前规约的文法的非终结符为A,获得包含A的所有边
ruleItem.parent);
for (NGAEdge ngaEdge : ruleEdges) {
/* 判断纯左递归,冗长的表达式是为了获得当前边的所在推导式的起始非终结符 */
if (isLeftRecursiveEdge(ngaEdge, arrRuleItems.get(NPAStatusList.get(NGAStatusList.indexOf(ngaEdge.begin)).data.iRuleItem).parent)) {
/* 添加Left Recursion边(特殊的Reduce边) */
NPAEdge npaEdge = connect(npaStatus, NPAStatusList.get(NGAStatusList.indexOf(ngaEdge.end)));
npaEdge.data.kAction = NPAEdgeType.LEFT_RECURSION;
if (ngaEdge.data.iStorage != -1) {
npaEdge.data.inst = NPAInstruction.LEFT_RECURSION;
npaEdge.data.iIndex = ngaEdge.data.iStorage;
} else {
npaEdge.data.inst = NPAInstruction.LEFT_RECURSION_DISCARD;
}
// 规约的规则
npaEdge.data.iHandler = npaStatus.data.iRuleItem;
/* 为左递归构造Lookahead表(Follow集),若LA成功则进入左递归 */
npaEdge.data.arrLookAhead = new HashSet<>();
for (NGAEdge edge : ngaEdge.end.outEdges) {
/* 若出边为终结符,则直接加入(终结符First集仍是本身) */
if (edge.data.kAction == NGAEdgeType.TOKEN) {
npaEdge.data.arrLookAhead.add(edge.data.token.id);
} else {
/* 若出边为非终结符,则加入非终结符的First集 */
npaEdge.data.arrLookAhead.addAll(edge.data.rule.rule.arrTokens.stream().map(exp -> exp.id).collect(Collectors.toList()));
}
}
} else {
/* 添加Reduce边 */
NPAEdge npaEdge = connect(npaStatus, NPAStatusList.get(NGAStatusList.indexOf(ngaEdge.end)));
npaEdge.data.kAction = NPAEdgeType.REDUCE;
npaEdge.data.status = NPAStatusList.get(NGAStatusList.indexOf(ngaEdge.begin));
if (ngaEdge.data.iStorage != -1) {
npaEdge.data.inst = NPAInstruction.TRANSLATE;
npaEdge.data.iIndex = ngaEdge.data.iStorage;
} else {
npaEdge.data.inst = NPAInstruction.TRANSLATE_DISCARD;
}
// 规约的规则
npaEdge.data.iHandler = npaStatus.data.iRuleItem;
}
}
}
if (isInitRuleStatus) {
/* 添加Finish边 */
NPAEdge npaEdge = connect(npaStatus, npaStatus);
npaEdge.data.kAction = NPAEdgeType.FINISH;
npaEdge.data.inst = NPAInstruction.TRANSLATE_FINISH;
npaEdge.data.iHandler = npaStatus.data.iRuleItem;
}
}
}
}
}
use of priv.bajdcc.LALR1.syntax.rule.Rule in project jMiniLang by bajdcc.
the class Syntax method getParagraphString.
/**
* 获得段落式描述
* @return 段落式描述
*/
public String getParagraphString() {
StringBuilder sb = new StringBuilder();
/* 起始符号 */
sb.append("#### 起始符号 ####");
sb.append(System.lineSeparator());
sb.append(strBeginRuleName);
sb.append(System.lineSeparator());
/* 终结符 */
sb.append("#### 终结符 ####");
sb.append(System.lineSeparator());
for (TokenExp exp : arrTerminals) {
sb.append(exp.toString());
sb.append(System.lineSeparator());
}
/* 非终结符 */
sb.append("#### 非终结符 ####");
sb.append(System.lineSeparator());
for (RuleExp exp : arrNonTerminals) {
sb.append(exp.toString());
sb.append(System.lineSeparator());
}
/* 推导规则 */
sb.append("#### 文法产生式 ####");
sb.append(System.lineSeparator());
for (RuleExp exp : arrNonTerminals) {
for (RuleItem item : exp.rule.arrRules) {
/* 规则正文 */
sb.append(getSingleString(exp.name, item.expression));
sb.append(System.lineSeparator());
/* First集合 */
sb.append("\t--== 终结符First集合 ==--");
sb.append(System.lineSeparator());
for (TokenExp token : item.setFirstSetTokens) {
sb.append("\t\t").append(token.name);
sb.append(System.lineSeparator());
}
sb.append("\t--== 非终结符First集合 ==--");
sb.append(System.lineSeparator());
for (RuleExp rule : item.setFirstSetRules) {
sb.append("\t\t").append(rule.name);
sb.append(System.lineSeparator());
}
}
}
return sb.toString();
}
use of priv.bajdcc.LALR1.syntax.rule.Rule in project jMiniLang by bajdcc.
the class Syntax method semanticAnalysis.
/**
* 进行语义分析
*
* @throws SyntaxException 词法错误
*/
private void semanticAnalysis() throws SyntaxException {
/* 非终结符数量 */
int size = arrNonTerminals.size();
/* 计算规则的First集合 */
for (RuleExp exp : arrNonTerminals) {
for (RuleItem item : exp.rule.arrRules) {
FirstsetSolver solver = new FirstsetSolver();
// 计算规则的First集合
item.expression.visit(solver);
if (!solver.solve(item)) {
// 若串长度可能为零,即产生空串
err(SyntaxError.EPSILON, getSingleString(exp.name, item.expression));
}
}
}
/* 建立连通矩阵 */
// First集依赖矩阵
BitVector2 firstsetDependency = new BitVector2(size, size);
firstsetDependency.clear();
/* 计算非终结符First集合包含关系的布尔连通矩阵 */
{
int i = 0;
for (RuleExp exp : arrNonTerminals) {
for (RuleItem item : exp.rule.arrRules) {
for (RuleExp rule : item.setFirstSetRules) {
firstsetDependency.set(i, rule.id);
}
}
i++;
}
}
/* 计算间接左递归 */
{
/* 标记并清除直接左递归 */
for (int i = 0; i < size; i++) {
if (firstsetDependency.test(i, i)) {
// 直接左递归
arrNonTerminals.get(i).rule.iRecursiveLevel = 1;
firstsetDependency.clear(i, i);
}
}
/* 获得拷贝 */
BitVector2 a = (BitVector2) firstsetDependency.clone();
BitVector2 b = (BitVector2) firstsetDependency.clone();
BitVector2 r = new BitVector2(size, size);
/* 检查是否出现环 */
for (int level = 2; level < size; level++) {
/* 进行布尔连通矩阵乘法,即r=aXb */
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
r.clear(i, j);
for (int k = 0; k < size; k++) {
boolean value = r.test(i, j) || (a.test(i, k) && b.test(k, j));
r.set(i, j, value);
}
}
}
/* 检查当前结果是否出现环 */
{
int i = 0;
for (RuleExp exp : arrNonTerminals) {
if (r.test(i, i)) {
if (exp.rule.iRecursiveLevel < 2) {
exp.rule.iRecursiveLevel = level;
}
}
i++;
}
}
/* 保存结果 */
a = (BitVector2) r.clone();
}
/* 检查是否存在环并报告错误 */
for (RuleExp exp : arrNonTerminals) {
if (exp.rule.iRecursiveLevel > 1) {
err(SyntaxError.INDIRECT_RECURSION, exp.name + " level:" + exp.rule.iRecursiveLevel);
}
}
}
/* 计算完整的First集合 */
{
/* 建立处理标记表 */
BitSet processed = new BitSet(size);
processed.clear();
for (RuleExp arrNonTerminal : arrNonTerminals) {
/* 找出一条无最左依赖的规则 */
// 最左依赖的规则索引
int nodependencyRule = -1;
for (int j = 0; j < size; j++) {
if (!processed.get(j)) {
boolean empty = true;
for (int k = 0; k < size; k++) {
if (firstsetDependency.test(j, k)) {
empty = false;
break;
}
}
if (empty) {
// 找到
nodependencyRule = j;
break;
}
}
}
if (nodependencyRule == -1) {
err(SyntaxError.MISS_NODEPENDENCY_RULE, arrNonTerminal.name);
}
/* 计算该规则的终结符First集合 */
{
Rule rule = arrNonTerminals.get(nodependencyRule).rule;
/* 计算规则的终结符First集合 */
for (RuleItem item : rule.arrRules) {
for (RuleExp exp : item.setFirstSetRules) {
item.setFirstSetTokens.addAll(exp.rule.arrTokens);
}
}
/* 计算非终结符的终结符First集合 */
for (RuleItem item : rule.arrRules) {
rule.arrTokens.addAll(item.setFirstSetTokens);
}
/* 修正左递归规则的终结符First集合 */
for (RuleItem item : rule.arrRules) {
if (item.setFirstSetRules.contains(arrNonTerminals.get(nodependencyRule))) {
item.setFirstSetTokens.addAll(rule.arrTokens);
}
}
}
/* 清除该规则 */
processed.set(nodependencyRule);
for (int j = 0; j < size; j++) {
firstsetDependency.clear(j, nodependencyRule);
}
}
}
/* 搜索不能产生字符串的规则 */
for (RuleExp exp : arrNonTerminals) {
for (RuleItem item : exp.rule.arrRules) {
if (item.setFirstSetTokens.isEmpty()) {
err(SyntaxError.FAILED, getSingleString(exp.name, item.expression));
}
}
}
}
use of priv.bajdcc.LALR1.syntax.rule.Rule in project jMiniLang by bajdcc.
the class Syntax method buildFirstAndFollow.
/**
* 构造First集和Follow集
*
* @throws SyntaxException 词法错误
*/
private void buildFirstAndFollow() throws SyntaxException {
/* 非终结符数量 */
int size = arrNonTerminals.size();
/* 计算规则的First集合 */
boolean update;
do {
update = false;
for (RuleExp exp : arrNonTerminals) {
for (RuleItem item : exp.rule.arrRules) {
FirstSetSolver solver = new FirstSetSolver();
// 计算规则的First集合
item.expression.visit(solver);
item.epsilon = solver.solve(item);
if (item.epsilon && !exp.rule.epsilon) {
exp.rule.epsilon = true;
update = true;
}
}
}
} while (update);
/* 建立连通矩阵 */
// First集依赖矩阵
BitVector2 firstsetDependency = new BitVector2(size, size);
firstsetDependency.clear();
/* 计算非终结符First集合包含关系的布尔连通矩阵 */
{
int i = 0;
for (RuleExp exp : arrNonTerminals) {
for (RuleItem item : exp.rule.arrRules) {
for (RuleExp rule : item.setFirstSetRules) {
firstsetDependency.set(i, rule.id);
}
}
i++;
}
}
/* 检查间接左递归 */
{
/* 标记直接左递归 */
for (int i = 0; i < size; i++) {
if (firstsetDependency.test(i, i)) {
// 出现直接左递归
err(SyntaxError.DIRECT_RECURSION, arrNonTerminals.get(i).name);
}
}
/* 获得拷贝 */
BitVector2 a = (BitVector2) firstsetDependency.clone();
BitVector2 b = (BitVector2) firstsetDependency.clone();
BitVector2 r = new BitVector2(size, size);
/* 检查是否出现环 */
for (int level = 2; level < size; level++) {
/* 进行布尔连通矩阵乘法,即r=aXb */
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
r.clear(i, j);
for (int k = 0; k < size; k++) {
boolean value = r.test(i, j) || (a.test(i, k) && b.test(k, j));
r.set(i, j, value);
}
}
}
/* 检查当前结果是否出现环 */
{
int i = 0;
for (RuleExp exp : arrNonTerminals) {
if (r.test(i, i)) {
if (exp.rule.iRecursiveLevel < 2) {
exp.rule.iRecursiveLevel = level;
}
}
i++;
}
}
/* 保存结果 */
a = (BitVector2) r.clone();
}
/* 检查是否存在环并报告错误 */
for (RuleExp exp : arrNonTerminals) {
if (exp.rule.iRecursiveLevel > 1) {
err(SyntaxError.INDIRECT_RECURSION, exp.name + " level:" + exp.rule.iRecursiveLevel);
}
}
}
/* 建立规则的依赖关系 */
ArrayList<Integer> nodependencyList = new ArrayList<>();
{
/* 建立处理标记表 */
BitSet processed = new BitSet(size);
processed.clear();
/* 寻找First集的依赖关系 */
for (RuleExp arrNonTerminal : arrNonTerminals) {
/* 找出一条无最左依赖的规则 */
// 最左依赖的规则索引
int nodependencyRule = -1;
for (int j = 0; j < size; j++) {
if (!processed.get(j)) {
boolean empty = true;
for (int k = 0; k < size; k++) {
if (firstsetDependency.test(j, k)) {
empty = false;
break;
}
}
if (empty) {
// 找到
nodependencyRule = j;
break;
}
}
}
if (nodependencyRule == -1) {
err(SyntaxError.MISS_NODEPENDENCY_RULE, arrNonTerminal.name);
}
/* 清除该规则 */
processed.set(nodependencyRule);
for (int j = 0; j < size; j++) {
firstsetDependency.clear(j, nodependencyRule);
}
nodependencyList.add(nodependencyRule);
}
}
for (int nodependencyRule : nodependencyList) {
/* 计算该规则的终结符First集合 */
Rule rule = arrNonTerminals.get(nodependencyRule).rule;
/* 计算规则的终结符First集合 */
for (RuleItem item : rule.arrRules) {
for (RuleExp exp : item.setFirstSetRules) {
item.setFirstSetTokens.addAll(exp.rule.arrFirsts);
}
}
/* 计算非终结符的终结符First集合 */
for (RuleItem item : rule.arrRules) {
rule.arrFirsts.addAll(item.setFirstSetTokens);
}
}
/* 搜索不能产生字符串的规则 */
for (RuleExp exp : arrNonTerminals) {
for (RuleItem item : exp.rule.arrRules) {
if (item.setFirstSetTokens.isEmpty()) {
err(SyntaxError.FAILED, getSingleString(exp.name, item.expression));
}
}
}
/* 求Follow集 */
mapNonTerminals.get(beginRuleName).rule.setFollows.add(mapTerminals.get(epsilonName));
do {
update = false;
for (RuleExp origin : arrNonTerminals) {
for (RuleItem item : origin.rule.arrRules) {
for (RuleExp target : arrNonTerminals) {
FollowSetSolver solver = new FollowSetSolver(origin, target);
if (origin.name.equals("E1") && target.name.equals("T")) {
update = !!update;
}
item.expression.visit(solver);
update |= solver.isUpdated();
}
}
}
} while (update);
/* 将哈希表按ID排序并保存 */
for (RuleExp exp : arrNonTerminals) {
for (RuleItem item : exp.rule.arrRules) {
item.arrFirstSetTokens = sortTerminal(item.setFirstSetTokens);
item.parent.arrFollows = sortTerminal(item.parent.setFollows);
}
}
}
use of priv.bajdcc.LALR1.syntax.rule.Rule in project jMiniLang by bajdcc.
the class NGAToString method visitBegin.
@Override
public void visitBegin(NGAStatus status, VisitBag bag) {
/* 若首次访问节点则先构造状态表 */
if (arrNGAStatus.isEmpty()) {
BreadthFirstSearch<NGAEdge, NGAStatus> bfs = new BreadthFirstSearch<>();
status.visit(bfs);
arrNGAStatus = bfs.arrStatus;
}
/* 输出状态标签 */
appendLine();
appendPrefix();
context.append("--== 状态[").append(arrNGAStatus.indexOf(status)).append("]").append(status.data.bFinal ? "[结束]" : "").append(" ==--");
appendLine();
appendPrefix();
context.append("项目: ").append(status.data.label);
appendLine();
/* 输出边 */
for (NGAEdge edge : status.outEdges) {
appendPrefix();
context.append("\t到达 ").append(arrNGAStatus.indexOf(edge.end)).append(" : ");
context.append(edge.data.kAction.getName());
switch(edge.data.kAction) {
case EPSILON:
break;
case RULE:
context.append(" = ").append(edge.data.rule);
break;
case TOKEN:
context.append(" = ").append(edge.data.token);
break;
default:
break;
}
appendLine();
}
}
Aggregations