diff --git a/res/SimpleGrammar.txt b/res/SimpleGrammar.txt index 56fdd46..2b8f2df 100644 --- a/res/SimpleGrammar.txt +++ b/res/SimpleGrammar.txt @@ -1,10 +1,26 @@ +program->declear program|calculation ; program|$ -assignment_expression->IDENTIFIER assignment_operator G -assignment_operator->=|MUL_ASSIGN|DIV_ASSIGN|MOD_ASSIGN|ADD_ASSIGN|SUB_ASSIGN|LEFT_ASSIGN|RIGHT_ASSIGN|AND_ASSIGN|XOR_ASSIGN|OR_ASSIGN -G->CONSTANT|IDENTIFIER|binary_operation +declear->type_name PUSH IDENTIFIER PUSH declear1 +declear1->; FILL|= declear2 +declear2->CONSTANT PUSH FILL_I ;|IDENTIFIER PUSH FILL_I ; -binary_operation->IDENTIFIER binary_operator CONSTANT|IDENTIFIER binary_operator IDENTIFIER|CONSTANT binary_operator CONSTANT -binary_operator->+|-|*|/|%|&|^|~|| +assignment->IDENTIFIER = CONSTANT -type_name->INT|FLOAT|DOUBLE|CHAR \ No newline at end of file +calculation->fourth calculation1 +calculation1->fourth_operator PUSH fourth GEQ calculation1|$ +fourth->third fourth1 +fourth1->third_operator PUSH third GEQ fourth1|$ +third->second third1 +third1->second_operator PUSH second GEQ third1|$ +second->first second1 +second1->first_operator PUSH first GEQ second1|$ +first->IDENTIFIER PUSH|CONSTANT PUSH|( calculation ) + +type_name->INT|FLOAT|DOUBLE|CHAR +binary_operator->*|+|-|/|%|&|~|^|| + +first_operator->!|~ +second_operator->*|/|% +third_operator->+|-|<<|>> +fourth_operator->&|^|| \ No newline at end of file diff --git a/res/lexer.c b/res/lexer.c index 66fa34e..8b63d35 100644 --- a/res/lexer.c +++ b/res/lexer.c @@ -1,3 +1,5 @@ -int main(){ - char -} \ No newline at end of file +int a = 13; +double c; +int b = a; + +a<<23-1; \ No newline at end of file diff --git a/src/com/compiler/Main.java b/src/com/compiler/Main.java index bc53119..64a0b79 100644 --- a/src/com/compiler/Main.java +++ b/src/com/compiler/Main.java @@ -4,6 +4,7 @@ import com.compiler.lexer.Lexer; import com.compiler.lexer.LexerTester; import com.compiler.parser.ParserGenerator; import com.compiler.parser.ParserTest; +import com.compiler.parser.Tables; import com.compiler.parser.Test; import com.compiler.utils.FileReader; import com.compiler.utils.Show; @@ -28,6 +29,8 @@ public class Main { boolean result = pt.Check(symbolString); System.out.println(result); + System.out.println(Tables.SymbolTable); + // List lines = FileReader.getLines("res/SimpleGrammar.txt"); ////// lines.add("primary_expression->IDENTIFIER|CONSTANT|STRING_LITERAL|( expression )"); ////// lines.add("B->tc|ee"); diff --git a/src/com/compiler/parser/LLParser.java b/src/com/compiler/parser/LLParser.java index 19be257..2ec39d5 100644 --- a/src/com/compiler/parser/LLParser.java +++ b/src/com/compiler/parser/LLParser.java @@ -1,7 +1,9 @@ package com.compiler.parser; +import com.compiler.lexer.Token; import com.compiler.utils.Pair; +import javax.swing.plaf.synth.SynthButtonUI; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.HashMap; @@ -52,41 +54,117 @@ abstract class LLParser { public boolean Check(ArrayList str) { var form = getForm(); Stack symStack = new Stack<>(); + Stack semStack = new Stack<>(); str.add(endSym); symStack.push(endSym); symStack.push(getStartSymbol()); - + Symbol topSym = new Symbol(); int index = 0; + int tmpVariableIndex = 0; + Symbol lastTopSym = new Symbol(); while (index < str.size()) { - var topSym = symStack.pop(); + topSym = symStack.pop(); switch (topSym.getType()) { + case Action: + switch (topSym.getaType()) { + case FILL: + Symbol name = semStack.pop();// 只能提供名字 + Symbol type = semStack.pop();// 提供类型名 + Token.tokenType tokenType = Token.tokenType.NONE; + switch (type.getId().toLowerCase()) { + case "int": + tokenType = Token.tokenType.INTEGER; + break; + case "double": + tokenType = Token.tokenType.DOUBLE; + break; + case "float": + tokenType = Token.tokenType.FLOAT; + break; + case "char": + tokenType = Token.tokenType.CHAR; + break; + } + Tables.SymbolTable.add(new SymbolTableItem(name.getValue(), tokenType, SymbolTableItem.cat_enum.VARIABLE, "")); + break; + case FILL_I: + Symbol i_initVal = semStack.pop(); + Symbol i_name = semStack.pop();// 只能提供名字 + Symbol i_type = semStack.pop();// 提供类型名 + Token.tokenType i_tokenType = Token.tokenType.NONE; + switch (i_type.getId().toLowerCase()) { + case "int": + i_tokenType = Token.tokenType.INTEGER; + break; + case "double": + i_tokenType = Token.tokenType.DOUBLE; + break; + case "float": + i_tokenType = Token.tokenType.FLOAT; + break; + case "char": + i_tokenType = Token.tokenType.CHAR; + break; + } + if (i_initVal.getId().equals("CONSTANT")) + Tables.SymbolTable.add(new SymbolTableItem(i_name.getValue(), i_tokenType, SymbolTableItem.cat_enum.VARIABLE, i_initVal.getValue())); + else if (i_initVal.getId().equals("IDENTIFIER")) { + //在符号表中找到这个标识符的值 + switch (Tables.getType(i_initVal.getValue())) { + case INTEGER: + Tables.SymbolTable.add(new SymbolTableItem(i_name.getValue(), i_tokenType, SymbolTableItem.cat_enum.VARIABLE, Integer.toString(Tables.getIntValue(i_initVal.getValue())))); + break; + case FLOAT: + Tables.SymbolTable.add(new SymbolTableItem(i_name.getValue(), i_tokenType, SymbolTableItem.cat_enum.VARIABLE, Double.toString(Tables.getDoubleValue(i_initVal.getValue())))); + break; + case CHAR: + Tables.SymbolTable.add(new SymbolTableItem(i_name.getValue(), i_tokenType, SymbolTableItem.cat_enum.VARIABLE, Double.toString(Tables.getCharValue(i_initVal.getValue())))); + break; + case NULL: + break; + } + } + break; + case PUSH: + semStack.push(lastTopSym); + break; + case GEQ: + Symbol opd2 = symStack.pop(); + Symbol opt = symStack.pop(); + Symbol opd1 = symStack.pop(); + Tables.quaternaryList.add(new Quaternary(opt.getId(), opd1.getValue(), opd2.getValue(), "t" + Integer.toString(tmpVariableIndex))); + break; + } + continue; case Terminal: case Empty: if (!topSym.equals(str.get(index))) { - return false; } + lastTopSym = str.get(index); ++index; break; case Nonterminal: final int index_tmp = index; - var res = form.keySet().stream().filter(pair -> pair.first.equals(topSym) && pair.second.equals(str.get(index_tmp))).findFirst(); + final Symbol topSym_tmp = topSym; + var res = form.keySet().stream().filter(pair -> pair.first.equals(topSym_tmp) && pair.second.equals(str.get(index_tmp))).findFirst(); if (res.isEmpty()) { - System.out.print(topSym); - System.out.print("::"); - System.out.println(str.get(index)); - System.out.print("Stack: "); - System.out.println(symStack); +// System.out.print(topSym); +// System.out.print("::"); +// System.out.println(str.get(index)); +// System.out.print("Stack: "); +// System.out.println(symStack); return false; } var symStr = form.get(res.get()); - System.out.print("Stack: "+symStack+" "); - System.out.print(topSym + "->"); - System.out.println(symStr); +// System.out.print("Stack: " + symStack + " "); +// System.out.print(topSym + "->"); +// System.out.println(symStr); for (int i = symStr.size() - 1; i >= 0; --i) { - if (symStr.get(i).getType() != Symbol.SymbolType.Empty) + if (symStr.get(i).getType() != Symbol.SymbolType.Empty) { symStack.push(symStr.get(i)); + } } break; case End: diff --git a/src/com/compiler/parser/ParserGenerator.java b/src/com/compiler/parser/ParserGenerator.java index 1b5238b..32f135a 100644 --- a/src/com/compiler/parser/ParserGenerator.java +++ b/src/com/compiler/parser/ParserGenerator.java @@ -2,6 +2,7 @@ package com.compiler.parser; import com.compiler.lexer.Token; +import javax.lang.model.util.ElementScanner6; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -34,6 +35,14 @@ public class ParserGenerator { for (String sym : syms) { if (sym.equals("$")) symbolString.add(new Symbol(sym, Symbol.SymbolType.Empty)); + else if (sym.equals("PUSH")) + symbolString.add(new Symbol(sym, Symbol.ActionTYpe.PUSH)); + else if (sym.equals("FILL")) + symbolString.add(new Symbol(sym, Symbol.ActionTYpe.FILL)); + else if (sym.equals("FILL_I")) + symbolString.add(new Symbol(sym, Symbol.ActionTYpe.FILL_I)); + else if (sym.equals("GEQ")) + symbolString.add(new Symbol(sym, Symbol.ActionTYpe.GEQ)); else if (ParserTest.isTerminal(sym)) symbolString.add(new Symbol(sym, Symbol.SymbolType.Terminal)); else @@ -118,76 +127,11 @@ public class ParserGenerator { case "!=": symbolList.add(new Symbol("NE_OP", Symbol.SymbolType.Terminal)); break; - case ";": - symbolList.add(new Symbol(";", Symbol.SymbolType.Terminal)); - break; - case "{": - symbolList.add(new Symbol("{", Symbol.SymbolType.Terminal)); - break; - case "}": - symbolList.add(new Symbol("}", Symbol.SymbolType.Terminal)); - break; - case "(": - symbolList.add(new Symbol("(", Symbol.SymbolType.Terminal)); - break; - case ")": - symbolList.add(new Symbol(")", Symbol.SymbolType.Terminal)); - break; - case "[": - symbolList.add(new Symbol("[", Symbol.SymbolType.Terminal)); - break; - case "]": - symbolList.add(new Symbol("]", Symbol.SymbolType.Terminal)); - break; - case ",": - symbolList.add(new Symbol(",", Symbol.SymbolType.Terminal)); - break; - case ".": - symbolList.add(new Symbol(".", Symbol.SymbolType.Terminal)); - break; - case "&": - symbolList.add(new Symbol("&", Symbol.SymbolType.Terminal)); - break; - case "!": - symbolList.add(new Symbol("!", Symbol.SymbolType.Terminal)); - break; - case "~": - symbolList.add(new Symbol("~", Symbol.SymbolType.Terminal)); - break; case "->": symbolList.add(new Symbol("PTR_OP", Symbol.SymbolType.Terminal)); break; - case "+": - symbolList.add(new Symbol("+", Symbol.SymbolType.Terminal)); - break; - case "-": - symbolList.add(new Symbol("-", Symbol.SymbolType.Terminal)); - break; - case "*": - symbolList.add(new Symbol("*", Symbol.SymbolType.Terminal)); - break; - case "/": - symbolList.add(new Symbol("/", Symbol.SymbolType.Terminal)); - break; - case "%": - symbolList.add(new Symbol("%", Symbol.SymbolType.Terminal)); - break; - case "<": - symbolList.add(new Symbol("<", Symbol.SymbolType.Terminal)); - break; - case ">": - symbolList.add(new Symbol(">", Symbol.SymbolType.Terminal)); - break; - case "^": - symbolList.add(new Symbol("^", Symbol.SymbolType.Terminal)); - break; - case "|": - symbolList.add(new Symbol("|", Symbol.SymbolType.Terminal)); - break; - case "?": - symbolList.add(new Symbol("?", Symbol.SymbolType.Terminal)); - break; default: + symbolList.add(new Symbol(token.getStr(), Symbol.SymbolType.Terminal)); break; } diff --git a/src/com/compiler/parser/ParserTest.java b/src/com/compiler/parser/ParserTest.java index 0d5b33b..a7e7aa0 100644 --- a/src/com/compiler/parser/ParserTest.java +++ b/src/com/compiler/parser/ParserTest.java @@ -15,7 +15,7 @@ public class ParserTest extends LLParser { } private HashMap> rules = new HashMap<>(); - private Symbol startSym = new Symbol("S", Symbol.SymbolType.Nonterminal); + private Symbol startSym = new Symbol("program", Symbol.SymbolType.Nonterminal); private void init() { initTerminalSymbols(); diff --git a/src/com/compiler/parser/Quaternary.java b/src/com/compiler/parser/Quaternary.java index eba72d1..b9c4e45 100644 --- a/src/com/compiler/parser/Quaternary.java +++ b/src/com/compiler/parser/Quaternary.java @@ -9,12 +9,17 @@ public class Quaternary { } - public enum operation {ADD, SUB, MUL, DIV, EQUAL} + public Quaternary(String opt, String opd1, String opd2, String opd3) { + this.opd1 = opd1; + this.opd2 = opd2; + this.opd3 = opd3; + this.opt = opt; + } - operation opt; + String opt; String opd1, opd2, opd3; - public operation getOpt() { + public String getOpt() { return opt; } diff --git a/src/com/compiler/parser/Symbol.java b/src/com/compiler/parser/Symbol.java index bb71e5a..158b026 100644 --- a/src/com/compiler/parser/Symbol.java +++ b/src/com/compiler/parser/Symbol.java @@ -6,7 +6,7 @@ public class Symbol { Symbol() { sType = SymbolType.Terminal; - id = ""; +// id = ""; } @@ -23,10 +23,23 @@ public class Symbol { this.valueType = type; } + Symbol(final String name, ActionTYpe at) { + id = name; + aType = at; + sType = SymbolType.Action; + this.value = ""; + } + enum SymbolType { Terminal, Nonterminal, Empty, End, Action } + enum ActionTYpe { + PUSH, FILL + , FILL_I //有初值的填表 + , GEQ //生成运算四元式 + } + public String getId() { return id; } @@ -35,6 +48,10 @@ public class Symbol { return sType; } + public ActionTYpe getaType() { + return aType; + } + public String getValue() { return value; } @@ -45,6 +62,7 @@ public class Symbol { private String id; private SymbolType sType; + private ActionTYpe aType; private String value; private Token.tokenType valueType = Token.tokenType.NONE; diff --git a/src/com/compiler/parser/Tables.java b/src/com/compiler/parser/Tables.java index b4b259f..86945a3 100644 --- a/src/com/compiler/parser/Tables.java +++ b/src/com/compiler/parser/Tables.java @@ -1,5 +1,7 @@ package com.compiler.parser; +import com.compiler.lexer.Token; + import java.util.ArrayList; import java.util.Arrays; @@ -19,6 +21,63 @@ public class Tables { public static ArrayList doubleList = new ArrayList<>(); public static ArrayList charList = new ArrayList<>(); + //四元式表 + public static ArrayList quaternaryList = new ArrayList<>(); + + + public static int getIntValue(String name) { + var first = SymbolTable.stream().filter(item -> item.getName().equals(name)).findFirst(); + if (first.isPresent()) { + var item = first.get(); + if (typeTabel.get(item.getTyp()).getType() == TypeLabelItem.type.INTEGER) + return integerList.get(item.getAddr()); + } + return Integer.MAX_VALUE; + } + + public static double getDoubleValue(String name) { + var first = SymbolTable.stream().filter(item -> item.getName().equals(name)).findFirst(); + if (first.isPresent()) { + var item = first.get(); + if (typeTabel.get(item.getTyp()).getType() == TypeLabelItem.type.FLOAT) + return doubleList.get(item.getAddr()); + } + return Double.MAX_VALUE; + } + + public static char getCharValue(String name) { + var first = SymbolTable.stream().filter(item -> item.getName().equals(name)).findFirst(); + if (first.isPresent()) { + var item = first.get(); + if (typeTabel.get(item.getTyp()).getType() == TypeLabelItem.type.CHAR) { + return charList.get(item.getAddr()); + } + } + return ' '; + } + + public static TypeLabelItem.type getType(String name) { + var first = SymbolTable.stream().filter(item -> item.getName().equals(name)).findFirst(); + if (first.isPresent()) { + var item = first.get(); + return typeTabel.get(item.getTyp()).getType(); + } + return TypeLabelItem.type.NULL; + } + + public static int getSymbolCount(String name, TypeLabelItem.type type) { + int index = 0; + for (SymbolTableItem item : SymbolTable) { + if (typeTabel.get(item.getTyp()).getType() == type) { + if (item.getName().equals(name)) { + return index; + } + ++index; + } + } + return index; + } + } // 类型表中的表项 @@ -38,7 +97,7 @@ class TypeLabelItem { } } - public enum type {INTEGER, FLOAT, CHAR, ARRAY, STRUCT} + public enum type {INTEGER, FLOAT, CHAR, ARRAY, STRUCT, NULL} private type t; private int tpoint; @@ -54,24 +113,33 @@ class TypeLabelItem { // 符号总表中的表项 class SymbolTableItem { - public SymbolTableItem(Symbol sym, cat_enum cat) { - this.name = sym.getId(); + public SymbolTableItem(String name, Token.tokenType tokenType, cat_enum cat, String initVal) { + this.name = name; this.cat = cat; - switch (sym.getValueType()) { + switch (tokenType) { case CHAR: typ = 2; - Tables.charList.add(sym.getValue().charAt(1)); + if (initVal.isEmpty()) + Tables.charList.add(' '); + else + Tables.charList.add(initVal.charAt(1)); addr = Tables.charList.size() - 1; break; case FLOAT: case DOUBLE: typ = 1; - Tables.doubleList.add(Double.parseDouble(sym.getValue())); + if (initVal.isEmpty()) + Tables.doubleList.add(0.0); + else + Tables.doubleList.add(Double.parseDouble(initVal)); addr = Tables.doubleList.size() - 1; break; case INTEGER: typ = 0; - Tables.integerList.add(Integer.parseInt(sym.getValue())); + if (initVal.isEmpty()) + Tables.integerList.add(0); + else + Tables.integerList.add(Integer.parseInt(initVal)); addr = Tables.integerList.size() - 1; break; } @@ -99,6 +167,28 @@ class SymbolTableItem { public String getName() { return name; } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("name: "); + sb.append(name); + sb.append(" type: "); + sb.append(typ); + sb.append(" value: "); + switch (Tables.typeTabel.get(typ).getType()) { + case INTEGER: + sb.append(Tables.integerList.get(addr)); + break; + case FLOAT: + sb.append(Tables.doubleList.get(addr)); + break; + case CHAR: + sb.append(Tables.charList.get(addr)); + break; + } + return sb.toString(); + } } //数组表