Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Set up visitor #3

Merged
merged 23 commits into from
Jun 13, 2024
8 changes: 5 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ SRC_DIR = src
PARSER_DIR = src/parser
BIN_DIR = out
MAIN_CLASS = com.clp.project.Main
PARSEALL_CLASS = com.clp.project.ParseAll
SOURCES = $(wildcard $(SRC_DIR)/*.java)
SOURCES = $(wildcard $(SRC_DIR)/*.java $(SRC_DIR)/*/*.java)
GRAMMARS = $(PARSER_DIR)/Python3Lexer.g4 $(PARSER_DIR)/Python3Parser.g4
ANTLR_OUTPUT = $(PARSER_DIR)/*.java
DATE = $(shell date +%Y%m%d-%H%M%S)
Expand All @@ -18,6 +17,9 @@ all: $(SOURCES) $(ANTLR_OUTPUT)
$(ANTLR_OUTPUT): $(GRAMMARS)
java -jar lib/antlr-4.13.1-complete.jar $^

build:
$(JAVAC) $(JAVAC_FLAGS) $(SOURCES)

run:
java -cp $(ANTLR_COMPLETE):$(BIN_DIR) $(MAIN_CLASS) $(ARGS)

Expand All @@ -30,4 +32,4 @@ clean:
release: clean
zip -r ../python3-miniparser-$(DATE).zip .

.PHONY: all run clean release runall
.PHONY: all build run clean release runall
1 change: 1 addition & 0 deletions progs/test2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x = 1
93 changes: 64 additions & 29 deletions src/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,83 @@
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Objects;
import javax.swing.*;
import org.antlr.v4.gui.TreeViewer;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.tree.*;

import com.clp.project.ast.*;
import com.clp.project.parser.*;
import com.clp.project.semanticanalysis.*;

public class Main {
public static void main(String[] args) {
for (File file : Objects.requireNonNull(new File("./progs/").listFiles())) {
try {
String fileStr = file.getPath();
// FIXME: use the fileStr above
fileStr = "./progs/test.py";
System.out.println(fileStr);

System.out.println(readFile(fileStr));

CharStream cs = CharStreams.fromFileName(fileStr);
Python3Lexer lexer = new Python3Lexer(cs);
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
Python3Parser parser = new Python3Parser(tokenStream);
Python3Parser.RootContext tree = parser.root();
// String treeStr = tree.toString();
// System.out.println(treeStr);
// Visualize the parse tree
JFrame frame = new JFrame("Parse Tree");
JPanel panel = new JPanel();
TreeViewer viewer = new TreeViewer(Arrays.asList(parser.getRuleNames()), tree);
viewer.setScale(1.5); // Zoom factor
panel.add(viewer);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setVisible(true);
break;
} catch (Exception e) {
e.printStackTrace();
// for (File file : Objects.requireNonNull(new File("./progs/").listFiles())) {
try {
// String fileStr = file.getPath();
// FIXME: use the fileStr above
String fileStr = "./progs/test2.py";
System.out.println(fileStr);

System.out.println(readFile(fileStr));

CharStream cs = CharStreams.fromFileName(fileStr);
Python3Lexer lexer = new Python3Lexer(cs);
CommonTokenStream tokens = new CommonTokenStream(lexer);
Python3Parser parser = new Python3Parser(tokens);
Python3Parser.RootContext tree = parser.root();

// DEBUG
{
tokens.fill();
for (Token token : tokens.getTokens()) {
System.out.println(token.toString());
}

System.out.println("Tree: " + tree);
}

if (tree == null) {
System.err.println("The tree is null.");
return;
}

if (parser.getNumberOfSyntaxErrors() > 0) {
System.err.println("Error on program parsing.");
return;
}

Python3VisitorImpl visitor = new Python3VisitorImpl();
SymbolTable ST = new SymbolTable();
Node ast = visitor.visit(tree);

ArrayList<SemanticError> errors = ast.checkSemantics(ST, 0);
if (errors.size() > 0) {
System.out.println("You had: " + errors.size() + " errors:");
for (SemanticError e : errors)
System.out.println("\t" + e);
} else {
System.out.println("Visualizing AST...");
System.out.println(ast.toPrint(""));
}

JFrame frame = new JFrame("Parse Tree");
JPanel panel = new JPanel();
TreeViewer viewer = new TreeViewer(Arrays.asList(parser.getRuleNames()),
tree);
viewer.setScale(1.5); // Zoom factor
panel.add(viewer);
frame.add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
// }
}

private static String readFile(String filePath) throws IOException {
Expand Down
8 changes: 8 additions & 0 deletions src/ast/BoolType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.clp.project.ast;

public class BoolType extends Type {
public String toPrint(String s) {
return s + "Bool ";
}

}
37 changes: 37 additions & 0 deletions src/ast/CompoundNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.clp.project.ast;

import java.util.ArrayList;

import com.clp.project.semanticanalysis.SemanticError;
import com.clp.project.semanticanalysis.SymbolTable;

public class CompoundNode implements Node {
private Node _if;

public CompoundNode(Node _if) {
this._if = _if;
}

@Override
public ArrayList<SemanticError> checkSemantics(SymbolTable ST, int _nesting) {
ArrayList<SemanticError> errors = new ArrayList<SemanticError>();

errors.addAll(_if.checkSemantics(ST, _nesting));

return errors;
}

public Type typeCheck() {
return new VoidType();
}

public String codeGeneration() {
return "";
}

public String toPrint(String s) {
// FIXME: fix
return "";
}

}
7 changes: 7 additions & 0 deletions src/ast/ErrorType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.clp.project.ast;

public class ErrorType extends Type {
public String toPrint(String s) {
return s + "Error\n";
}
}
54 changes: 54 additions & 0 deletions src/ast/IfNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.clp.project.ast;

import java.util.ArrayList;

import com.clp.project.semanticanalysis.SemanticError;
import com.clp.project.semanticanalysis.SymbolTable;

public class IfNode implements Node {
private Node guard;
private Node thenbranch;
private Node elsebranch;

public IfNode(Node _guard, Node _thenbranch, Node _elsebranch) {
guard = _guard;
thenbranch = _thenbranch;
elsebranch = _elsebranch;
}

@Override
public ArrayList<SemanticError> checkSemantics(SymbolTable ST, int _nesting) {
ArrayList<SemanticError> errors = new ArrayList<SemanticError>();

errors.addAll(guard.checkSemantics(ST, _nesting));
errors.addAll(thenbranch.checkSemantics(ST, _nesting));
errors.addAll(elsebranch.checkSemantics(ST, _nesting));

return errors;
}

public Type typeCheck() {
if (guard.typeCheck() instanceof BoolType) {
Type thenexp = thenbranch.typeCheck();
Type elseexp = elsebranch.typeCheck();
if (thenexp.getClass().equals(elseexp.getClass()))
return thenexp;
else {
System.out.println("Type Error: incompatible types in then and else branches");
return new ErrorType();
}
} else {
System.out.println("Type Error: non boolean condition in if");
return new ErrorType();
}
}

public String codeGeneration() {
return "";
}

public String toPrint(String s) {
return s + "If\n" + guard.toPrint(s + " ") + thenbranch.toPrint(s + " ") + elsebranch.toPrint(s + " ");
}

}
30 changes: 30 additions & 0 deletions src/ast/IntNode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.clp.project.ast;

import java.util.ArrayList;

import com.clp.project.semanticanalysis.SemanticError;
import com.clp.project.semanticanalysis.SymbolTable;

public class IntNode implements Node {
private Integer val;

public IntNode(Integer _val) {
val = _val;
}

public ArrayList<SemanticError> checkSemantics(SymbolTable ST, int _nesting) {
return new ArrayList<SemanticError>();
}

public Type typeCheck() {
return new IntType();
}

public String codeGeneration() {
return "";
}

public String toPrint(String s) {
return s + Integer.toString(val) + "\n";
}
}
7 changes: 7 additions & 0 deletions src/ast/IntType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.clp.project.ast;

public class IntType extends Type {
public String toPrint(String s) {
return s + "Int ";
}
}
17 changes: 17 additions & 0 deletions src/ast/Node.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.clp.project.ast;

import java.util.ArrayList;

import com.clp.project.semanticanalysis.SemanticError;
import com.clp.project.semanticanalysis.SymbolTable;

public interface Node {

ArrayList<SemanticError> checkSemantics(SymbolTable ST, int _nesting);

Type typeCheck();

String codeGeneration();

String toPrint(String s);
}
67 changes: 67 additions & 0 deletions src/ast/Python3VisitorImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.clp.project.ast;

import java.util.ArrayList;
import java.util.List;

import com.clp.project.parser.Python3ParserBaseVisitor;
import com.clp.project.parser.Python3Parser.*;

public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
public Node visitRoot(RootContext ctx) {
ArrayList<Node> stmts = new ArrayList<Node>();
ArrayList<Node> compStmts = new ArrayList<Node>();

for (Simple_stmtsContext s : ctx.simple_stmts()) {
stmts.add(visit(s));
}
for (Compound_stmtContext s : ctx.compound_stmt()) {
compStmts.add(visit(s));
}

return new RootNode(stmts, compStmts);
}

public Node visitSimple_stmts(Simple_stmtsContext ctx) {
ArrayList<Node> stmts = new ArrayList<Node>();

for (Simple_stmtContext stm : ctx.simple_stmt()) {
stmts.add(visit(stm));
}

return new SimpleStmtsNode(stmts);
}

public Node visitSimple_stmt(Simple_stmtContext ctx) {
Node exp = visit(ctx.expr());

return exp;
}

public Node visitCompound_stmt(Compound_stmtContext ctx) {
Node ifStmt = visit(ctx.if_stmt());
// FIXME: adds below
// Node whileStmt = visit(ctx.while_stmt());
// Node forStmt = visit(ctx.for_stmt());
// Node funcDef = visit(ctx.funcdef());
//
return new CompoundNode(ifStmt);
}

public Node visitAssignment(AssignmentContext ctx) {
Node exp = visit(ctx.exprlist(1));
return exp;
}

// FIXME: add support for `elif`
public Node visitIf_stmt(If_stmtContext ctx) {
var blocks = ctx.block();
Node condExp = visit(ctx.expr(0));
Node thenExp = visit(blocks.get(0));
Node elseExp = null;
if (blocks.size() > 1) {
elseExp = visit(blocks.get(1));
}

return new IfNode(condExp, thenExp, elseExp);
}
}
Loading