stmt_list, opt_stmt_list;
+non terminal Stmt stmt, expr_stmt;
+non terminal Expr expr, binary_expr;
+
+/* Precedences (lowest to highest) for resolving what would otherwise be
+ * ambiguities in the form of shift/reduce conflicts.. */
+precedence left PLUS;
+
+/* The start symbol. */
+start with program;
+
+
+/***** GRAMMAR RULES *****/
+
+program ::= program_head:d opt_stmt_list:s
+ {: RESULT = new Program(d.isEmpty() ? getLeft(s) : getLeft(d),
+ sxright, d, s, errors);
+ :}
+ ;
+
+/* Initial list of declarations. */
+program_head ::= /* not implemented; currently matches empty string */
+ {: RESULT = empty(); :}
+ ;
+
+opt_stmt_list ::= {: RESULT = empty(); :}
+ | stmt_list:s {: RESULT = s; :}
+ ;
+
+stmt_list ::= stmt:s {: RESULT = single(s); :}
+ | stmt_list:l stmt:s {: RESULT = combine(l, s); :}
+ | stmt_list:l error {: RESULT = l; :}
+ /* If there is a syntax error in the source, this says to discard
+ * symbols from the parsing stack and perform reductions until
+ * there is a stmt_list on top of the stack, and then to discard
+ * input symbols until it is possible to shift again, reporting
+ * a syntax error. */
+ ;
+
+stmt ::= expr_stmt:s NEWLINE {: RESULT = s; :}
+ ;
+
+expr_stmt ::= expr:e {: RESULT = new ExprStmt(exleft, exright, e); :}
+ ;
+
+expr ::= binary_expr:e {: RESULT = e; :}
+ | NUMBER:n {: RESULT = new IntegerLiteral(nxleft, nxright, n); :}
+ ;
+
+
+/* A binary expression, illustrating how to find the left and right
+ * source position of a phrase. */
+binary_expr ::= expr:e1 PLUS:op expr:e2
+ {: RESULT = new BinaryExpr(e1xleft, e2xright,
+ e1, op, e2); :}
+ ;
diff --git a/src/main/java/chocopy/common/Utils.java b/src/main/java/chocopy/common/Utils.java
new file mode 100644
index 0000000..661dfd3
--- /dev/null
+++ b/src/main/java/chocopy/common/Utils.java
@@ -0,0 +1,64 @@
+package chocopy.common;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.stream.Collectors;
+
+
+/**
+ * Utility functions for general use.
+ */
+public class Utils {
+
+ /**
+ * Return resource file FILENAME's contents as a string. FILENAME
+ * can refer to a file within the class hierarchy, so that a text
+ * resource in file resource.txt in the chocopy.common.codegen
+ * package, for example, could be referred to with FILENAME
+ * chocopy/common/codegen/resource.txt.
+ *
+ * Credit: Lucio Paiva.
+ */
+ public static String getResourceFileAsString(String fileName) {
+ InputStream is =
+ Utils.class.getClassLoader().getResourceAsStream(fileName);
+ if (is != null) {
+ BufferedReader reader =
+ new BufferedReader
+ (new InputStreamReader(is, StandardCharsets.UTF_8));
+ return reader.lines().collect
+ (Collectors.joining(System.lineSeparator()));
+ }
+ return null;
+ }
+
+ /**
+ * Return an exception signalling a fatal error having a message
+ * formed from MSGFORMAT and ARGS, as for String.format.
+ */
+ public static Error fatal(String msgFormat, Object... args) {
+ return new Error(String.format(msgFormat, args));
+ }
+
+ /**
+ * Return the string S padded with FILL to TOLEN characters. Padding
+ * is on the left if PADONLEFT, and otherwise on the right. If S is
+ * already at least TOLEN characters, returns S.
+ */
+ public static String pad(String s, Character fill, int toLen,
+ boolean padOnLeft) {
+ StringBuilder result = new StringBuilder(toLen);
+ if (!padOnLeft) {
+ result.append(s);
+ }
+ for (int n = s.length(); n < toLen; n += 1) {
+ result.append(fill);
+ }
+ if (padOnLeft) {
+ result.append(s);
+ }
+ return result.toString();
+ }
+}
diff --git a/src/main/java/chocopy/common/analysis/NodeAnalyzer.java b/src/main/java/chocopy/common/analysis/NodeAnalyzer.java
new file mode 100644
index 0000000..5ea8a6c
--- /dev/null
+++ b/src/main/java/chocopy/common/analysis/NodeAnalyzer.java
@@ -0,0 +1,100 @@
+package chocopy.common.analysis;
+
+import chocopy.common.astnodes.*;
+
+/**
+ * This interface can be used to separate logic for various concrete
+ * classes in the AST class hierarchy.
+ *
+ * The idea is that a phase of the analysis is encapsulated in a class
+ * that implements this interface, and contains an overriding of the
+ * analyze method for each concrete Node class that needs something
+ * other than default processing. Each concrete node class, C, implements
+ * a generic dispatch method that takes a NodeAnalyzer argument and
+ * calls the overloading of analyze that takes an argument of type C.
+ * The effect is that anode.dispatch(anAnalyzer) executes the method
+ * anAnalyzer.analyze that is appropriate to aNode's dynamic type.
+ * As a result each NodeAnalyzer subtype encapsulates all
+ * implementations of a particular action on Nodes. Thus, it inverts
+ * the usual OO pattern in which the implementations of analysis A for
+ * each different class are scattered among the class bodies
+ * themselves as overridings of a method A on the Node class.
+ *
+ * The class AbstractNodeAnalyzer provides empty default
+ * implementations for these methods.
+ *
+ * The type T is the type of result returned by the encapsulated analysis.
+ */
+public interface NodeAnalyzer {
+
+ T analyze(AssignStmt node);
+
+ T analyze(BinaryExpr node);
+
+ T analyze(BooleanLiteral node);
+
+ T analyze(CallExpr node);
+
+ T analyze(ClassDef node);
+
+ T analyze(ClassType node);
+
+ T analyze(CompilerError node);
+
+ T analyze(Errors node);
+
+ T analyze(ExprStmt node);
+
+ T analyze(ForStmt node);
+
+ T analyze(FuncDef node);
+
+ T analyze(GlobalDecl node);
+
+ T analyze(Identifier node);
+
+ T analyze(IfExpr node);
+
+ T analyze(IfStmt node);
+
+ T analyze(IndexExpr node);
+
+ T analyze(IntegerLiteral node);
+
+ T analyze(ListExpr node);
+
+ T analyze(ListType node);
+
+ T analyze(MemberExpr node);
+
+ T analyze(MethodCallExpr node);
+
+ T analyze(NoneLiteral node);
+
+ T analyze(NonLocalDecl node);
+
+ T analyze(Program node);
+
+ T analyze(ReturnStmt node);
+
+ T analyze(StringLiteral node);
+
+ T analyze(TypedVar node);
+
+ T analyze(UnaryExpr node);
+
+ T analyze(VarDef node);
+
+ T analyze(WhileStmt node);
+
+ /**
+ * Set the default value returned by calls to analyze that are not
+ * overridden to VALUE. By default, this is null.
+ */
+ void setDefault(T value);
+
+ /**
+ * Default value for non-overridden methods.
+ */
+ T defaultAction(Node node);
+}
diff --git a/src/main/java/chocopy/common/astnodes/AssignStmt.java b/src/main/java/chocopy/common/astnodes/AssignStmt.java
new file mode 100644
index 0000000..8b3f49c
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/AssignStmt.java
@@ -0,0 +1,36 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+import java.util.List;
+
+/**
+ * Single and multiple assignments.
+ */
+public class AssignStmt extends Stmt {
+ /**
+ * List of left-hand sides.
+ */
+ public final List targets;
+ /**
+ * Right-hand-side value to be assigned.
+ */
+ public final Expr value;
+
+ /**
+ * AST for TARGETS[0] = TARGETS[1] = ... = VALUE spanning source locations
+ * [LEFT..RIGHT].
+ */
+ public AssignStmt(Location left, Location right,
+ List targets, Expr value) {
+ super(left, right);
+ this.targets = targets;
+ this.value = value;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/BinaryExpr.java b/src/main/java/chocopy/common/astnodes/BinaryExpr.java
new file mode 100644
index 0000000..3ef3d46
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/BinaryExpr.java
@@ -0,0 +1,40 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * .
+ */
+public class BinaryExpr extends Expr {
+
+ /**
+ * Left operand.
+ */
+ public final Expr left;
+ /**
+ * Operator name.
+ */
+ public final String operator;
+ /**
+ * Right operand.
+ */
+ public final Expr right;
+
+ /**
+ * An AST for expressions of the form LEFTEXPR OP RIGHTEXPR
+ * from text in range [LEFTLOC..RIGHTLOC].
+ */
+ public BinaryExpr(Location leftLoc, Location rightLoc, Expr leftExpr,
+ String op, Expr rightExpr) {
+ super(leftLoc, rightLoc);
+ left = leftExpr;
+ operator = op;
+ right = rightExpr;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/BooleanLiteral.java b/src/main/java/chocopy/common/astnodes/BooleanLiteral.java
new file mode 100644
index 0000000..bf13f08
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/BooleanLiteral.java
@@ -0,0 +1,29 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Literals True or False.
+ */
+public final class BooleanLiteral extends Literal {
+
+ /**
+ * True iff I represent True.
+ */
+ public final boolean value;
+
+ /**
+ * An AST for the token True or False at [LEFT..RIGHT], depending on
+ * VALUE.
+ */
+ public BooleanLiteral(Location left, Location right, boolean value) {
+ super(left, right);
+ this.value = value;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/CallExpr.java b/src/main/java/chocopy/common/astnodes/CallExpr.java
new file mode 100644
index 0000000..80272ee
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/CallExpr.java
@@ -0,0 +1,36 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+import java.util.List;
+
+/**
+ * A function call.
+ */
+public class CallExpr extends Expr {
+
+ /**
+ * The called function.
+ */
+ public final Identifier function;
+ /**
+ * The actual parameter expressions.
+ */
+ public final List args;
+
+ /**
+ * AST for FUNCTION(ARGS) at [LEFT..RIGHT].
+ */
+ public CallExpr(Location left, Location right, Identifier function,
+ List args) {
+ super(left, right);
+ this.function = function;
+ this.args = args;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/ClassDef.java b/src/main/java/chocopy/common/astnodes/ClassDef.java
new file mode 100644
index 0000000..982d128
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/ClassDef.java
@@ -0,0 +1,50 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+import java.util.List;
+
+/**
+ * A class definition.
+ */
+public class ClassDef extends Declaration {
+
+ /**
+ * Name of the declared class.
+ */
+ public final Identifier name;
+ /**
+ * Name of the parent class.
+ */
+ public final Identifier superClass;
+ /**
+ * Body of the class.
+ */
+ public final List declarations;
+
+ /**
+ * An AST for class
+ * NAME(SUPERCLASS):
+ * DECLARATIONS.
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public ClassDef(Location left, Location right,
+ Identifier name, Identifier superClass,
+ List declarations) {
+ super(left, right);
+ this.name = name;
+ this.superClass = superClass;
+ this.declarations = declarations;
+ }
+
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+ @Override
+ public Identifier getIdentifier() {
+ return this.name;
+ }
+}
diff --git a/src/main/java/chocopy/common/astnodes/ClassType.java b/src/main/java/chocopy/common/astnodes/ClassType.java
new file mode 100644
index 0000000..eab39af
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/ClassType.java
@@ -0,0 +1,28 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * A simple class type name.
+ */
+public final class ClassType extends TypeAnnotation {
+
+ /**
+ * The denotation of the class in source.
+ */
+ public final String className;
+
+ /**
+ * An AST denoting a type named CLASSNAME0 at [LEFT..RIGHT].
+ */
+ public ClassType(Location left, Location right, String className0) {
+ super(left, right);
+ className = className0;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/CompilerError.java b/src/main/java/chocopy/common/astnodes/CompilerError.java
new file mode 100644
index 0000000..c61617e
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/CompilerError.java
@@ -0,0 +1,64 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * Represents a single error. Does not correspond to any Python source
+ * construct.
+ */
+public class CompilerError extends Node {
+
+ /**
+ * Represents an error with message MESSAGE. Iff SYNTAX, it is a
+ * syntactic error. The error applies to source text at [LEFT..RIGHT].
+ */
+ public CompilerError(Location left, Location right, String message,
+ boolean syntax) {
+ super(left, right);
+ this.message = message;
+ this.syntax = syntax;
+ }
+
+ @JsonInclude(JsonInclude.Include.NON_DEFAULT)
+ public boolean isSyntax() {
+ return syntax;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ CompilerError that = (CompilerError) o;
+ return Objects.equals(message, that.message)
+ && Arrays.equals(getLocation(), that.getLocation());
+ }
+
+ @Override
+ public int hashCode() {
+ int result = Objects.hash(message);
+ result = 31 * result + Arrays.hashCode(getLocation());
+ return result;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+ /**
+ * The error message.
+ */
+ public final String message;
+ /**
+ * True if this is a syntax error.
+ */
+ private final boolean syntax;
+}
diff --git a/src/main/java/chocopy/common/astnodes/Declaration.java b/src/main/java/chocopy/common/astnodes/Declaration.java
new file mode 100644
index 0000000..769ece3
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/Declaration.java
@@ -0,0 +1,23 @@
+package chocopy.common.astnodes;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Base of all AST nodes representing definitions or declarations.
+ */
+public abstract class Declaration extends Node {
+
+ /**
+ * A definition or declaration spanning source locations [LEFT..RIGHT].
+ */
+ public Declaration(Location left, Location right) {
+ super(left, right);
+ }
+
+ /**
+ * Return the identifier defined by this Declaration.
+ */
+ @JsonIgnore
+ public abstract Identifier getIdentifier();
+}
diff --git a/src/main/java/chocopy/common/astnodes/Errors.java b/src/main/java/chocopy/common/astnodes/Errors.java
new file mode 100644
index 0000000..cea2c5b
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/Errors.java
@@ -0,0 +1,90 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+import java.util.List;
+
+/**
+ * Collects the error messages in a Program. There is exactly one per
+ * Program node.
+ */
+public class Errors extends Node {
+
+ /**
+ * The accumulated error messages in the order added.
+ */
+ public final List errors;
+
+ /**
+ * True iff multiple semantic errors allowed on a node.
+ */
+ @JsonIgnore
+ private boolean allowMultipleErrors;
+
+ /**
+ * An Errors whose list of CompilerErrors is ERRORS. The list should be
+ * modified using this.add.
+ */
+ @JsonCreator
+ public Errors(List errors) {
+ super(null, null);
+ this.errors = errors;
+ allowMultipleErrors = true;
+ }
+
+ /**
+ * Return true iff there are any errors.
+ */
+ public boolean hasErrors() {
+ return !this.errors.isEmpty();
+ }
+
+ /**
+ * Prevent multiple semantic errors on the same node.
+ */
+ public void suppressMultipleErrors() {
+ allowMultipleErrors = false;
+ }
+
+ /**
+ * Add a new semantic error message attributed to NODE, with message
+ * String.format(MESSAGEFORM, ARGS).
+ */
+ public void semError(Node node, String messageForm, Object... args) {
+ if (allowMultipleErrors || !node.hasError()) {
+ String msg = String.format(messageForm, args);
+ CompilerError err = new CompilerError(null, null, msg, false);
+ err.setLocation(node.getLocation());
+ add(err);
+ if (!node.hasError()) {
+ node.setErrorMsg(msg);
+ }
+ }
+ }
+
+ /**
+ * Add a new syntax error message attributed to the source text
+ * between LEFT and RIGHT, and with message
+ * String.format(MESSAGEFORM, ARGS).
+ */
+ public void syntaxError(Location left, Location right,
+ String messageForm, Object... args) {
+ add(new CompilerError(left, right, String.format(messageForm, args),
+ true));
+ }
+
+ /**
+ * Add ERR to the list of errors.
+ */
+ public void add(CompilerError err) {
+ errors.add(err);
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/Expr.java b/src/main/java/chocopy/common/astnodes/Expr.java
new file mode 100644
index 0000000..c5cb884
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/Expr.java
@@ -0,0 +1,22 @@
+package chocopy.common.astnodes;
+
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Base of all AST nodes representing expressions.
+ *
+ * There is nothing in this class, but there will be many AST
+ * node types that have fields that are *any expression*. For those
+ * cases, having a field of this type will encompass all types of
+ * expressions such as binary expressions and literals that subclass
+ * this class.
+ */
+public abstract class Expr extends Node {
+
+ /**
+ * A Python expression spanning source locations [LEFT..RIGHT].
+ */
+ public Expr(Location left, Location right) {
+ super(left, right);
+ }
+}
diff --git a/src/main/java/chocopy/common/astnodes/ExprStmt.java b/src/main/java/chocopy/common/astnodes/ExprStmt.java
new file mode 100644
index 0000000..177c407
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/ExprStmt.java
@@ -0,0 +1,29 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Statements consisting of expressions.
+ */
+public final class ExprStmt extends Stmt {
+
+ /**
+ * The expression I evaluate.
+ */
+ public final Expr expr;
+
+ /**
+ * The AST for EXPR spanning source locations [LEFT..RIGHT]
+ * in a statement context.
+ */
+ public ExprStmt(Location left, Location right, Expr expr) {
+ super(left, right);
+ this.expr = expr;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/ForStmt.java b/src/main/java/chocopy/common/astnodes/ForStmt.java
new file mode 100644
index 0000000..8463da1
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/ForStmt.java
@@ -0,0 +1,43 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+import java.util.List;
+
+/**
+ * For statements.
+ */
+public class ForStmt extends Stmt {
+ /**
+ * Control variable.
+ */
+ public final Identifier identifier;
+ /**
+ * Source of values of control statement.
+ */
+ public final Expr iterable;
+ /**
+ * Repeated statements.
+ */
+ public final List body;
+
+ /**
+ * The AST for
+ * for IDENTIFIER in ITERABLE:
+ * BODY
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public ForStmt(Location left, Location right,
+ Identifier identifier, Expr iterable, List body) {
+ super(left, right);
+ this.identifier = identifier;
+ this.iterable = iterable;
+ this.body = body;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/FuncDef.java b/src/main/java/chocopy/common/astnodes/FuncDef.java
new file mode 100644
index 0000000..42f67bf
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/FuncDef.java
@@ -0,0 +1,61 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+import java.util.List;
+
+/**
+ * Def statements.
+ */
+public class FuncDef extends Declaration {
+
+ /**
+ * Defined name.
+ */
+ public final Identifier name;
+ /**
+ * Formal parameters.
+ */
+ public final List params;
+ /**
+ * Return type annotation.
+ */
+ public final TypeAnnotation returnType;
+ /**
+ * Local-variable,inner-function, global, and nonlocal declarations.
+ */
+ public final List declarations;
+ /**
+ * Other statements.
+ */
+ public final List statements;
+
+ /**
+ * The AST for
+ * def NAME(PARAMS) -> RETURNTYPE:
+ * DECLARATIONS
+ * STATEMENTS
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public FuncDef(Location left, Location right,
+ Identifier name, List params,
+ TypeAnnotation returnType,
+ List declarations, List statements) {
+ super(left, right);
+ this.name = name;
+ this.params = params;
+ this.returnType = returnType;
+ this.declarations = declarations;
+ this.statements = statements;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+ @Override
+ public Identifier getIdentifier() {
+ return this.name;
+ }
+}
diff --git a/src/main/java/chocopy/common/astnodes/GlobalDecl.java b/src/main/java/chocopy/common/astnodes/GlobalDecl.java
new file mode 100644
index 0000000..3bac547
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/GlobalDecl.java
@@ -0,0 +1,34 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Declaration of global variable.
+ */
+public class GlobalDecl extends Declaration {
+
+ /**
+ * The declared variable.
+ */
+ public final Identifier variable;
+
+ /**
+ * The AST for the declaration
+ * global VARIABLE
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public GlobalDecl(Location left, Location right, Identifier variable) {
+ super(left, right);
+ this.variable = variable;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+ @Override
+ public Identifier getIdentifier() {
+ return this.variable;
+ }
+}
diff --git a/src/main/java/chocopy/common/astnodes/Identifier.java b/src/main/java/chocopy/common/astnodes/Identifier.java
new file mode 100644
index 0000000..b1aeea5
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/Identifier.java
@@ -0,0 +1,29 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * A simple identifier.
+ */
+public class Identifier extends Expr {
+
+ /**
+ * Text of the identifier.
+ */
+ public final String name;
+
+ /**
+ * An AST for the variable, method, or parameter named NAME, spanning
+ * source locations [LEFT..RIGHT].
+ */
+ public Identifier(Location left, Location right, String name) {
+ super(left, right);
+ this.name = name;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/IfExpr.java b/src/main/java/chocopy/common/astnodes/IfExpr.java
new file mode 100644
index 0000000..67d5b13
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/IfExpr.java
@@ -0,0 +1,40 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Conditional expressions.
+ */
+public class IfExpr extends Expr {
+ /**
+ * Boolean condition.
+ */
+ public final Expr condition;
+ /**
+ * True branch.
+ */
+ public final Expr thenExpr;
+ /**
+ * False branch.
+ */
+ public final Expr elseExpr;
+
+ /**
+ * The AST for
+ * THENEXPR if CONDITION else ELSEEXPR
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public IfExpr(Location left, Location right,
+ Expr condition, Expr thenExpr, Expr elseExpr) {
+ super(left, right);
+ this.condition = condition;
+ this.thenExpr = thenExpr;
+ this.elseExpr = elseExpr;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/IfStmt.java b/src/main/java/chocopy/common/astnodes/IfStmt.java
new file mode 100644
index 0000000..16da823
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/IfStmt.java
@@ -0,0 +1,45 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+import java.util.List;
+
+/**
+ * Conditional statement.
+ */
+public class IfStmt extends Stmt {
+ /**
+ * Test condition.
+ */
+ public final Expr condition;
+ /**
+ * "True" branch.
+ */
+ public final List thenBody;
+ /**
+ * "False" branch.
+ */
+ public final List elseBody;
+
+ /**
+ * The AST for
+ * if CONDITION:
+ * THENBODY
+ * else:
+ * ELSEBODY
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public IfStmt(Location left, Location right,
+ Expr condition, List thenBody, List elseBody) {
+ super(left, right);
+ this.condition = condition;
+ this.thenBody = thenBody;
+ this.elseBody = elseBody;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/IndexExpr.java b/src/main/java/chocopy/common/astnodes/IndexExpr.java
new file mode 100644
index 0000000..8038c3f
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/IndexExpr.java
@@ -0,0 +1,35 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * List-indexing expression.
+ */
+public class IndexExpr extends Expr {
+
+ /**
+ * Indexed list.
+ */
+ public final Expr list;
+ /**
+ * Expression for index value.
+ */
+ public final Expr index;
+
+ /**
+ * The AST for
+ * LIST[INDEX].
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public IndexExpr(Location left, Location right, Expr list, Expr index) {
+ super(left, right);
+ this.list = list;
+ this.index = index;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/IntegerLiteral.java b/src/main/java/chocopy/common/astnodes/IntegerLiteral.java
new file mode 100644
index 0000000..d383472
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/IntegerLiteral.java
@@ -0,0 +1,29 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Integer numerals.
+ */
+public final class IntegerLiteral extends Literal {
+
+ /**
+ * Value denoted.
+ */
+ public final int value;
+
+ /**
+ * The AST for the literal VALUE, spanning source
+ * locations [LEFT..RIGHT].
+ */
+ public IntegerLiteral(Location left, Location right, int value) {
+ super(left, right);
+ this.value = value;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/ListExpr.java b/src/main/java/chocopy/common/astnodes/ListExpr.java
new file mode 100644
index 0000000..226d42b
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/ListExpr.java
@@ -0,0 +1,32 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+import java.util.List;
+
+/**
+ * List displays.
+ */
+public final class ListExpr extends Expr {
+
+ /**
+ * List of element expressions.
+ */
+ public final List elements;
+
+ /**
+ * The AST for
+ * [ ELEMENTS ].
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public ListExpr(Location left, Location right, List elements) {
+ super(left, right);
+ this.elements = elements;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/ListType.java b/src/main/java/chocopy/common/astnodes/ListType.java
new file mode 100644
index 0000000..0cbf0a0
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/ListType.java
@@ -0,0 +1,30 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Type denotation for a list type.
+ */
+public final class ListType extends TypeAnnotation {
+
+ /**
+ * The element of list element.
+ */
+ public final TypeAnnotation elementType;
+
+ /**
+ * The AST for the type annotation
+ * [ ELEMENTTYPE ].
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public ListType(Location left, Location right, TypeAnnotation elementType) {
+ super(left, right);
+ this.elementType = elementType;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/Literal.java b/src/main/java/chocopy/common/astnodes/Literal.java
new file mode 100644
index 0000000..ac2c026
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/Literal.java
@@ -0,0 +1,18 @@
+package chocopy.common.astnodes;
+
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Base of all the literal nodes.
+ *
+ * There is nothing in this class, but it is useful to isolate
+ * expressions that are constant literals.
+ */
+public abstract class Literal extends Expr {
+ /**
+ * A literal spanning source locations [LEFT..RIGHT].
+ */
+ public Literal(Location left, Location right) {
+ super(left, right);
+ }
+}
diff --git a/src/main/java/chocopy/common/astnodes/MemberExpr.java b/src/main/java/chocopy/common/astnodes/MemberExpr.java
new file mode 100644
index 0000000..a59abe7
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/MemberExpr.java
@@ -0,0 +1,36 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Attribute accessor.
+ */
+public class MemberExpr extends Expr {
+
+ /**
+ * Object selected from.
+ */
+ public final Expr object;
+ /**
+ * Name of attribute (instance variable or method).
+ */
+ public final Identifier member;
+
+ /**
+ * The AST for
+ * OBJECT.MEMBER.
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public MemberExpr(Location left, Location right,
+ Expr object, Identifier member) {
+ super(left, right);
+ this.object = object;
+ this.member = member;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/MethodCallExpr.java b/src/main/java/chocopy/common/astnodes/MethodCallExpr.java
new file mode 100644
index 0000000..7674a13
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/MethodCallExpr.java
@@ -0,0 +1,38 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+import java.util.List;
+
+/**
+ * Method calls.
+ */
+public class MethodCallExpr extends Expr {
+
+ /**
+ * Expression for the bound method to be called.
+ */
+ public final MemberExpr method;
+ /**
+ * Actual parameters.
+ */
+ public final List args;
+
+ /**
+ * The AST for
+ * METHOD(ARGS).
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public MethodCallExpr(Location left, Location right,
+ MemberExpr method, List args) {
+ super(left, right);
+ this.method = method;
+ this.args = args;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/Node.java b/src/main/java/chocopy/common/astnodes/Node.java
new file mode 100644
index 0000000..d84345b
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/Node.java
@@ -0,0 +1,204 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+import java.io.IOException;
+
+/**
+ * Root of the AST class hierarchy. Every node has a left and right
+ * location, indicating the start and end of the represented construct
+ * in the source text.
+ *
+ * Every node can be marked with an error message, which serves two purposes:
+ * 1. It indicates that an error message has been issued for this
+ * Node, allowing tne program to reduce cascades of error
+ * messages.
+ * 2. It aids in debugging by making it convenient to see which
+ * Nodes have caused an error.
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
+ include = JsonTypeInfo.As.EXISTING_PROPERTY,
+ property = "kind")
+/* List of all concrete subclasses of Node. */
+@JsonSubTypes({
+ @JsonSubTypes.Type(AssignStmt.class),
+ @JsonSubTypes.Type(BinaryExpr.class),
+ @JsonSubTypes.Type(BooleanLiteral.class),
+ @JsonSubTypes.Type(CallExpr.class),
+ @JsonSubTypes.Type(ClassDef.class),
+ @JsonSubTypes.Type(ClassType.class),
+ @JsonSubTypes.Type(CompilerError.class),
+ @JsonSubTypes.Type(Errors.class),
+ @JsonSubTypes.Type(ExprStmt.class),
+ @JsonSubTypes.Type(ForStmt.class),
+ @JsonSubTypes.Type(FuncDef.class),
+ @JsonSubTypes.Type(GlobalDecl.class),
+ @JsonSubTypes.Type(Identifier.class),
+ @JsonSubTypes.Type(IfExpr.class),
+ @JsonSubTypes.Type(IfStmt.class),
+ @JsonSubTypes.Type(IndexExpr.class),
+ @JsonSubTypes.Type(IntegerLiteral.class),
+ @JsonSubTypes.Type(ListExpr.class),
+ @JsonSubTypes.Type(ListType.class),
+ @JsonSubTypes.Type(MemberExpr.class),
+ @JsonSubTypes.Type(MethodCallExpr.class),
+ @JsonSubTypes.Type(NoneLiteral.class),
+ @JsonSubTypes.Type(NonLocalDecl.class),
+ @JsonSubTypes.Type(Program.class),
+ @JsonSubTypes.Type(ReturnStmt.class),
+ @JsonSubTypes.Type(StringLiteral.class),
+ @JsonSubTypes.Type(TypedVar.class),
+ @JsonSubTypes.Type(UnaryExpr.class),
+ @JsonSubTypes.Type(VarDef.class),
+ @JsonSubTypes.Type(WhileStmt.class),
+})
+public abstract class Node {
+
+ /**
+ * Node-type indicator for JSON form.
+ */
+ public final String kind;
+
+ /**
+ * Source position information: 0: line number of start, 1: column number
+ * of start, 2: line number of end, 3: column number of end.
+ */
+ private final int[] location = new int[4];
+
+ /**
+ * First error message "blamed" on this Node. When non-null, indicates
+ * that an error has been found in this Node.
+ */
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ private String errorMsg;
+
+ /**
+ * A Node corresponding to source text between LEFT and RIGHT.
+ */
+ public Node(Location left, Location right) {
+ if (left != null) {
+ location[0] = left.getLine();
+ location[1] = left.getColumn();
+ }
+ if (right != null) {
+ location[2] = right.getLine();
+ location[3] = right.getColumn();
+ }
+ this.kind = getClass().getSimpleName();
+ this.errorMsg = null;
+ }
+
+ /**
+ * Return my source location as
+ * { , , , }.
+ * Result should not be modified, and contents will change after
+ * setLocation().
+ */
+ public int[] getLocation() {
+ return location;
+ }
+
+ /**
+ * Copy LOCATION as getLocation().
+ */
+ public void setLocation(final int[] location) {
+ System.arraycopy(location, 0, this.location, 0, 4);
+ }
+
+ public String getErrorMsg() {
+ return errorMsg;
+ }
+
+ public void setErrorMsg(String msg) {
+ this.errorMsg = msg;
+ }
+
+ /**
+ * Return true iff I have been marked with an error message.
+ */
+ @JsonIgnore
+ public boolean hasError() {
+ return this.errorMsg != null;
+ }
+
+ /**
+ * Invoke ANALYZER on me as a node of static type T. See the comment
+ * on NodeAnalyzer. Returns modified Node.
+ */
+ public abstract T dispatch(NodeAnalyzer analyzer);
+
+ /**
+ * Print out the AST in JSON format.
+ */
+ @Override
+ public String toString() {
+ try {
+ return toJSON();
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Return a serialization of this node in JSON format.
+ */
+ public String toJSON() throws JsonProcessingException {
+ return mapper.writeValueAsString(this);
+ }
+
+ /**
+ * Mapper to-and-from serialized JSON.
+ */
+ private static final ObjectMapper mapper = new ObjectMapper();
+
+ static {
+ mapper.enable(SerializationFeature.INDENT_OUTPUT);
+ mapper.registerModule(new ParameterNamesModule());
+ }
+
+ /**
+ * Returns a T from JSON, a JSON-serialized T value with class
+ * CLAS.
+ */
+ public static T fromJSON(String json, Class clas)
+ throws IOException {
+ return mapper.readValue(json, clas);
+ }
+
+ /**
+ * Returns the result of converting JSON, a JSon-serialization of
+ * a Node value, into the value it serializes.
+ */
+ public static Node fromJSON(String json)
+ throws IOException {
+ return fromJSON(json, Node.class);
+ }
+
+ /**
+ * Returns the result of converting TREE to the value of type T
+ * that it represents, where CLAS reflects T.
+ */
+ public static T fromJSON(JsonNode tree, Class clas)
+ throws IOException {
+ return mapper.treeToValue(tree, clas);
+ }
+
+ /**
+ * Returns the translation of serialized value SRC into the
+ * corresponding JSON tree.
+ */
+ public static JsonNode readTree(String src) throws IOException {
+ return mapper.readTree(src);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/NonLocalDecl.java b/src/main/java/chocopy/common/astnodes/NonLocalDecl.java
new file mode 100644
index 0000000..d03508e
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/NonLocalDecl.java
@@ -0,0 +1,34 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Nonlocal declaration.
+ */
+public class NonLocalDecl extends Declaration {
+
+ /**
+ * Name of identifier being declared.
+ */
+ public final Identifier variable;
+
+ /**
+ * The AST for
+ * nonlocal VARIABLE
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public NonLocalDecl(Location left, Location right, Identifier variable) {
+ super(left, right);
+ this.variable = variable;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+ @Override
+ public Identifier getIdentifier() {
+ return this.variable;
+ }
+}
diff --git a/src/main/java/chocopy/common/astnodes/NoneLiteral.java b/src/main/java/chocopy/common/astnodes/NoneLiteral.java
new file mode 100644
index 0000000..d38211c
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/NoneLiteral.java
@@ -0,0 +1,21 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * The expression 'None'.
+ */
+public final class NoneLiteral extends Literal {
+
+ /**
+ * The AST for None, spanning source locations [LEFT..RIGHT].
+ */
+ public NoneLiteral(Location left, Location right) {
+ super(left, right);
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+}
diff --git a/src/main/java/chocopy/common/astnodes/Program.java b/src/main/java/chocopy/common/astnodes/Program.java
new file mode 100644
index 0000000..29dd28e
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/Program.java
@@ -0,0 +1,70 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An entire ChocoPy program.
+ */
+public class Program extends Node {
+
+ /**
+ * Initial variable, class, and function declarations.
+ */
+ public final List declarations;
+ /**
+ * Trailing statements.
+ */
+ public final List statements;
+ /**
+ * Accumulated errors.
+ */
+ public final Errors errors;
+
+ /**
+ * The AST for the program
+ * DECLARATIONS
+ * STATEMENTS
+ * spanning source locations [LEFT..RIGHT].
+ *
+ * ERRORS is the container for all error messages applying to the
+ * program.
+ */
+ public Program(Location left, Location right,
+ List declarations, List statements,
+ Errors errors) {
+ super(left, right);
+ this.declarations = declarations;
+ this.statements = statements;
+ if (errors == null) {
+ this.errors = new Errors(new ArrayList<>());
+ } else {
+ this.errors = errors;
+ }
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+ /**
+ * Returns true iff there is at least one error in the program.
+ */
+ @JsonIgnore
+ public boolean hasErrors() {
+ return errors.hasErrors();
+ }
+
+ /**
+ * A convenience method returning the list of all CompilerErrors for
+ * this program.
+ */
+ @JsonIgnore
+ public List getErrorList() {
+ return errors.errors;
+ }
+}
diff --git a/src/main/java/chocopy/common/astnodes/ReturnStmt.java b/src/main/java/chocopy/common/astnodes/ReturnStmt.java
new file mode 100644
index 0000000..f4751c7
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/ReturnStmt.java
@@ -0,0 +1,30 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Return from function.
+ */
+public class ReturnStmt extends Stmt {
+
+ /**
+ * Returned value.
+ */
+ public final Expr value;
+
+ /**
+ * The AST for
+ * return VALUE
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public ReturnStmt(Location left, Location right, Expr value) {
+ super(left, right);
+ this.value = value;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/Stmt.java b/src/main/java/chocopy/common/astnodes/Stmt.java
new file mode 100644
index 0000000..a2642fd
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/Stmt.java
@@ -0,0 +1,21 @@
+package chocopy.common.astnodes;
+
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Base of all AST nodes representing statements.
+ *
+ * There is nothing in this class, but there will be some AST
+ * node types that have fields that are *any statement* or a
+ * list of statements. For those cases, having a field of this type will
+ * encompass all types of statements such as expression statements,
+ * if statements, while statements, etc.
+ */
+public abstract class Stmt extends Node {
+ /**
+ * A statement spanning source locations [LEFT..RIGHT].
+ */
+ public Stmt(Location left, Location right) {
+ super(left, right);
+ }
+}
diff --git a/src/main/java/chocopy/common/astnodes/StringLiteral.java b/src/main/java/chocopy/common/astnodes/StringLiteral.java
new file mode 100644
index 0000000..5adb024
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/StringLiteral.java
@@ -0,0 +1,29 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * String constants.
+ */
+public final class StringLiteral extends Literal {
+
+ /**
+ * Contents of the literal, not including quotation marks.
+ */
+ public final String value;
+
+ /**
+ * The AST for a string literal containing VALUE, spanning source
+ * locations [LEFT..RIGHT].
+ */
+ public StringLiteral(Location left, Location right, String value) {
+ super(left, right);
+ this.value = value;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/TypeAnnotation.java b/src/main/java/chocopy/common/astnodes/TypeAnnotation.java
new file mode 100644
index 0000000..1002a86
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/TypeAnnotation.java
@@ -0,0 +1,16 @@
+package chocopy.common.astnodes;
+
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * Base of all AST nodes representing type annotations (list or class
+ * types.
+ */
+public abstract class TypeAnnotation extends Node {
+ /**
+ * An annotation spanning source locations [LEFT..RIGHT].
+ */
+ public TypeAnnotation(Location left, Location right) {
+ super(left, right);
+ }
+}
diff --git a/src/main/java/chocopy/common/astnodes/TypedVar.java b/src/main/java/chocopy/common/astnodes/TypedVar.java
new file mode 100644
index 0000000..7593775
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/TypedVar.java
@@ -0,0 +1,36 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * An identifier with attached type annotation.
+ */
+public class TypedVar extends Node {
+
+ /**
+ * The typed identifier.
+ */
+ public final Identifier identifier;
+ /**
+ * The declared type.
+ */
+ public final TypeAnnotation type;
+
+ /**
+ * The AST for
+ * IDENTIFIER : TYPE.
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public TypedVar(Location left, Location right,
+ Identifier identifier, TypeAnnotation type) {
+ super(left, right);
+ this.identifier = identifier;
+ this.type = type;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/UnaryExpr.java b/src/main/java/chocopy/common/astnodes/UnaryExpr.java
new file mode 100644
index 0000000..10ba57f
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/UnaryExpr.java
@@ -0,0 +1,36 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * An expression applying a unary operator.
+ */
+public class UnaryExpr extends Expr {
+
+ /**
+ * The text representation of the operator.
+ */
+ public final String operator;
+ /**
+ * The operand to which it is applied.
+ */
+ public final Expr operand;
+
+ /**
+ * The AST for
+ * OPERATOR OPERAND
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public UnaryExpr(Location left, Location right,
+ String operator, Expr operand) {
+ super(left, right);
+ this.operator = operator;
+ this.operand = operand;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/common/astnodes/VarDef.java b/src/main/java/chocopy/common/astnodes/VarDef.java
new file mode 100644
index 0000000..047b63b
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/VarDef.java
@@ -0,0 +1,42 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+/**
+ * A declaration of a variable (i.e., with type annotation).
+ */
+public class VarDef extends Declaration {
+ /**
+ * The variable and its assigned type.
+ */
+ public final TypedVar var;
+ /**
+ * The initial value assigned.
+ */
+ public final Literal value;
+
+ /**
+ * The AST for
+ * VAR = VALUE
+ * where VAR has a type annotation, and spanning source
+ * locations [LEFT..RIGHT].
+ */
+ public VarDef(Location left, Location right, TypedVar var, Literal value) {
+ super(left, right);
+ this.var = var;
+ this.value = value;
+ }
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+ /**
+ * The identifier defined by this declaration.
+ */
+ @Override
+ public Identifier getIdentifier() {
+ return this.var.identifier;
+ }
+}
diff --git a/src/main/java/chocopy/common/astnodes/WhileStmt.java b/src/main/java/chocopy/common/astnodes/WhileStmt.java
new file mode 100644
index 0000000..2936771
--- /dev/null
+++ b/src/main/java/chocopy/common/astnodes/WhileStmt.java
@@ -0,0 +1,39 @@
+package chocopy.common.astnodes;
+
+import chocopy.common.analysis.NodeAnalyzer;
+import java_cup.runtime.ComplexSymbolFactory.Location;
+
+import java.util.List;
+
+/**
+ * Indefinite repetition construct.
+ */
+public class WhileStmt extends Stmt {
+ /**
+ * Test for whether to continue.
+ */
+ public final Expr condition;
+ /**
+ * Loop body.
+ */
+ public final List body;
+
+ /**
+ * The AST for
+ * while CONDITION:
+ * BODY
+ * spanning source locations [LEFT..RIGHT].
+ */
+ public WhileStmt(Location left, Location right,
+ Expr condition, List body) {
+ super(left, right);
+ this.condition = condition;
+ this.body = body;
+ }
+
+
+ public T dispatch(NodeAnalyzer analyzer) {
+ return analyzer.analyze(this);
+ }
+
+}
diff --git a/src/main/java/chocopy/pa1/StudentParser.java b/src/main/java/chocopy/pa1/StudentParser.java
new file mode 100644
index 0000000..c29db68
--- /dev/null
+++ b/src/main/java/chocopy/pa1/StudentParser.java
@@ -0,0 +1,25 @@
+package chocopy.pa1;
+
+import chocopy.common.astnodes.Program;
+import java_cup.runtime.ComplexSymbolFactory;
+
+import java.io.StringReader;
+
+/**
+ * Interface between driver and parser.
+ */
+public class StudentParser {
+
+ /**
+ * Return the Program AST resulting from parsing INPUT. Turn on
+ * parser debugging iff DEBUG.
+ */
+ public static Program process(String input, boolean debug) {
+ ChocoPyLexer lexer = new ChocoPyLexer(new StringReader(input));
+ ChocoPyParser parser =
+ new ChocoPyParser(lexer, new ComplexSymbolFactory());
+ return parser.parseProgram(debug);
+ }
+}
+
+
diff --git a/src/main/jflex/chocopy/pa1/ChocoPy.jflex b/src/main/jflex/chocopy/pa1/ChocoPy.jflex
new file mode 100644
index 0000000..9aafe7f
--- /dev/null
+++ b/src/main/jflex/chocopy/pa1/ChocoPy.jflex
@@ -0,0 +1,82 @@
+package chocopy.pa1;
+import java_cup.runtime.*;
+
+%%
+
+/*** Do not change the flags below unless you know what you are doing. ***/
+
+%unicode
+%line
+%column
+
+%class ChocoPyLexer
+%public
+
+%cupsym ChocoPyTokens
+%cup
+%cupdebug
+
+%eofclose false
+
+/*** Do not change the flags above unless you know what you are doing. ***/
+
+/* The following code section is copied verbatim to the
+ * generated lexer class. */
+%{
+ /* The code below includes some convenience methods to create tokens
+ * of a given type and optionally a value that the CUP parser can
+ * understand. Specifically, a lot of the logic below deals with
+ * embedded information about where in the source code a given token
+ * was recognized, so that the parser can report errors accurately.
+ * (It need not be modified for this project.) */
+
+ /** Producer of token-related values for the parser. */
+ final ComplexSymbolFactory symbolFactory = new ComplexSymbolFactory();
+
+ /** Return a terminal symbol of syntactic category TYPE and no
+ * semantic value at the current source location. */
+ private Symbol symbol(int type) {
+ return symbol(type, yytext());
+ }
+
+ /** Return a terminal symbol of syntactic category TYPE and semantic
+ * value VALUE at the current source location. */
+ private Symbol symbol(int type, Object value) {
+ return symbolFactory.newSymbol(ChocoPyTokens.terminalNames[type], type,
+ new ComplexSymbolFactory.Location(yyline + 1, yycolumn + 1),
+ new ComplexSymbolFactory.Location(yyline + 1,yycolumn + yylength()),
+ value);
+ }
+
+%}
+
+/* Macros (regexes used in rules below) */
+
+WhiteSpace = [ \t]
+LineBreak = \r|\n|\r\n
+
+IntegerLiteral = 0 | [1-9][0-9]*
+
+%%
+
+
+ {
+
+ /* Delimiters. */
+ {LineBreak} { return symbol(ChocoPyTokens.NEWLINE); }
+
+ /* Literals. */
+ {IntegerLiteral} { return symbol(ChocoPyTokens.NUMBER,
+ Integer.parseInt(yytext())); }
+
+ /* Operators. */
+ "+" { return symbol(ChocoPyTokens.PLUS, yytext()); }
+
+ /* Whitespace. */
+ {WhiteSpace} { /* ignore */ }
+}
+
+<> { return symbol(ChocoPyTokens.EOF); }
+
+/* Error fallback. */
+[^] { return symbol(ChocoPyTokens.UNRECOGNIZED); }
diff --git a/src/test/data/pa1/sample/bad_assign_expr1.py b/src/test/data/pa1/sample/bad_assign_expr1.py
new file mode 100644
index 0000000..ccc8c3e
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_assign_expr1.py
@@ -0,0 +1 @@
+x = (y = 2)
diff --git a/src/test/data/pa1/sample/bad_assign_expr1.py.ast b/src/test/data/pa1/sample/bad_assign_expr1.py.ast
new file mode 100644
index 0000000..d134770
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_assign_expr1.py.ast
@@ -0,0 +1,16 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 6, 1, 6 ],
+ "declarations" : [ ],
+ "statements" : [ ],
+ "errors" : {
+ "errors" : [ {
+ "kind" : "CompilerError",
+ "location" : [ 1, 8, 1, 8 ],
+ "message" : "Parse error near token EQ: =",
+ "syntax" : true
+ } ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/bad_assign_expr2.py b/src/test/data/pa1/sample/bad_assign_expr2.py
new file mode 100644
index 0000000..444bc53
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_assign_expr2.py
@@ -0,0 +1 @@
+print(x = 1)
diff --git a/src/test/data/pa1/sample/bad_assign_expr2.py.ast b/src/test/data/pa1/sample/bad_assign_expr2.py.ast
new file mode 100644
index 0000000..53e699c
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_assign_expr2.py.ast
@@ -0,0 +1,16 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 7, 1, 7 ],
+ "declarations" : [ ],
+ "statements" : [ ],
+ "errors" : {
+ "errors" : [ {
+ "kind" : "CompilerError",
+ "location" : [ 1, 9, 1, 9 ],
+ "message" : "Parse error near token EQ: =",
+ "syntax" : true
+ } ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/bad_func_def.py b/src/test/data/pa1/sample/bad_func_def.py
new file mode 100644
index 0000000..ebd2373
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_func_def.py
@@ -0,0 +1,6 @@
+def foo(a, b) -> 1:
+ x:int = a
+ return 1
+
+print(1)
+print(3**6)
diff --git a/src/test/data/pa1/sample/bad_func_def.py.ast b/src/test/data/pa1/sample/bad_func_def.py.ast
new file mode 100644
index 0000000..934bef0
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_func_def.py.ast
@@ -0,0 +1,64 @@
+{
+ "kind" : "Program",
+ "location" : [ 2, 13, 6, 8 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 2, 13, 2, 13 ],
+ "expr" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 13, 2, 13 ],
+ "name" : "a"
+ }
+ }, {
+ "kind" : "ReturnStmt",
+ "location" : [ 3, 5, 3, 12 ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 12, 3, 12 ],
+ "value" : 1
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 5, 1, 5, 8 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 5, 1, 5, 8 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 1, 5, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 5, 7, 5, 7 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ {
+ "kind" : "CompilerError",
+ "location" : [ 1, 10, 1, 10 ],
+ "message" : "Parse error near token COMMA: ,",
+ "syntax" : true
+ }, {
+ "kind" : "CompilerError",
+ "location" : [ 2, 13, 2, 13 ],
+ "message" : "Parse error near token IDENTIFIER: a",
+ "syntax" : true
+ }, {
+ "kind" : "CompilerError",
+ "location" : [ 5, 1, 5, 0 ],
+ "message" : "Parse error near token DEDENT: ",
+ "syntax" : true
+ }, {
+ "kind" : "CompilerError",
+ "location" : [ 6, 9, 6, 9 ],
+ "message" : "Parse error near token TIMES: *",
+ "syntax" : true
+ } ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/bad_indentation.py b/src/test/data/pa1/sample/bad_indentation.py
new file mode 100644
index 0000000..670b7ab
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_indentation.py
@@ -0,0 +1,3 @@
+x = 1
+ y = 2
+z = 3
diff --git a/src/test/data/pa1/sample/bad_indentation.py.ast b/src/test/data/pa1/sample/bad_indentation.py.ast
new file mode 100644
index 0000000..f37b92e
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_indentation.py.ast
@@ -0,0 +1,47 @@
+{
+ "kind" : "Program",
+ "location" : [ 2, 3, 3, 6 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 2, 3, 2, 7 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 2, 3, 2, 3 ],
+ "name" : "y"
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 7, 2, 7 ],
+ "value" : 2
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 3, 1, 3, 5 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 3, 1, 3, 1 ],
+ "name" : "z"
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 5, 3, 5 ],
+ "value" : 3
+ }
+ } ],
+ "errors" : {
+ "errors" : [ {
+ "kind" : "CompilerError",
+ "location" : [ 2, 1, 2, 2 ],
+ "message" : "Parse error near token INDENT: ",
+ "syntax" : true
+ }, {
+ "kind" : "CompilerError",
+ "location" : [ 3, 1, 3, 0 ],
+ "message" : "Parse error near token DEDENT: ",
+ "syntax" : true
+ } ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/bad_stmt.py b/src/test/data/pa1/sample/bad_stmt.py
new file mode 100644
index 0000000..8e8a4da
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_stmt.py
@@ -0,0 +1,4 @@
+1 + 2
+3 == 4 or (not False && True)
+5 + 6
+7 << 8
diff --git a/src/test/data/pa1/sample/bad_stmt.py.ast b/src/test/data/pa1/sample/bad_stmt.py.ast
new file mode 100644
index 0000000..afe9602
--- /dev/null
+++ b/src/test/data/pa1/sample/bad_stmt.py.ast
@@ -0,0 +1,65 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 7 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 5 ],
+ "expr" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 1, 1, 5 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 1, 1, 1 ],
+ "value" : 1
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 5, 1, 5 ],
+ "value" : 2
+ }
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 3, 1, 3, 5 ],
+ "expr" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 3, 1, 3, 5 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 1, 3, 1 ],
+ "value" : 5
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 5, 3, 5 ],
+ "value" : 6
+ }
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 6, 4, 6 ],
+ "expr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 6, 4, 6 ],
+ "value" : 8
+ }
+ } ],
+ "errors" : {
+ "errors" : [ {
+ "kind" : "CompilerError",
+ "location" : [ 2, 22, 2, 22 ],
+ "message" : "Parse error near token UNRECOGNIZED: &",
+ "syntax" : true
+ }, {
+ "kind" : "CompilerError",
+ "location" : [ 4, 4, 4, 4 ],
+ "message" : "Parse error near token LT: <",
+ "syntax" : true
+ } ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/chained_mixed_assignments.py b/src/test/data/pa1/sample/chained_mixed_assignments.py
new file mode 100644
index 0000000..46a230a
--- /dev/null
+++ b/src/test/data/pa1/sample/chained_mixed_assignments.py
@@ -0,0 +1,2 @@
+x[0] = y = z.f = 1
+z.g = y = x[0]
diff --git a/src/test/data/pa1/sample/chained_mixed_assignments.py.ast b/src/test/data/pa1/sample/chained_mixed_assignments.py.ast
new file mode 100644
index 0000000..9654bf6
--- /dev/null
+++ b/src/test/data/pa1/sample/chained_mixed_assignments.py.ast
@@ -0,0 +1,85 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 2, 15 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 1, 1, 1, 18 ],
+ "targets" : [ {
+ "kind" : "IndexExpr",
+ "location" : [ 1, 1, 1, 4 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "x"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 3, 1, 3 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "Identifier",
+ "location" : [ 1, 8, 1, 8 ],
+ "name" : "y"
+ }, {
+ "kind" : "MemberExpr",
+ "location" : [ 1, 12, 1, 14 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 12, 1, 12 ],
+ "name" : "z"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 14, 1, 14 ],
+ "name" : "f"
+ }
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 18, 1, 18 ],
+ "value" : 1
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 2, 1, 2, 14 ],
+ "targets" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 2, 1, 2, 3 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 1, 2, 1 ],
+ "name" : "z"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 3, 2, 3 ],
+ "name" : "g"
+ }
+ }, {
+ "kind" : "Identifier",
+ "location" : [ 2, 7, 2, 7 ],
+ "name" : "y"
+ } ],
+ "value" : {
+ "kind" : "IndexExpr",
+ "location" : [ 2, 11, 2, 14 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 11, 2, 11 ],
+ "name" : "x"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 13, 2, 13 ],
+ "value" : 0
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/chained_var_assignments.py b/src/test/data/pa1/sample/chained_var_assignments.py
new file mode 100644
index 0000000..b253c2a
--- /dev/null
+++ b/src/test/data/pa1/sample/chained_var_assignments.py
@@ -0,0 +1 @@
+x = y = z = 1
diff --git a/src/test/data/pa1/sample/chained_var_assignments.py.ast b/src/test/data/pa1/sample/chained_var_assignments.py.ast
new file mode 100644
index 0000000..28f0ea7
--- /dev/null
+++ b/src/test/data/pa1/sample/chained_var_assignments.py.ast
@@ -0,0 +1,32 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 14 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 1, 1, 1, 13 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "x"
+ }, {
+ "kind" : "Identifier",
+ "location" : [ 1, 5, 1, 5 ],
+ "name" : "y"
+ }, {
+ "kind" : "Identifier",
+ "location" : [ 1, 9, 1, 9 ],
+ "name" : "z"
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 13, 1, 13 ],
+ "value" : 1
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/class_attr.py b/src/test/data/pa1/sample/class_attr.py
new file mode 100644
index 0000000..bb1e1cd
--- /dev/null
+++ b/src/test/data/pa1/sample/class_attr.py
@@ -0,0 +1,4 @@
+class Foo(object):
+ x:int = 1
+
+f = Foo()
diff --git a/src/test/data/pa1/sample/class_attr.py.ast b/src/test/data/pa1/sample/class_attr.py.ast
new file mode 100644
index 0000000..4fdab40
--- /dev/null
+++ b/src/test/data/pa1/sample/class_attr.py.ast
@@ -0,0 +1,65 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 10 ],
+ "declarations" : [ {
+ "kind" : "ClassDef",
+ "location" : [ 1, 1, 2, 14 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 7, 1, 9 ],
+ "name" : "Foo"
+ },
+ "superClass" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 11, 1, 16 ],
+ "name" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 2, 5, 2, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 2, 5, 2, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 5 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 7, 2, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 13, 2, 13 ],
+ "value" : 1
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 4, 1, 4, 9 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 4, 1, 4, 1 ],
+ "name" : "f"
+ } ],
+ "value" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 5, 4, 9 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 7 ],
+ "name" : "Foo"
+ },
+ "args" : [ ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/class_attr_get.py b/src/test/data/pa1/sample/class_attr_get.py
new file mode 100644
index 0000000..b4e6365
--- /dev/null
+++ b/src/test/data/pa1/sample/class_attr_get.py
@@ -0,0 +1,5 @@
+class Foo(object):
+ x:int = 1
+
+f = Foo()
+print(f.x)
diff --git a/src/test/data/pa1/sample/class_attr_get.py.ast b/src/test/data/pa1/sample/class_attr_get.py.ast
new file mode 100644
index 0000000..f286342
--- /dev/null
+++ b/src/test/data/pa1/sample/class_attr_get.py.ast
@@ -0,0 +1,91 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 5, 11 ],
+ "declarations" : [ {
+ "kind" : "ClassDef",
+ "location" : [ 1, 1, 2, 14 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 7, 1, 9 ],
+ "name" : "Foo"
+ },
+ "superClass" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 11, 1, 16 ],
+ "name" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 2, 5, 2, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 2, 5, 2, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 5 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 7, 2, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 13, 2, 13 ],
+ "value" : 1
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 4, 1, 4, 9 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 4, 1, 4, 1 ],
+ "name" : "f"
+ } ],
+ "value" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 5, 4, 9 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 7 ],
+ "name" : "Foo"
+ },
+ "args" : [ ]
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 5, 1, 5, 10 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 5, 1, 5, 10 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 1, 5, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 5, 7, 5, 9 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 7, 5, 7 ],
+ "name" : "f"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 9, 5, 9 ],
+ "name" : "x"
+ }
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/class_attr_set.py b/src/test/data/pa1/sample/class_attr_set.py
new file mode 100644
index 0000000..ac94bf8
--- /dev/null
+++ b/src/test/data/pa1/sample/class_attr_set.py
@@ -0,0 +1,5 @@
+class Foo(object):
+ x:int = 1
+
+f = Foo()
+f.x = 2
diff --git a/src/test/data/pa1/sample/class_attr_set.py.ast b/src/test/data/pa1/sample/class_attr_set.py.ast
new file mode 100644
index 0000000..03d6bba
--- /dev/null
+++ b/src/test/data/pa1/sample/class_attr_set.py.ast
@@ -0,0 +1,87 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 5, 8 ],
+ "declarations" : [ {
+ "kind" : "ClassDef",
+ "location" : [ 1, 1, 2, 14 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 7, 1, 9 ],
+ "name" : "Foo"
+ },
+ "superClass" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 11, 1, 16 ],
+ "name" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 2, 5, 2, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 2, 5, 2, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 5 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 7, 2, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 13, 2, 13 ],
+ "value" : 1
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 4, 1, 4, 9 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 4, 1, 4, 1 ],
+ "name" : "f"
+ } ],
+ "value" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 5, 4, 9 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 7 ],
+ "name" : "Foo"
+ },
+ "args" : [ ]
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 5, 1, 5, 7 ],
+ "targets" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 5, 1, 5, 3 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 1, 5, 1 ],
+ "name" : "f"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 3, 5, 3 ],
+ "name" : "x"
+ }
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 5, 7, 5, 7 ],
+ "value" : 2
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/class_constructor.py b/src/test/data/pa1/sample/class_constructor.py
new file mode 100644
index 0000000..46d7ccb
--- /dev/null
+++ b/src/test/data/pa1/sample/class_constructor.py
@@ -0,0 +1,8 @@
+class Foo(object):
+ x:int = 0
+
+ def __init__(self:"Foo", x:int):
+ self.x = x
+
+f = Foo(1)
+print(f.x)
diff --git a/src/test/data/pa1/sample/class_constructor.py.ast b/src/test/data/pa1/sample/class_constructor.py.ast
new file mode 100644
index 0000000..6850e03
--- /dev/null
+++ b/src/test/data/pa1/sample/class_constructor.py.ast
@@ -0,0 +1,159 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 8, 11 ],
+ "declarations" : [ {
+ "kind" : "ClassDef",
+ "location" : [ 1, 1, 7, 0 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 7, 1, 9 ],
+ "name" : "Foo"
+ },
+ "superClass" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 11, 1, 16 ],
+ "name" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 2, 5, 2, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 2, 5, 2, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 5 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 7, 2, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 13, 2, 13 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 4, 5, 5, 19 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 9, 4, 16 ],
+ "name" : "__init__"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 4, 18, 4, 27 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 18, 4, 21 ],
+ "name" : "self"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 23, 4, 27 ],
+ "className" : "Foo"
+ }
+ }, {
+ "kind" : "TypedVar",
+ "location" : [ 4, 30, 4, 34 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 30, 4, 30 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 32, 4, 34 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 36, 4, 36 ],
+ "className" : ""
+ },
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 5, 9, 5, 18 ],
+ "targets" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 5, 9, 5, 14 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 9, 5, 12 ],
+ "name" : "self"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 14, 5, 14 ],
+ "name" : "x"
+ }
+ } ],
+ "value" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 18, 5, 18 ],
+ "name" : "x"
+ }
+ } ]
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 7, 1, 7, 10 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 7, 1, 7, 1 ],
+ "name" : "f"
+ } ],
+ "value" : {
+ "kind" : "CallExpr",
+ "location" : [ 7, 5, 7, 10 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 7, 5, 7, 7 ],
+ "name" : "Foo"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 7, 9, 7, 9 ],
+ "value" : 1
+ } ]
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 8, 1, 8, 10 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 8, 1, 8, 10 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 1, 8, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 8, 7, 8, 9 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 7, 8, 7 ],
+ "name" : "f"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 9, 8, 9 ],
+ "name" : "x"
+ }
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/class_method.py b/src/test/data/pa1/sample/class_method.py
new file mode 100644
index 0000000..cc03ce2
--- /dev/null
+++ b/src/test/data/pa1/sample/class_method.py
@@ -0,0 +1,9 @@
+class Foo(object):
+ x:int = 0
+
+ def set(self:"Foo", x:int) -> object:
+ self.x = x
+
+f = Foo()
+f.set(1)
+print(f.x)
diff --git a/src/test/data/pa1/sample/class_method.py.ast b/src/test/data/pa1/sample/class_method.py.ast
new file mode 100644
index 0000000..66bc2e1
--- /dev/null
+++ b/src/test/data/pa1/sample/class_method.py.ast
@@ -0,0 +1,181 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 9, 11 ],
+ "declarations" : [ {
+ "kind" : "ClassDef",
+ "location" : [ 1, 1, 7, 0 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 7, 1, 9 ],
+ "name" : "Foo"
+ },
+ "superClass" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 11, 1, 16 ],
+ "name" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 2, 5, 2, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 2, 5, 2, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 5 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 7, 2, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 13, 2, 13 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 4, 5, 5, 19 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 9, 4, 11 ],
+ "name" : "set"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 4, 13, 4, 22 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 13, 4, 16 ],
+ "name" : "self"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 18, 4, 22 ],
+ "className" : "Foo"
+ }
+ }, {
+ "kind" : "TypedVar",
+ "location" : [ 4, 25, 4, 29 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 25, 4, 25 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 27, 4, 29 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 35, 4, 40 ],
+ "className" : "object"
+ },
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 5, 9, 5, 18 ],
+ "targets" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 5, 9, 5, 14 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 9, 5, 12 ],
+ "name" : "self"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 14, 5, 14 ],
+ "name" : "x"
+ }
+ } ],
+ "value" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 18, 5, 18 ],
+ "name" : "x"
+ }
+ } ]
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 7, 1, 7, 9 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 7, 1, 7, 1 ],
+ "name" : "f"
+ } ],
+ "value" : {
+ "kind" : "CallExpr",
+ "location" : [ 7, 5, 7, 9 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 7, 5, 7, 7 ],
+ "name" : "Foo"
+ },
+ "args" : [ ]
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 8, 1, 8, 8 ],
+ "expr" : {
+ "kind" : "MethodCallExpr",
+ "location" : [ 8, 1, 8, 8 ],
+ "method" : {
+ "kind" : "MemberExpr",
+ "location" : [ 8, 1, 8, 5 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 1, 8, 1 ],
+ "name" : "f"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 3, 8, 5 ],
+ "name" : "set"
+ }
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 8, 7, 8, 7 ],
+ "value" : 1
+ } ]
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 9, 1, 9, 10 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 9, 1, 9, 10 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 1, 9, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 9, 7, 9, 9 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 7, 9, 7 ],
+ "name" : "f"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 9, 9, 9 ],
+ "name" : "x"
+ }
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/coverage.py b/src/test/data/pa1/sample/coverage.py
new file mode 100644
index 0000000..1da3446
--- /dev/null
+++ b/src/test/data/pa1/sample/coverage.py
@@ -0,0 +1,38 @@
+count:int = 0
+
+def foo(s: str) -> int:
+ return len(s)
+
+class bar(object):
+ p: bool = True
+
+ def baz(self:"bar", xx: [int]) -> str:
+ global count
+ x:int = 0
+ y:int = 1
+
+ def qux(y: int) -> object:
+ nonlocal x
+ if x > y:
+ x = -1
+
+ for x in xx:
+ self.p = x == 2
+
+ qux(0) # Yay! ChocoPy
+
+ count = count + 1
+
+ while x <= 0:
+ if self.p:
+ xx[0] = xx[1]
+ self.p = not self.p
+ x = x + 1
+ elif foo("Long"[0]) == 1:
+ return self is None
+
+ return "Nope"
+
+print(bar().baz([1,2]))
+
+
diff --git a/src/test/data/pa1/sample/coverage.py.ast b/src/test/data/pa1/sample/coverage.py.ast
new file mode 100644
index 0000000..c7bab9f
--- /dev/null
+++ b/src/test/data/pa1/sample/coverage.py.ast
@@ -0,0 +1,613 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 36, 24 ],
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 1, 1, 1, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 1, 1, 1, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 5 ],
+ "name" : "count"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 7, 1, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 13, 1, 13 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 3, 1, 4, 18 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 5, 3, 7 ],
+ "name" : "foo"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 3, 9, 3, 14 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 9, 3, 9 ],
+ "name" : "s"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 3, 12, 3, 14 ],
+ "className" : "str"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 3, 20, 3, 22 ],
+ "className" : "int"
+ },
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 4, 5, 4, 17 ],
+ "value" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 12, 4, 17 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 12, 4, 14 ],
+ "name" : "len"
+ },
+ "args" : [ {
+ "kind" : "Identifier",
+ "location" : [ 4, 16, 4, 16 ],
+ "name" : "s"
+ } ]
+ }
+ } ]
+ }, {
+ "kind" : "ClassDef",
+ "location" : [ 6, 1, 36, 0 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 6, 7, 6, 9 ],
+ "name" : "bar"
+ },
+ "superClass" : {
+ "kind" : "Identifier",
+ "location" : [ 6, 11, 6, 16 ],
+ "name" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 7, 5, 7, 18 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 7, 5, 7, 11 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 7, 5, 7, 5 ],
+ "name" : "p"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 7, 8, 7, 11 ],
+ "className" : "bool"
+ }
+ },
+ "value" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 7, 15, 7, 18 ],
+ "value" : true
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 9, 5, 34, 22 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 9, 9, 11 ],
+ "name" : "baz"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 9, 13, 9, 22 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 13, 9, 16 ],
+ "name" : "self"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 9, 18, 9, 22 ],
+ "className" : "bar"
+ }
+ }, {
+ "kind" : "TypedVar",
+ "location" : [ 9, 25, 9, 33 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 25, 9, 26 ],
+ "name" : "xx"
+ },
+ "type" : {
+ "kind" : "ListType",
+ "location" : [ 9, 29, 9, 33 ],
+ "elementType" : {
+ "kind" : "ClassType",
+ "location" : [ 9, 30, 9, 32 ],
+ "className" : "int"
+ }
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 9, 39, 9, 41 ],
+ "className" : "str"
+ },
+ "declarations" : [ {
+ "kind" : "GlobalDecl",
+ "location" : [ 10, 9, 10, 20 ],
+ "variable" : {
+ "kind" : "Identifier",
+ "location" : [ 10, 16, 10, 20 ],
+ "name" : "count"
+ }
+ }, {
+ "kind" : "VarDef",
+ "location" : [ 11, 9, 11, 17 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 11, 9, 11, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 11, 9, 11, 9 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 11, 11, 11, 13 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 11, 17, 11, 17 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "VarDef",
+ "location" : [ 12, 9, 12, 17 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 12, 9, 12, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 12, 9, 12, 9 ],
+ "name" : "y"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 12, 11, 12, 13 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 12, 17, 12, 17 ],
+ "value" : 1
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 14, 9, 19, 8 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 14, 13, 14, 15 ],
+ "name" : "qux"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 14, 17, 14, 22 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 14, 17, 14, 17 ],
+ "name" : "y"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 14, 20, 14, 22 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 14, 28, 14, 33 ],
+ "className" : "object"
+ },
+ "declarations" : [ {
+ "kind" : "NonLocalDecl",
+ "location" : [ 15, 13, 15, 22 ],
+ "variable" : {
+ "kind" : "Identifier",
+ "location" : [ 15, 22, 15, 22 ],
+ "name" : "x"
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 16, 13, 19, 8 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 16, 16, 16, 20 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 16, 16, 16, 16 ],
+ "name" : "x"
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "Identifier",
+ "location" : [ 16, 20, 16, 20 ],
+ "name" : "y"
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 17, 17, 17, 22 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 17, 17, 17, 17 ],
+ "name" : "x"
+ } ],
+ "value" : {
+ "kind" : "UnaryExpr",
+ "location" : [ 17, 21, 17, 22 ],
+ "operator" : "-",
+ "operand" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 17, 22, 17, 22 ],
+ "value" : 1
+ }
+ }
+ } ],
+ "elseBody" : [ ]
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ForStmt",
+ "location" : [ 19, 9, 22, 8 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 19, 13, 19, 13 ],
+ "name" : "x"
+ },
+ "iterable" : {
+ "kind" : "Identifier",
+ "location" : [ 19, 18, 19, 19 ],
+ "name" : "xx"
+ },
+ "body" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 20, 13, 20, 27 ],
+ "targets" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 20, 13, 20, 18 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 20, 13, 20, 16 ],
+ "name" : "self"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 20, 18, 20, 18 ],
+ "name" : "p"
+ }
+ } ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 20, 22, 20, 27 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 20, 22, 20, 22 ],
+ "name" : "x"
+ },
+ "operator" : "==",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 20, 27, 20, 27 ],
+ "value" : 2
+ }
+ }
+ } ]
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 22, 9, 22, 14 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 22, 9, 22, 14 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 22, 9, 22, 11 ],
+ "name" : "qux"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 22, 13, 22, 13 ],
+ "value" : 0
+ } ]
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 24, 9, 24, 25 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 24, 9, 24, 13 ],
+ "name" : "count"
+ } ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 24, 17, 24, 25 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 24, 17, 24, 21 ],
+ "name" : "count"
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 24, 25, 24, 25 ],
+ "value" : 1
+ }
+ }
+ }, {
+ "kind" : "WhileStmt",
+ "location" : [ 26, 9, 34, 8 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 26, 15, 26, 20 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 26, 15, 26, 15 ],
+ "name" : "x"
+ },
+ "operator" : "<=",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 26, 20, 26, 20 ],
+ "value" : 0
+ }
+ },
+ "body" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 27, 13, 34, 8 ],
+ "condition" : {
+ "kind" : "MemberExpr",
+ "location" : [ 27, 16, 27, 21 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 27, 16, 27, 19 ],
+ "name" : "self"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 27, 21, 27, 21 ],
+ "name" : "p"
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 28, 17, 28, 29 ],
+ "targets" : [ {
+ "kind" : "IndexExpr",
+ "location" : [ 28, 17, 28, 21 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 28, 17, 28, 18 ],
+ "name" : "xx"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 28, 20, 28, 20 ],
+ "value" : 0
+ }
+ } ],
+ "value" : {
+ "kind" : "IndexExpr",
+ "location" : [ 28, 25, 28, 29 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 28, 25, 28, 26 ],
+ "name" : "xx"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 28, 28, 28, 28 ],
+ "value" : 1
+ }
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 29, 17, 29, 35 ],
+ "targets" : [ {
+ "kind" : "MemberExpr",
+ "location" : [ 29, 17, 29, 22 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 29, 17, 29, 20 ],
+ "name" : "self"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 29, 22, 29, 22 ],
+ "name" : "p"
+ }
+ } ],
+ "value" : {
+ "kind" : "UnaryExpr",
+ "location" : [ 29, 26, 29, 35 ],
+ "operator" : "not",
+ "operand" : {
+ "kind" : "MemberExpr",
+ "location" : [ 29, 30, 29, 35 ],
+ "object" : {
+ "kind" : "Identifier",
+ "location" : [ 29, 30, 29, 33 ],
+ "name" : "self"
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 29, 35, 29, 35 ],
+ "name" : "p"
+ }
+ }
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 30, 17, 30, 25 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 30, 17, 30, 17 ],
+ "name" : "x"
+ } ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 30, 21, 30, 25 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 30, 21, 30, 21 ],
+ "name" : "x"
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 30, 25, 30, 25 ],
+ "value" : 1
+ }
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 31, 13, 34, 8 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 31, 18, 31, 36 ],
+ "left" : {
+ "kind" : "CallExpr",
+ "location" : [ 31, 18, 31, 31 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 31, 18, 31, 20 ],
+ "name" : "foo"
+ },
+ "args" : [ {
+ "kind" : "IndexExpr",
+ "location" : [ 31, 22, 31, 30 ],
+ "list" : {
+ "kind" : "StringLiteral",
+ "location" : [ 31, 22, 31, 27 ],
+ "value" : "Long"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 31, 29, 31, 29 ],
+ "value" : 0
+ }
+ } ]
+ },
+ "operator" : "==",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 31, 36, 31, 36 ],
+ "value" : 1
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 32, 17, 32, 35 ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 32, 24, 32, 35 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 32, 24, 32, 27 ],
+ "name" : "self"
+ },
+ "operator" : "is",
+ "right" : {
+ "kind" : "NoneLiteral",
+ "location" : [ 32, 32, 32, 35 ]
+ }
+ }
+ } ],
+ "elseBody" : [ ]
+ } ]
+ } ]
+ }, {
+ "kind" : "ReturnStmt",
+ "location" : [ 34, 9, 34, 21 ],
+ "value" : {
+ "kind" : "StringLiteral",
+ "location" : [ 34, 16, 34, 21 ],
+ "value" : "Nope"
+ }
+ } ]
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 36, 1, 36, 23 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 36, 1, 36, 23 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 36, 1, 36, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "MethodCallExpr",
+ "location" : [ 36, 7, 36, 22 ],
+ "method" : {
+ "kind" : "MemberExpr",
+ "location" : [ 36, 7, 36, 15 ],
+ "object" : {
+ "kind" : "CallExpr",
+ "location" : [ 36, 7, 36, 11 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 36, 7, 36, 9 ],
+ "name" : "bar"
+ },
+ "args" : [ ]
+ },
+ "member" : {
+ "kind" : "Identifier",
+ "location" : [ 36, 13, 36, 15 ],
+ "name" : "baz"
+ }
+ },
+ "args" : [ {
+ "kind" : "ListExpr",
+ "location" : [ 36, 17, 36, 21 ],
+ "elements" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 36, 18, 36, 18 ],
+ "value" : 1
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 36, 20, 36, 20 ],
+ "value" : 2
+ } ]
+ } ]
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/def_func.py b/src/test/data/pa1/sample/def_func.py
new file mode 100644
index 0000000..55e9c43
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func.py
@@ -0,0 +1,4 @@
+def foo() -> int:
+ return 1
+
+foo()
diff --git a/src/test/data/pa1/sample/def_func.py.ast b/src/test/data/pa1/sample/def_func.py.ast
new file mode 100644
index 0000000..00a7e65
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func.py.ast
@@ -0,0 +1,48 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 6 ],
+ "declarations" : [ {
+ "kind" : "FuncDef",
+ "location" : [ 1, 1, 2, 13 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 5, 1, 7 ],
+ "name" : "foo"
+ },
+ "params" : [ ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 14, 1, 16 ],
+ "className" : "int"
+ },
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 2, 5, 2, 12 ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 12, 2, 12 ],
+ "value" : 1
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 1, 4, 5 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 1, 4, 5 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 1, 4, 3 ],
+ "name" : "foo"
+ },
+ "args" : [ ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/def_func_args.py b/src/test/data/pa1/sample/def_func_args.py
new file mode 100644
index 0000000..196f504
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_args.py
@@ -0,0 +1,4 @@
+def foo(x:int, y:int) -> bool:
+ return x > y
+
+foo(1,2)
diff --git a/src/test/data/pa1/sample/def_func_args.py.ast b/src/test/data/pa1/sample/def_func_args.py.ast
new file mode 100644
index 0000000..77d9dc9
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_args.py.ast
@@ -0,0 +1,92 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 9 ],
+ "declarations" : [ {
+ "kind" : "FuncDef",
+ "location" : [ 1, 1, 2, 17 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 5, 1, 7 ],
+ "name" : "foo"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 1, 9, 1, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 9, 1, 9 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 11, 1, 13 ],
+ "className" : "int"
+ }
+ }, {
+ "kind" : "TypedVar",
+ "location" : [ 1, 16, 1, 20 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 16, 1, 16 ],
+ "name" : "y"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 18, 1, 20 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 26, 1, 29 ],
+ "className" : "bool"
+ },
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 2, 5, 2, 16 ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 2, 12, 2, 16 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 12, 2, 12 ],
+ "name" : "x"
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 16, 2, 16 ],
+ "name" : "y"
+ }
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 1, 4, 8 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 1, 4, 8 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 1, 4, 3 ],
+ "name" : "foo"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 5, 4, 5 ],
+ "value" : 1
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 7, 4, 7 ],
+ "value" : 2
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/def_func_global.py b/src/test/data/pa1/sample/def_func_global.py
new file mode 100644
index 0000000..12f9dfc
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_global.py
@@ -0,0 +1,7 @@
+z:int = 0
+
+def foo(x:int) -> bool:
+ global z
+ return x > z
+
+foo(1)
diff --git a/src/test/data/pa1/sample/def_func_global.py.ast b/src/test/data/pa1/sample/def_func_global.py.ast
new file mode 100644
index 0000000..736af77
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_global.py.ast
@@ -0,0 +1,105 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 7, 7 ],
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 1, 1, 1, 9 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 1, 1, 1, 5 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "z"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 3, 1, 5 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 9, 1, 9 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 3, 1, 5, 17 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 5, 3, 7 ],
+ "name" : "foo"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 3, 9, 3, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 9, 3, 9 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 3, 11, 3, 13 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 3, 19, 3, 22 ],
+ "className" : "bool"
+ },
+ "declarations" : [ {
+ "kind" : "GlobalDecl",
+ "location" : [ 4, 5, 4, 12 ],
+ "variable" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 12, 4, 12 ],
+ "name" : "z"
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 5, 5, 5, 16 ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 5, 12, 5, 16 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 12, 5, 12 ],
+ "name" : "x"
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 16, 5, 16 ],
+ "name" : "z"
+ }
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 7, 1, 7, 6 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 7, 1, 7, 6 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 7, 1, 7, 3 ],
+ "name" : "foo"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 7, 5, 7, 5 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/def_func_nested.py b/src/test/data/pa1/sample/def_func_nested.py
new file mode 100644
index 0000000..835614e
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_nested.py
@@ -0,0 +1,10 @@
+
+def foo(x:int) -> bool:
+ a:int = 0
+ b:int = 1
+ def bar(y: int) -> int:
+ a:int = 2
+ return y
+ return bar(x) > a
+
+foo(1)
diff --git a/src/test/data/pa1/sample/def_func_nested.py.ast b/src/test/data/pa1/sample/def_func_nested.py.ast
new file mode 100644
index 0000000..0024178
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_nested.py.ast
@@ -0,0 +1,187 @@
+{
+ "kind" : "Program",
+ "location" : [ 2, 1, 10, 7 ],
+ "declarations" : [ {
+ "kind" : "FuncDef",
+ "location" : [ 2, 1, 8, 22 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 7 ],
+ "name" : "foo"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 2, 9, 2, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 9, 2, 9 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 11, 2, 13 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 19, 2, 22 ],
+ "className" : "bool"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 3, 5, 3, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 3, 5, 3, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 5, 3, 5 ],
+ "name" : "a"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 3, 7, 3, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 13, 3, 13 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "VarDef",
+ "location" : [ 4, 5, 4, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 4, 5, 4, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 5 ],
+ "name" : "b"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 7, 4, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 13, 4, 13 ],
+ "value" : 1
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 5, 5, 7, 17 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 9, 5, 11 ],
+ "name" : "bar"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 5, 13, 5, 18 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 13, 5, 13 ],
+ "name" : "y"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 5, 16, 5, 18 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 5, 24, 5, 26 ],
+ "className" : "int"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 6, 9, 6, 17 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 6, 9, 6, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 6, 9, 6, 9 ],
+ "name" : "a"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 6, 11, 6, 13 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 6, 17, 6, 17 ],
+ "value" : 2
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 7, 9, 7, 16 ],
+ "value" : {
+ "kind" : "Identifier",
+ "location" : [ 7, 16, 7, 16 ],
+ "name" : "y"
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 8, 5, 8, 21 ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 8, 12, 8, 21 ],
+ "left" : {
+ "kind" : "CallExpr",
+ "location" : [ 8, 12, 8, 17 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 12, 8, 14 ],
+ "name" : "bar"
+ },
+ "args" : [ {
+ "kind" : "Identifier",
+ "location" : [ 8, 16, 8, 16 ],
+ "name" : "x"
+ } ]
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 21, 8, 21 ],
+ "name" : "a"
+ }
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 10, 1, 10, 6 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 10, 1, 10, 6 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 10, 1, 10, 3 ],
+ "name" : "foo"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 10, 5, 10, 5 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/def_func_nonlocal.py b/src/test/data/pa1/sample/def_func_nonlocal.py
new file mode 100644
index 0000000..1304328
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_nonlocal.py
@@ -0,0 +1,11 @@
+
+def foo(x:int) -> bool:
+ a:int = 0
+ b:int = 1
+ def bar(y: int) -> int:
+ nonlocal a
+ a = 2
+ return y
+ return bar(x) > a
+
+foo(1)
diff --git a/src/test/data/pa1/sample/def_func_nonlocal.py.ast b/src/test/data/pa1/sample/def_func_nonlocal.py.ast
new file mode 100644
index 0000000..5c1e1de
--- /dev/null
+++ b/src/test/data/pa1/sample/def_func_nonlocal.py.ast
@@ -0,0 +1,186 @@
+{
+ "kind" : "Program",
+ "location" : [ 2, 1, 11, 7 ],
+ "declarations" : [ {
+ "kind" : "FuncDef",
+ "location" : [ 2, 1, 9, 22 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 7 ],
+ "name" : "foo"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 2, 9, 2, 13 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 9, 2, 9 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 11, 2, 13 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 2, 19, 2, 22 ],
+ "className" : "bool"
+ },
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 3, 5, 3, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 3, 5, 3, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 5, 3, 5 ],
+ "name" : "a"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 3, 7, 3, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 13, 3, 13 ],
+ "value" : 0
+ }
+ }, {
+ "kind" : "VarDef",
+ "location" : [ 4, 5, 4, 13 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 4, 5, 4, 9 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 5 ],
+ "name" : "b"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 4, 7, 4, 9 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 13, 4, 13 ],
+ "value" : 1
+ }
+ }, {
+ "kind" : "FuncDef",
+ "location" : [ 5, 5, 8, 17 ],
+ "name" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 9, 5, 11 ],
+ "name" : "bar"
+ },
+ "params" : [ {
+ "kind" : "TypedVar",
+ "location" : [ 5, 13, 5, 18 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 13, 5, 13 ],
+ "name" : "y"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 5, 16, 5, 18 ],
+ "className" : "int"
+ }
+ } ],
+ "returnType" : {
+ "kind" : "ClassType",
+ "location" : [ 5, 24, 5, 26 ],
+ "className" : "int"
+ },
+ "declarations" : [ {
+ "kind" : "NonLocalDecl",
+ "location" : [ 6, 9, 6, 18 ],
+ "variable" : {
+ "kind" : "Identifier",
+ "location" : [ 6, 18, 6, 18 ],
+ "name" : "a"
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 7, 9, 7, 13 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 7, 9, 7, 9 ],
+ "name" : "a"
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 7, 13, 7, 13 ],
+ "value" : 2
+ }
+ }, {
+ "kind" : "ReturnStmt",
+ "location" : [ 8, 9, 8, 16 ],
+ "value" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 16, 8, 16 ],
+ "name" : "y"
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ReturnStmt",
+ "location" : [ 9, 5, 9, 21 ],
+ "value" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 9, 12, 9, 21 ],
+ "left" : {
+ "kind" : "CallExpr",
+ "location" : [ 9, 12, 9, 17 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 12, 9, 14 ],
+ "name" : "bar"
+ },
+ "args" : [ {
+ "kind" : "Identifier",
+ "location" : [ 9, 16, 9, 16 ],
+ "name" : "x"
+ } ]
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "Identifier",
+ "location" : [ 9, 21, 9, 21 ],
+ "name" : "a"
+ }
+ }
+ } ]
+ } ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 11, 1, 11, 6 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 11, 1, 11, 6 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 11, 1, 11, 3 ],
+ "name" : "foo"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 11, 5, 11, 5 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/expr_if.py b/src/test/data/pa1/sample/expr_if.py
new file mode 100644
index 0000000..e9e9c26
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_if.py
@@ -0,0 +1 @@
+3 if 1 > 2 else 4
diff --git a/src/test/data/pa1/sample/expr_if.py.ast b/src/test/data/pa1/sample/expr_if.py.ast
new file mode 100644
index 0000000..0ed9a55
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_if.py.ast
@@ -0,0 +1,43 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 18 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 17 ],
+ "expr" : {
+ "kind" : "IfExpr",
+ "location" : [ 1, 1, 1, 17 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 6, 1, 10 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 6, 1, 6 ],
+ "value" : 1
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 10, 1, 10 ],
+ "value" : 2
+ }
+ },
+ "thenExpr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 1, 1, 1 ],
+ "value" : 3
+ },
+ "elseExpr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 17, 1, 17 ],
+ "value" : 4
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/expr_if_chained.py b/src/test/data/pa1/sample/expr_if_chained.py
new file mode 100644
index 0000000..4a7837e
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_if_chained.py
@@ -0,0 +1 @@
+3 if 1 > 2 else 4 if 1 < 0 else 5
diff --git a/src/test/data/pa1/sample/expr_if_chained.py.ast b/src/test/data/pa1/sample/expr_if_chained.py.ast
new file mode 100644
index 0000000..2776da9
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_if_chained.py.ast
@@ -0,0 +1,67 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 34 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 33 ],
+ "expr" : {
+ "kind" : "IfExpr",
+ "location" : [ 1, 1, 1, 33 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 6, 1, 10 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 6, 1, 6 ],
+ "value" : 1
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 10, 1, 10 ],
+ "value" : 2
+ }
+ },
+ "thenExpr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 1, 1, 1 ],
+ "value" : 3
+ },
+ "elseExpr" : {
+ "kind" : "IfExpr",
+ "location" : [ 1, 17, 1, 33 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 22, 1, 26 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 22, 1, 22 ],
+ "value" : 1
+ },
+ "operator" : "<",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 26, 1, 26 ],
+ "value" : 0
+ }
+ },
+ "thenExpr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 17, 1, 17 ],
+ "value" : 4
+ },
+ "elseExpr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 33, 1, 33 ],
+ "value" : 5
+ }
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/expr_index.py b/src/test/data/pa1/sample/expr_index.py
new file mode 100644
index 0000000..8e95ff2
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_index.py
@@ -0,0 +1 @@
+a + b[i][j]
diff --git a/src/test/data/pa1/sample/expr_index.py.ast b/src/test/data/pa1/sample/expr_index.py.ast
new file mode 100644
index 0000000..a5f97ee
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_index.py.ast
@@ -0,0 +1,47 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 12 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 11 ],
+ "expr" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 1, 1, 11 ],
+ "left" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "a"
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IndexExpr",
+ "location" : [ 1, 5, 1, 11 ],
+ "list" : {
+ "kind" : "IndexExpr",
+ "location" : [ 1, 5, 1, 8 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 5, 1, 5 ],
+ "name" : "b"
+ },
+ "index" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 7, 1, 7 ],
+ "name" : "i"
+ }
+ },
+ "index" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 10, 1, 10 ],
+ "name" : "j"
+ }
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/expr_plus.py b/src/test/data/pa1/sample/expr_plus.py
new file mode 100644
index 0000000..8138b36
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_plus.py
@@ -0,0 +1 @@
+1 + 2 + 3
diff --git a/src/test/data/pa1/sample/expr_plus.py.ast b/src/test/data/pa1/sample/expr_plus.py.ast
new file mode 100644
index 0000000..f924e67
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_plus.py.ast
@@ -0,0 +1,39 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 10 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 9 ],
+ "expr" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 1, 1, 9 ],
+ "left" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 1, 1, 5 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 1, 1, 1 ],
+ "value" : 1
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 5, 1, 5 ],
+ "value" : 2
+ }
+ },
+ "operator" : "+",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 9, 1, 9 ],
+ "value" : 3
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/expr_unary.py b/src/test/data/pa1/sample/expr_unary.py
new file mode 100644
index 0000000..3a2e3f4
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_unary.py
@@ -0,0 +1 @@
+-1
diff --git a/src/test/data/pa1/sample/expr_unary.py.ast b/src/test/data/pa1/sample/expr_unary.py.ast
new file mode 100644
index 0000000..e4ef8d2
--- /dev/null
+++ b/src/test/data/pa1/sample/expr_unary.py.ast
@@ -0,0 +1,24 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 3 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 2 ],
+ "expr" : {
+ "kind" : "UnaryExpr",
+ "location" : [ 1, 1, 1, 2 ],
+ "operator" : "-",
+ "operand" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 2, 1, 2 ],
+ "value" : 1
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/global.py b/src/test/data/pa1/sample/global.py
new file mode 100644
index 0000000..779d3bb
--- /dev/null
+++ b/src/test/data/pa1/sample/global.py
@@ -0,0 +1,5 @@
+x:int = 1
+
+x = 2
+
+print(x)
diff --git a/src/test/data/pa1/sample/global.py.ast b/src/test/data/pa1/sample/global.py.ast
new file mode 100644
index 0000000..84b42b1
--- /dev/null
+++ b/src/test/data/pa1/sample/global.py.ast
@@ -0,0 +1,63 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 5, 9 ],
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 1, 1, 1, 9 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 1, 1, 1, 5 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 3, 1, 5 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 9, 1, 9 ],
+ "value" : 1
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 3, 1, 3, 5 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 3, 1, 3, 1 ],
+ "name" : "x"
+ } ],
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 5, 3, 5 ],
+ "value" : 2
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 5, 1, 5, 8 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 5, 1, 5, 8 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 5, 1, 5, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "Identifier",
+ "location" : [ 5, 7, 5, 7 ],
+ "name" : "x"
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/literals.py b/src/test/data/pa1/sample/literals.py
new file mode 100644
index 0000000..081863e
--- /dev/null
+++ b/src/test/data/pa1/sample/literals.py
@@ -0,0 +1,7 @@
+True
+False
+1
+None
+"This is a string"
+[1, 2, 3]
+
diff --git a/src/test/data/pa1/sample/literals.py.ast b/src/test/data/pa1/sample/literals.py.ast
new file mode 100644
index 0000000..d6fd3bc
--- /dev/null
+++ b/src/test/data/pa1/sample/literals.py.ast
@@ -0,0 +1,70 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 6, 10 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 4 ],
+ "expr" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 1, 1, 1, 4 ],
+ "value" : true
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 2, 1, 2, 5 ],
+ "expr" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 2, 1, 2, 5 ],
+ "value" : false
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 3, 1, 3, 1 ],
+ "expr" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 1, 3, 1 ],
+ "value" : 1
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 1, 4, 4 ],
+ "expr" : {
+ "kind" : "NoneLiteral",
+ "location" : [ 4, 1, 4, 4 ]
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 5, 1, 5, 18 ],
+ "expr" : {
+ "kind" : "StringLiteral",
+ "location" : [ 5, 1, 5, 18 ],
+ "value" : "This is a string"
+ }
+ }, {
+ "kind" : "ExprStmt",
+ "location" : [ 6, 1, 6, 9 ],
+ "expr" : {
+ "kind" : "ListExpr",
+ "location" : [ 6, 1, 6, 9 ],
+ "elements" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 6, 2, 6, 2 ],
+ "value" : 1
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 6, 5, 6, 5 ],
+ "value" : 2
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 6, 8, 6, 8 ],
+ "value" : 3
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_call.py b/src/test/data/pa1/sample/stmt_call.py
new file mode 100644
index 0000000..b917a72
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_call.py
@@ -0,0 +1 @@
+print(1)
diff --git a/src/test/data/pa1/sample/stmt_call.py.ast b/src/test/data/pa1/sample/stmt_call.py.ast
new file mode 100644
index 0000000..4d0ef38
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_call.py.ast
@@ -0,0 +1,28 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 1, 9 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 1, 1, 1, 8 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 1, 1, 1, 8 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 5 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 7, 1, 7 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_for.py b/src/test/data/pa1/sample/stmt_for.py
new file mode 100644
index 0000000..6f65c5f
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_for.py
@@ -0,0 +1,4 @@
+x:int = 0
+for x in [1, 2, 3]:
+ print(x)
+
diff --git a/src/test/data/pa1/sample/stmt_for.py.ast b/src/test/data/pa1/sample/stmt_for.py.ast
new file mode 100644
index 0000000..ba0847b
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_for.py.ast
@@ -0,0 +1,76 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 5, 1 ],
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 1, 1, 1, 9 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 1, 1, 1, 5 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 3, 1, 5 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 9, 1, 9 ],
+ "value" : 0
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "ForStmt",
+ "location" : [ 2, 1, 5, 1 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 5 ],
+ "name" : "x"
+ },
+ "iterable" : {
+ "kind" : "ListExpr",
+ "location" : [ 2, 10, 2, 18 ],
+ "elements" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 11, 2, 11 ],
+ "value" : 1
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 14, 2, 14 ],
+ "value" : 2
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 17, 2, 17 ],
+ "value" : 3
+ } ]
+ },
+ "body" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 3, 5, 3, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 3, 5, 3, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 3, 5, 3, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "Identifier",
+ "location" : [ 3, 11, 3, 11 ],
+ "name" : "x"
+ } ]
+ }
+ } ]
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_if.py b/src/test/data/pa1/sample/stmt_if.py
new file mode 100644
index 0000000..b87c003
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_if.py
@@ -0,0 +1,3 @@
+if True:
+ False
+
diff --git a/src/test/data/pa1/sample/stmt_if.py.ast b/src/test/data/pa1/sample/stmt_if.py.ast
new file mode 100644
index 0000000..2b08a8f
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_if.py.ast
@@ -0,0 +1,29 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 1 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 1, 1, 4, 1 ],
+ "condition" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 1, 4, 1, 7 ],
+ "value" : true
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 2, 5, 2, 9 ],
+ "expr" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 2, 5, 2, 9 ],
+ "value" : false
+ }
+ } ],
+ "elseBody" : [ ]
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_if_elif.py b/src/test/data/pa1/sample/stmt_if_elif.py
new file mode 100644
index 0000000..7fa86dd
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_if_elif.py
@@ -0,0 +1,6 @@
+if 1 > 2:
+ print(1)
+elif 3 == 4:
+ print(2)
+elif True:
+ print(3)
diff --git a/src/test/data/pa1/sample/stmt_if_elif.py.ast b/src/test/data/pa1/sample/stmt_if_elif.py.ast
new file mode 100644
index 0000000..11dcd2e
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_if_elif.py.ast
@@ -0,0 +1,112 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 7, 1 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 1, 1, 7, 1 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 4, 1, 8 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 4, 1, 4 ],
+ "value" : 1
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 8, 1, 8 ],
+ "value" : 2
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 2, 5, 2, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 2, 5, 2, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 11, 2, 11 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 3, 1, 7, 1 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 3, 6, 3, 11 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 6, 3, 6 ],
+ "value" : 3
+ },
+ "operator" : "==",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 11, 3, 11 ],
+ "value" : 4
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 5, 4, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 5, 4, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 11, 4, 11 ],
+ "value" : 2
+ } ]
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 5, 1, 7, 1 ],
+ "condition" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 5, 6, 5, 9 ],
+ "value" : true
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 6, 5, 6, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 6, 5, 6, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 6, 5, 6, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 6, 11, 6, 11 ],
+ "value" : 3
+ } ]
+ }
+ } ],
+ "elseBody" : [ ]
+ } ]
+ } ]
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_if_elif_else.py b/src/test/data/pa1/sample/stmt_if_elif_else.py
new file mode 100644
index 0000000..161d9d9
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_if_elif_else.py
@@ -0,0 +1,8 @@
+if 1 > 2:
+ print(1)
+elif 3 == 4:
+ print(2)
+elif True:
+ print(3)
+else:
+ print(4)
diff --git a/src/test/data/pa1/sample/stmt_if_elif_else.py.ast b/src/test/data/pa1/sample/stmt_if_elif_else.py.ast
new file mode 100644
index 0000000..dc25855
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_if_elif_else.py.ast
@@ -0,0 +1,129 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 9, 1 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 1, 1, 9, 1 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 1, 4, 1, 8 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 4, 1, 4 ],
+ "value" : 1
+ },
+ "operator" : ">",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 1, 8, 1, 8 ],
+ "value" : 2
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 2, 5, 2, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 2, 5, 2, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 2, 5, 2, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 2, 11, 2, 11 ],
+ "value" : 1
+ } ]
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 3, 1, 9, 1 ],
+ "condition" : {
+ "kind" : "BinaryExpr",
+ "location" : [ 3, 6, 3, 11 ],
+ "left" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 6, 3, 6 ],
+ "value" : 3
+ },
+ "operator" : "==",
+ "right" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 11, 3, 11 ],
+ "value" : 4
+ }
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 5, 4, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 4, 5, 4, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 5, 4, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 11, 4, 11 ],
+ "value" : 2
+ } ]
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 5, 1, 9, 1 ],
+ "condition" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 5, 6, 5, 9 ],
+ "value" : true
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 6, 5, 6, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 6, 5, 6, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 6, 5, 6, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 6, 11, 6, 11 ],
+ "value" : 3
+ } ]
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 8, 5, 8, 12 ],
+ "expr" : {
+ "kind" : "CallExpr",
+ "location" : [ 8, 5, 8, 12 ],
+ "function" : {
+ "kind" : "Identifier",
+ "location" : [ 8, 5, 8, 9 ],
+ "name" : "print"
+ },
+ "args" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 8, 11, 8, 11 ],
+ "value" : 4
+ } ]
+ }
+ } ]
+ } ]
+ } ]
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_ifelse.py b/src/test/data/pa1/sample/stmt_ifelse.py
new file mode 100644
index 0000000..f138957
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_ifelse.py
@@ -0,0 +1,5 @@
+if True:
+ False
+else:
+ True
+
diff --git a/src/test/data/pa1/sample/stmt_ifelse.py.ast b/src/test/data/pa1/sample/stmt_ifelse.py.ast
new file mode 100644
index 0000000..8e23d16
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_ifelse.py.ast
@@ -0,0 +1,37 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 6, 1 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "IfStmt",
+ "location" : [ 1, 1, 6, 1 ],
+ "condition" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 1, 4, 1, 7 ],
+ "value" : true
+ },
+ "thenBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 2, 5, 2, 9 ],
+ "expr" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 2, 5, 2, 9 ],
+ "value" : false
+ }
+ } ],
+ "elseBody" : [ {
+ "kind" : "ExprStmt",
+ "location" : [ 4, 5, 4, 8 ],
+ "expr" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 4, 5, 4, 8 ],
+ "value" : true
+ }
+ } ]
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_list_assign.py b/src/test/data/pa1/sample/stmt_list_assign.py
new file mode 100644
index 0000000..e9e31d9
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_list_assign.py
@@ -0,0 +1,4 @@
+x:int = None
+
+x = [1, 2, 3]
+x[0] = x[1]
diff --git a/src/test/data/pa1/sample/stmt_list_assign.py.ast b/src/test/data/pa1/sample/stmt_list_assign.py.ast
new file mode 100644
index 0000000..b65848c
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_list_assign.py.ast
@@ -0,0 +1,88 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 12 ],
+ "declarations" : [ {
+ "kind" : "VarDef",
+ "location" : [ 1, 1, 1, 12 ],
+ "var" : {
+ "kind" : "TypedVar",
+ "location" : [ 1, 1, 1, 5 ],
+ "identifier" : {
+ "kind" : "Identifier",
+ "location" : [ 1, 1, 1, 1 ],
+ "name" : "x"
+ },
+ "type" : {
+ "kind" : "ClassType",
+ "location" : [ 1, 3, 1, 5 ],
+ "className" : "int"
+ }
+ },
+ "value" : {
+ "kind" : "NoneLiteral",
+ "location" : [ 1, 9, 1, 12 ]
+ }
+ } ],
+ "statements" : [ {
+ "kind" : "AssignStmt",
+ "location" : [ 3, 1, 3, 13 ],
+ "targets" : [ {
+ "kind" : "Identifier",
+ "location" : [ 3, 1, 3, 1 ],
+ "name" : "x"
+ } ],
+ "value" : {
+ "kind" : "ListExpr",
+ "location" : [ 3, 5, 3, 13 ],
+ "elements" : [ {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 6, 3, 6 ],
+ "value" : 1
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 9, 3, 9 ],
+ "value" : 2
+ }, {
+ "kind" : "IntegerLiteral",
+ "location" : [ 3, 12, 3, 12 ],
+ "value" : 3
+ } ]
+ }
+ }, {
+ "kind" : "AssignStmt",
+ "location" : [ 4, 1, 4, 11 ],
+ "targets" : [ {
+ "kind" : "IndexExpr",
+ "location" : [ 4, 1, 4, 4 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 1, 4, 1 ],
+ "name" : "x"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 3, 4, 3 ],
+ "value" : 0
+ }
+ } ],
+ "value" : {
+ "kind" : "IndexExpr",
+ "location" : [ 4, 8, 4, 11 ],
+ "list" : {
+ "kind" : "Identifier",
+ "location" : [ 4, 8, 4, 8 ],
+ "name" : "x"
+ },
+ "index" : {
+ "kind" : "IntegerLiteral",
+ "location" : [ 4, 10, 4, 10 ],
+ "value" : 1
+ }
+ }
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/sample/stmt_while.py b/src/test/data/pa1/sample/stmt_while.py
new file mode 100644
index 0000000..1aaefd8
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_while.py
@@ -0,0 +1,3 @@
+while True:
+ pass
+
diff --git a/src/test/data/pa1/sample/stmt_while.py.ast b/src/test/data/pa1/sample/stmt_while.py.ast
new file mode 100644
index 0000000..a564490
--- /dev/null
+++ b/src/test/data/pa1/sample/stmt_while.py.ast
@@ -0,0 +1,20 @@
+{
+ "kind" : "Program",
+ "location" : [ 1, 1, 4, 1 ],
+ "declarations" : [ ],
+ "statements" : [ {
+ "kind" : "WhileStmt",
+ "location" : [ 1, 1, 4, 1 ],
+ "condition" : {
+ "kind" : "BooleanLiteral",
+ "location" : [ 1, 7, 1, 10 ],
+ "value" : true
+ },
+ "body" : [ ]
+ } ],
+ "errors" : {
+ "errors" : [ ],
+ "kind" : "Errors",
+ "location" : [ 0, 0, 0, 0 ]
+ }
+}
\ No newline at end of file
diff --git a/src/test/data/pa1/student_contributed/bad.py b/src/test/data/pa1/student_contributed/bad.py
new file mode 100644
index 0000000..b85905e
--- /dev/null
+++ b/src/test/data/pa1/student_contributed/bad.py
@@ -0,0 +1 @@
+1 2 3
diff --git a/src/test/data/pa1/student_contributed/good.py b/src/test/data/pa1/student_contributed/good.py
new file mode 100644
index 0000000..8138b36
--- /dev/null
+++ b/src/test/data/pa1/student_contributed/good.py
@@ -0,0 +1 @@
+1 + 2 + 3