Skip to content

Commit

Permalink
Type declarations are now used in code generation.
Browse files Browse the repository at this point in the history
  • Loading branch information
ZeroBone committed Mar 28, 2020
1 parent 44259c3 commit 6dd6c83
Show file tree
Hide file tree
Showing 11 changed files with 134 additions and 71 deletions.
37 changes: 18 additions & 19 deletions run/ParseNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,52 +27,51 @@ void reduce() {
break;
case 1:
{
Object s = ((ParseNode)children.get(1)).payload;
Object t = ((ParseNode)children.get(0)).payload;
StatementNode s = (StatementNode)((ParseNode)children.get(1)).payload;
TranslationUnitNode t = (TranslationUnitNode)((ParseNode)children.get(0)).payload;
t.addStatement(s); v = t;
}
break;
case 2:
{
Object nonTerminal = ((ParseNode)children.get(2)).payload;
Object body = ((ParseNode)children.get(0)).payload;
IdToken nonTerminal = (IdToken)((ParseNode)children.get(2)).payload;
ProductionStatementBody body = (ProductionStatementBody)((ParseNode)children.get(0)).payload;
v = new ProductionStatementNode(nonTerminal, body.getProduction(), body.getCode());
}
break;
case 3:
{
Object nonTerminal = ((ParseNode)children.get(1)).payload;
Object type = ((ParseNode)children.get(0)).payload;
v = new TypeStatementNode(nonTerminal, type);
IdToken symbol = (IdToken)((ParseNode)children.get(1)).payload;
IdToken type = (IdToken)((ParseNode)children.get(0)).payload;
v = new TypeStatementNode(symbol, type);
}
break;
case 4:
{
Object code = ((ParseNode)children.get(0)).payload;
IdToken code = (IdToken)((ParseNode)children.get(0)).payload;
v = new ProductionStatementBody(code);
}
break;
case 5:
{
Object s = ((ParseNode)children.get(2)).payload;
Object arg = ((ParseNode)children.get(1)).payload;
Object b = ((ParseNode)children.get(0)).payload;
IdToken s = (IdToken)((ParseNode)children.get(2)).payload;
IdToken arg = (IdToken)((ParseNode)children.get(1)).payload;
ProductionStatementBody b = (ProductionStatementBody)((ParseNode)children.get(0)).payload;

char firstChar = s.charAt(0);
if (Character.isUpperCase(firstChar)) {
if (StringUtils.isTerminal(s.id)) {
if (arg == null) {
b.addTerminal(s);
b.addTerminal(s.id);
}
else {
b.addTerminal(s, arg);
b.addTerminal(s.id, arg.id);
}
}
else {
if (arg == null) {
b.addNonTerminal(s);
b.addNonTerminal(s.id);
}
else {
b.addNonTerminal(s, arg);
b.addNonTerminal(s.id, arg.id);
}
}
v = b;
Expand All @@ -86,7 +85,7 @@ void reduce() {
break;
case 7:
{
Object c = ((ParseNode)children.get(0)).payload;
Object c = (Object)((ParseNode)children.get(0)).payload;
v = c;
}
break;
Expand All @@ -97,7 +96,7 @@ void reduce() {
break;
case 9:
{
Object arg = ((ParseNode)children.get(1)).payload;
IdToken arg = (IdToken)((ParseNode)children.get(1)).payload;
v = arg;
}
break;
Expand Down
28 changes: 14 additions & 14 deletions run/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@
public final class Parser {
public static final int T_EOF = 0;

public static final int T_CODE = 5;
public static final int T_CODE = 4;

public static final int T_SEMICOLON = 4;
public static final int T_SEMICOLON = 3;

public static final int T_RIGHT_PAREN = 7;
public static final int T_RIGHT_PAREN = 6;

public static final int T_ID = 1;

public static final int T_ASSIGN = 2;

public static final int T_TYPE = 3;
public static final int T_LEFT_PAREN = 5;

public static final int T_LEFT_PAREN = 6;
public static final int T_TYPE = 7;

private static final int terminalCount = 8;

Expand All @@ -27,23 +27,23 @@ public final class Parser {
private static final int startSymbol = -1;

private static final int[] table = {
1,2,0,2,0,0,0,0,
0,3,0,4,0,0,0,0,
0,6,0,0,5,0,0,0,
7,7,0,7,0,8,0,0,
0,9,0,0,9,0,10,0};
1,2,0,0,0,0,0,2,
0,3,0,0,0,0,0,4,
0,6,0,5,0,0,0,0,
7,7,0,0,8,0,0,7,
0,9,0,9,0,10,0,0};

private static final int[][] actionTable = {
{},
{-2,-1},
{1,2,-3},
{3,1,1},
{4,-4},
{7,1,1},
{3,-4},
{1,-5,-3},
{},
{5},
{4},
{},
{6,1,7}};
{5,1,6}};

private Stack<ParseNode> stack;

Expand Down
29 changes: 19 additions & 10 deletions run/knife.kn
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,45 @@
translationUnit = ; { v = new TranslationUnitNode(); }
translationUnit = statement(s) translationUnit(t); { t.addStatement(s); v = t; }

// token types

%type ID IdToken

// statements
%type statement StatementNode

// production statement
statement = ID(nonTerminal) ASSIGN productionStatementBody(body); { v = new ProductionStatementNode(nonTerminal, body.getProduction(), body.getCode()); }

// type statement
statement = TYPE ID(nonTerminal) ID(type); { v = new TypeStatementNode(nonTerminal, type); }

%type productionStatementBody ProductionStatementBody
productionStatementBody = SEMICOLON productionStatementCode(code); { v = new ProductionStatementBody(code); }
productionStatementBody = ID(s) productionStatementArgument(arg) productionStatementBody(b); {
char firstChar = s.charAt(0);
if (Character.isUpperCase(firstChar)) {
if (StringUtils.isTerminal(s.id)) {
if (arg == null) {
b.addTerminal(s);
b.addTerminal(s.id);
}
else {
b.addTerminal(s, arg);
b.addTerminal(s.id, arg.id);
}
}
else {
if (arg == null) {
b.addNonTerminal(s);
b.addNonTerminal(s.id);
}
else {
b.addNonTerminal(s, arg);
b.addNonTerminal(s.id, arg.id);
}
}
v = b;
}

%type productionStatementCode IdToken
productionStatementCode = ; { v = null; }
productionStatementCode = CODE(c); { v = c; }

%type productionStatementArgument IdToken
productionStatementArgument = ; { v = null; }
productionStatementArgument = LEFT_PAREN ID(arg) RIGHT_PAREN; { v = arg; }
productionStatementArgument = LEFT_PAREN ID(arg) RIGHT_PAREN; { v = arg; }

// type statement
statement = TYPE ID(symbol) ID(type); { v = new TypeStatementNode(symbol, type); }
47 changes: 38 additions & 9 deletions src/net/zerobone/knife/Knife.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import net.zerobone.knife.ast.entities.ProductionSymbol;
import net.zerobone.knife.ast.statements.ProductionStatementNode;
import net.zerobone.knife.ast.statements.StatementNode;
import net.zerobone.knife.ast.statements.TypeStatementNode;
import net.zerobone.knife.generator.Generator;
import net.zerobone.knife.generator.GeneratorContext;
import net.zerobone.knife.grammar.Grammar;
Expand All @@ -25,12 +26,15 @@

public class Knife {

public static final String VERSION = "1.0.0-beta";
private static final String VERSION = "1.0.0-beta";

private Grammar grammar;

private Knife(Grammar grammar) {
private final HashMap<String, String> typeMap;

private Knife(Grammar grammar, HashMap<String, String> typeMap) {
this.grammar = grammar;
this.typeMap = typeMap;
}

private void handleErrors(ArrayList<VerificationError> errors) {
Expand Down Expand Up @@ -237,7 +241,7 @@ private void run() {
System.err.println("I/O error: " + e.getMessage());
}

GeneratorContext context = new GeneratorContext("net.zerobone.knife.parser", table);
GeneratorContext context = new GeneratorContext("net.zerobone.knife.parser", table, typeMap);

try {
Generator.generate(context);
Expand Down Expand Up @@ -273,7 +277,7 @@ public static void main(String[] args) {
is = new FileInputStream(args[0]);
}
catch (FileNotFoundException e) {
System.out.println("Error: File '" + args[0] + "' was not found!");
System.out.println("I/O error: File '" + args[0] + "' was not found!");
return;
}

Expand All @@ -286,12 +290,17 @@ public static void main(String[] args) {

do {
currentToken = lexer.lex();
parser.parse(currentToken.id, currentToken);
} while (currentToken.id != Parser.T_EOF);
parser.parse(currentToken.type, currentToken);
} while (currentToken.type != Parser.T_EOF);

}
catch (LexerException | IOException e) {
e.printStackTrace();
catch (LexerException e) {
System.err.println("Syntax error: " + e.getMessage());
return;
}
catch (IOException e) {
System.err.println("I/O error: " + e.getMessage());
return;
}

if (!parser.successfullyParsed()) {
Expand All @@ -303,6 +312,10 @@ public static void main(String[] args) {

Grammar grammar = null;

HashMap<String, String> typeMap = new HashMap<>();

assert t != null;

for (StatementNode stmt : t.statements) {

if (stmt instanceof ProductionStatementNode) {
Expand All @@ -317,6 +330,20 @@ public static void main(String[] args) {
}

}
else if (stmt instanceof TypeStatementNode) {

String symbol = ((TypeStatementNode)stmt).symbol;

String type = ((TypeStatementNode)stmt).type;

if (typeMap.containsKey(symbol)) {
System.err.println("Error: Duplicate type declaration for symbol '" + symbol + "'.");
return;
}

typeMap.put(symbol, type);

}

}

Expand All @@ -325,7 +352,9 @@ public static void main(String[] args) {
return;
}

Knife knife = new Knife(grammar);
// TODO: check that all symbols in the type map exist

Knife knife = new Knife(grammar, typeMap);

knife.run();

Expand Down
6 changes: 3 additions & 3 deletions src/net/zerobone/knife/ast/statements/TypeStatementNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

public class TypeStatementNode extends StatementNode {

public String nonTerminal;
public String symbol;

public String type;

public TypeStatementNode(String nonTerminal, String type) {
this.nonTerminal = nonTerminal;
public TypeStatementNode(String symbol, String type) {
this.symbol = symbol;
this.type = type;
}

Expand Down
7 changes: 6 additions & 1 deletion src/net/zerobone/knife/generator/GeneratorContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,22 @@
import com.squareup.javapoet.ClassName;
import net.zerobone.knife.grammar.table.ParsingTable;

import java.util.HashMap;

public class GeneratorContext {

final String packageName;

final ParsingTable table;

final HashMap<String, String> typeMap;

private ClassName tokenTypeName = null;

public GeneratorContext(String packageName, ParsingTable table) {
public GeneratorContext(String packageName, ParsingTable table, HashMap<String, String> typeMap) {
this.packageName = packageName;
this.table = table;
this.typeMap = typeMap;
}

public void setTokenTypeName(String basePackage, String className) {
Expand Down
8 changes: 7 additions & 1 deletion src/net/zerobone/knife/generator/ParseNodeGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,15 @@ private static MethodSpec constructReduceMethod(GeneratorContext context) {
continue;
}

String symbolType = context.typeMap.get(symbol.id);

if (symbolType == null) {
symbolType = "Object";
}

int childIndex = production.body.size() - 1 - j;

b.addStatement("Object " + symbol.argumentName + " = ((ParseNode)children.get(" + childIndex + ")).payload");
b.addStatement(symbolType + " " + symbol.argumentName + " = (" + symbolType + ")((ParseNode)children.get(" + childIndex + ")).payload");

}

Expand Down
6 changes: 3 additions & 3 deletions src/net/zerobone/knife/lexer/tokens/IdToken.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

public class IdToken extends Token{

public final String identifier;
public final String id;

public IdToken(int line, String identifier) {
public IdToken(int line, String id) {
super(line, Parser.T_ID);
this.identifier = identifier;
this.id = id;
}

}
Loading

0 comments on commit 6dd6c83

Please sign in to comment.