summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgeno <gabriele.genovese2@studio.unibo.it>2024-06-27 18:20:34 +0200
committergeno <gabriele.genovese2@studio.unibo.it>2024-06-27 18:20:34 +0200
commiteb7fb04d2dfadd004fa86f28da42681e0038df06 (patch)
tree1bba3962300083017673c5d689a5d2bf1652109d
parent095a2cb4e9abb88805aac3271874bc512108ff96 (diff)
left, right = 1, 2 assignment covered
sfaccimm ho fatto refactoring dell exprlist
-rw-r--r--src/ast/Python3VisitorImpl.java192
-rw-r--r--src/ast/nodes/AssignmentNode.java21
-rw-r--r--src/ast/nodes/AtomNode.java22
-rw-r--r--src/ast/nodes/ExprListNode.java61
-rw-r--r--src/ast/nodes/ForStmtNode.java12
-rw-r--r--src/ast/nodes/ParamdefNode.java2
-rw-r--r--src/ast/nodes/TestlistCompNode.java61
-rw-r--r--test/trailers.py13
8 files changed, 262 insertions, 122 deletions
diff --git a/src/ast/Python3VisitorImpl.java b/src/ast/Python3VisitorImpl.java
index d4b4fbf..5b812ea 100644
--- a/src/ast/Python3VisitorImpl.java
+++ b/src/ast/Python3VisitorImpl.java
@@ -12,20 +12,19 @@ import org.antlr.v4.runtime.tree.TerminalNode;
* Overrides each `visitNODE` method from the base class.
*/
public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
+
/**
* Since a root can be a simple_stmts or a compound_stmt, this method
* returns a new `RootNode` with a list of them.
*
- * ```
- * root : NEWLINE* (simple_stmts | compound_stmt)* EOF;
- * ```
+ * ``` root : NEWLINE* (simple_stmts | compound_stmt)* EOF; ```
*/
public Node visitRoot(RootContext ctx) {
ArrayList<Node> childs = new ArrayList<Node>();
-
- for (int i = 0; i < ctx.getChildCount(); i++){
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
var child = ctx.getChild(i);
-
+
if (child instanceof Simple_stmtsContext) {
childs.add(visit((Simple_stmtsContext) child));
} else if (child instanceof Compound_stmtContext) {
@@ -39,9 +38,7 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
/**
* Returns a `SimpleStmtsNode`, made by an array of SimpleStmtNode
*
- * ```
- * simple_stmts : simple_stmt (';' simple_stmt)* ';'? NEWLINE ;
- * ```
+ * ``` simple_stmts : simple_stmt (';' simple_stmt)* ';'? NEWLINE ; ```
*/
public Node visitSimple_stmts(Simple_stmtsContext ctx) {
ArrayList<Node> stmts = new ArrayList<Node>();
@@ -57,9 +54,7 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
* Returns a `CompoundNode`. It can be built by a different kind of
* statements, so only one of theme won't be null.
*
- * ```
- * compound_stmt : if_stmt | while_stmt | for_stmt | funcdef ;
- * ```
+ * ``` compound_stmt : if_stmt | while_stmt | for_stmt | funcdef ; ```
*/
public Node visitCompound_stmt(Compound_stmtContext ctx) {
Node ifStmt = null;
@@ -90,9 +85,7 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
* Returns a `SimpleStmtNode`. It can be built by a different kind of
* statements, so only one of theme won't be null.
*
- * ```
- * simple_stmt : assignment | expr | return_stmt | import_stm ;
- * ```
+ * ``` simple_stmt : assignment | expr | return_stmt | import_stm ; ```
*/
public Node visitSimple_stmt(Simple_stmtContext ctx) {
Node assignment = null;
@@ -122,10 +115,8 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
/**
* Returns an `AssignmentNode`. It's made by left side, an assignment and a
* right side.
- *
- * ```
- * assignment : exprlist augassign exprlist ;
- * ```
+ *
+ * ``` assignment : exprlist augassign exprlist ; ```
*/
public Node visitAssignment(AssignmentContext ctx) {
Node lhr = visit(ctx.exprlist(0));
@@ -138,9 +129,7 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
/**
* Returns a `ReturnStmtNode`. The returned exprlist can be null.
*
- * ```
- * return_stmt : 'return' exprlist? ;
- * ```
+ * ``` return_stmt : 'return' exprlist? ; ```
*/
public Node visitReturn_stmt(Return_stmtContext ctx) {
Node exprList = null;
@@ -155,10 +144,8 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
* Returns a `ImportNode`. An import can be made in different ways so we
* check the way in a module is imported (by from, by alias or by star).
*
- * ```
- * import_stm : 'import' dotted_name ('as' NAME)?
- * | 'from' dotted_name 'import' (NAME (',' NAME)* | '*') ;
- * ```
+ * ``` import_stm : 'import' dotted_name ('as' NAME)? | 'from' dotted_name
+ * 'import' (NAME (',' NAME)* | '*') ; ```
*/
public Node visitImport_stm(Import_stmContext ctx) {
boolean isFrom = ctx.FROM() != null;
@@ -179,9 +166,7 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
/**
* Returns a `DottedNameNode` used in `import_stm`.
*
- * ```
- * dotted_name : NAME ('.' NAME)* ;
- * ```
+ * ``` dotted_name : NAME ('.' NAME)* ; ```
*/
public Node visitDotted_name(Dotted_nameContext ctx) {
ArrayList<TerminalNode> names = new ArrayList<TerminalNode>();
@@ -196,9 +181,7 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
/**
* Returns a `FuncdefNode`. A paramlist can be null.
*
- * ```
- * funcdef : 'def' NAME '(' paramlist? ')' ':' block ;
- * ```
+ * ``` funcdef : 'def' NAME '(' paramlist? ')' ':' block ; ```
*/
public Node visitFuncdef(FuncdefContext ctx) {
Node paramlist = null;
@@ -216,9 +199,8 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
* Returns a `ParamlistNode`. We ignore the paramdef with default values
* (eg: is_used=False) because there is no test which uses this feature.
*
- * ```
- * paramlist : paramdef ('=' expr)? (',' paramdef ('=' expr)?)* ;
- *
+ * ``` paramlist : paramdef ('=' expr)? (',' paramdef ('=' expr)?)* ;
+ *
* ```
*/
public Node visitParamlist(ParamlistContext ctx) {
@@ -235,9 +217,7 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
* Returns a `ParamdefNode`. We ignore the paramdef with type annotation
* (eg: x : int) because there is no test which uses this feature.
*
- * ```
- * paramdef : NAME (':' expr)? ;
- * ```
+ * ``` paramdef : NAME (':' expr)? ; ```
*/
public Node visitParamdef(ParamdefContext ctx) {
return new ParamdefNode(ctx.NAME().toString());
@@ -247,11 +227,8 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
* Returns an `AugassignNode`. We don't provide all kinds of assignment
* below.
*
- * ```
- * augassign : '=' | '+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' |
- * '^=' | '<<=' | '>>=' | '**=' | '//='
- * ;
- * ```
+ * ``` augassign : '=' | '+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' |
+ * '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=' ; ```
*/
public Node visitAugassign(AugassignContext ctx) {
Node x = null;
@@ -285,17 +262,15 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
} else if (ctx.IDIV_ASSIGN() != null) {
x = new AugassignNode(ctx.IDIV_ASSIGN());
}
-
+
return x;
}
/**
- * Returns a `IfNode`.
- * FIXME: add support for elif statement.
+ * Returns a `IfNode`. FIXME: add support for elif statement.
*
- * ```
- * if_stmt : 'if' expr ':' block ('elif' expr ':' block)* ('else' ':' block)? ;
- * ```
+ * ``` if_stmt : 'if' expr ':' block ('elif' expr ':' block)* ('else' ':'
+ * block)? ; ```
*/
public Node visitIf_stmt(If_stmtContext ctx) {
var blocks = ctx.block();
@@ -312,9 +287,7 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
/**
* Returns a `WhileStmtNode`. We do not provide 'else' branch.
*
- * ```
- * while_stmt : 'while' expr ':' block ('else' ':' block)? ;
- * ```
+ * ``` while_stmt : 'while' expr ':' block ('else' ':' block)? ; ```
*/
public Node visitWhile_stmt(While_stmtContext ctx) {
Node expr = visit(ctx.expr());
@@ -328,9 +301,7 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
/**
* Returns a `ForSmtNode`. We do not provide 'else' branch.
*
- * ```
- * for_stmt : 'for' exprlist ':' block ('else' ':' block)? ;
- * ```
+ * ``` for_stmt : 'for' exprlist ':' block ('else' ':' block)? ; ```
*/
public Node visitFor_stmt(For_stmtContext ctx) {
Node exprList = visit(ctx.exprlist());
@@ -345,17 +316,15 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
* Returns a `BlockNode`. A block can be be a simple_stmts or a list of
* simple_stms and/or compound_stmt, so we just use a list for each kind.
*
- * ```
- * block : simple_stmts
- * | NEWLINE INDENT (simple_stmts | compound_stmt)+ DEDENT ;
- * ```
+ * ``` block : simple_stmts | NEWLINE INDENT (simple_stmts | compound_stmt)+
+ * DEDENT ; ```
*/
public Node visitBlock(BlockContext ctx) {
ArrayList<Node> childs = new ArrayList<Node>();
- for (int i = 0; i < ctx.getChildCount(); i++){
+ for (int i = 0; i < ctx.getChildCount(); i++) {
var child = ctx.getChild(i);
-
+
if (child instanceof Simple_stmtsContext) {
childs.add(visit((Simple_stmtsContext) child));
} else if (child instanceof Compound_stmtContext) {
@@ -369,10 +338,8 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
/**
* Returns a `CompNode`. It should never be null.
*
- * ```
- * comp_op : '<' | '>' | '==' | '>=' | '<=' | '<>' | '!=' | 'in' | 'not' 'in' |
- * 'is' | 'is' 'not' ;
- * ```
+ * ``` comp_op : '<' | '>' | '==' | '>=' | '<=' | '<>' | '!=' | 'in' | 'not'
+ * 'in' | 'is' | 'is' 'not' ; ```
*/
public Node visitComp_op(Comp_opContext ctx) {
Node comp = null;
@@ -404,13 +371,11 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
* Returns an `ExprNode`. An expession can be a different kind of
* sub-expression. We do not provide all kinds of expr(s).
*
- * ```
- * expr : atom trailer* | expr '**' expr | ('+' | '-' | '~')+ expr | expr ('*' |
- * '@' | '/' | '%' | '//') expr | expr ('+' | '-') expr | expr ('<<' | '>>')
- * expr | expr '&' expr | expr '^' expr | expr '|' expr | 'not' expr | expr
- * comp_op expr | expr 'and' expr | expr 'or' expr | expr 'if' expr 'else' expr
- * ;
- * ```
+ * ``` expr : atom trailer* | expr '**' expr | ('+' | '-' | '~')+ expr |
+ * expr ('*' | '@' | '/' | '%' | '//') expr | expr ('+' | '-') expr | expr
+ * ('<<' | '>>') expr | expr '&' expr | expr '^' expr | expr '|' expr |
+ * 'not' expr | expr comp_op expr | expr 'and' expr | expr 'or' expr | expr
+ * 'if' expr 'else' expr ; ```
*/
public Node visitExpr(ExprContext ctx) {
Node atom = null;
@@ -459,42 +424,52 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
}
/**
- * Returns an `AtomNode`.
- * FIXME: add support for testlist_comp
+ * Returns an `AtomNode`. FIXME: add support for testlist_comp
*
- * ```
- * atom : '(' testlist_comp? ')' | '[' testlist_comp? ']' | '{' testlist_comp?
- * '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False' ;
- * ```
+ * ``` atom : '(' testlist_comp? ')' | '[' testlist_comp? ']' | '{'
+ * testlist_comp? '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' |
+ * 'False' ; ```
*/
public Node visitAtom(AtomContext ctx) {
+ Testlist_compContext tlc = ctx.testlist_comp();
if (ctx.NUMBER() != null) {
- return new AtomNode(ctx.NUMBER().toString());
+ return new AtomNode(ctx.NUMBER().toString(), null);
} else if (ctx.TRUE() != null) {
- return new AtomNode(ctx.TRUE().toString());
+ return new AtomNode(ctx.TRUE().toString(), null);
} else if (ctx.FALSE() != null) {
- return new AtomNode(ctx.FALSE().toString());
+ return new AtomNode(ctx.FALSE().toString(), null);
} else if (ctx.NAME() != null) {
- return new AtomNode(ctx.NAME().toString());
- } else if (ctx.STRING() != null) {
-
+ return new AtomNode(ctx.NAME().toString(), null);
+ } else if (!ctx.STRING().isEmpty()) {
var varName = "";
for (var x : ctx.STRING()) {
varName += x;
}
+ return new AtomNode(varName, null);
+ } else if (ctx.OPEN_BRACE() != null && ctx.CLOSE_BRACE() != null) {
+ return manageTlc(tlc);
+ } else if (ctx.OPEN_BRACK() != null && ctx.CLOSE_BRACK() != null) {
+ return manageTlc(tlc);
+ } else if (ctx.OPEN_PAREN() != null && ctx.CLOSE_PAREN() != null) {
+ return manageTlc(tlc);
+ }
+ return new AtomNode(ctx.NONE().toString(), null);
+ }
- return new AtomNode(varName);
+ public AtomNode manageTlc(Testlist_compContext tlc) {
+ if (tlc != null) {
+ Node testlist_comp = visit(tlc);
+ return new AtomNode(null, testlist_comp);
+ } else {
+ return new AtomNode(null, null);
}
- return new AtomNode(ctx.NONE().toString());
}
/**
* Returns an `TrailerNode`.
*
- * ```
- * trailer : '(' arglist? ')' | '[' expr (',' expr)* ','? ']' | '.' NAME | '['
- * expr? ':' expr? (':' expr? )? ']' ;
- * ```
+ * ``` trailer : '(' arglist? ')' | '[' expr (',' expr)* ','? ']' | '.' NAME
+ * | '[' expr? ':' expr? (':' expr? )? ']' ; ```
*/
public Node visitTrailer(TrailerContext ctx) {
Node arglist = null;
@@ -517,31 +492,24 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
}
/**
- * Returns a `Node`.
- * FIXME: what to do in case of list??
+ * Returns a `Node`. FIXME: what to do in case of list??
*
- * ```
- * exprlist : expr (',' expr )* ','? ;
- * ```
+ * ``` exprlist : expr (',' expr )* ','? ; ```
*/
public Node visitExprlist(ExprlistContext ctx) {
- Node exp;
+ ArrayList<Node> exprlist = new ArrayList<Node>();
- if (ctx.expr(0).expr(0) != null){
- exp = visit(ctx.expr(0).expr(0));
- } else {
- exp = visit(ctx.expr(0));
+ for (ExprContext c : ctx.expr()) {
+ exprlist.add(visit(c));
}
- return exp;
+ return new ExprListNode(exprlist);
}
/**
* Returns a `ArglistNode`.
*
- * ```
- * arglist : argument (',' argument)* ','? ;
- * ```
+ * ``` arglist : argument (',' argument)* ','? ; ```
*/
public Node visitArglist(ArglistContext ctx) {
ArrayList<Node> arguments = new ArrayList<Node>();
@@ -552,4 +520,20 @@ public class Python3VisitorImpl extends Python3ParserBaseVisitor<Node> {
return new ArglistNode(arguments);
}
+
+ /**
+ * Returns a `TestlistCompNode`.
+ *
+ * ``` testlist_comp : expr (comp_for | (',' expr)* ','?) ; ```
+ */
+ public Node visitTestlist_comp(Testlist_compContext ctx) {
+ // TODO: implement comp_for
+ ArrayList<Node> exprlist = new ArrayList<Node>();
+
+ for (ExprContext c : ctx.expr()) {
+ exprlist.add(visit(c));
+ }
+
+ return new TestlistCompNode(exprlist);
+ }
}
diff --git a/src/ast/nodes/AssignmentNode.java b/src/ast/nodes/AssignmentNode.java
index 3d597ef..07966c3 100644
--- a/src/ast/nodes/AssignmentNode.java
+++ b/src/ast/nodes/AssignmentNode.java
@@ -10,14 +10,14 @@ import semanticanalysis.SymbolTable;
*/
public class AssignmentNode implements Node {
- private ExprNode lhr;
+ private ExprListNode lhr;
private Node assign;
- private ExprNode rhr;
+ private ExprListNode rhr;
public AssignmentNode(Node lhr, Node assign, Node rhr) {
- this.lhr = (ExprNode) lhr;
+ this.lhr = (ExprListNode) lhr;
this.assign = assign;
- this.rhr = (ExprNode) rhr;
+ this.rhr = (ExprListNode) rhr;
}
@Override
@@ -28,7 +28,18 @@ public class AssignmentNode implements Node {
errors.addAll(assign.checkSemantics(ST, _nesting));
errors.addAll(rhr.checkSemantics(ST, _nesting));
- ST.insert(lhr.getId(), rhr.typeCheck(), _nesting, "");
+ int lsize = lhr.getSize();
+ int rsize = rhr.getSize();
+
+ if (lsize == rsize) {
+ for (int i = 0; i < lsize; i++) {
+ ExprNode latom = (ExprNode) lhr.getElem(i);
+ ExprNode ratom = (ExprNode) rhr.getElem(i);
+ ST.insert(latom.getId(), ratom.typeCheck(), _nesting, "");
+ }
+ } else {
+ errors.add(new SemanticError("ValueError: different size of left or right side assignment"));
+ }
return errors;
}
diff --git a/src/ast/nodes/AtomNode.java b/src/ast/nodes/AtomNode.java
index 3c2b1eb..592aac4 100644
--- a/src/ast/nodes/AtomNode.java
+++ b/src/ast/nodes/AtomNode.java
@@ -13,9 +13,11 @@ import semanticanalysis.SymbolTable;
public class AtomNode implements Node {
protected String val;
+ protected TestlistCompNode exprlist;
- public AtomNode(String val) {
+ public AtomNode(String val, Node exprlist) {
this.val = val;
+ this.exprlist = (TestlistCompNode) exprlist;
}
public String getId() {
@@ -26,10 +28,16 @@ public class AtomNode implements Node {
public ArrayList<SemanticError> checkSemantics(SymbolTable ST, int _nesting) {
var errors = new ArrayList<SemanticError>();
- if ((this.typeCheck() instanceof AtomType) && ST.nslookup(this.getId()) < 0) {
- errors.add(new SemanticError("name '" + this.getId() + "' is not defined."));
- } else {
- // System.out.println("exist " + this.getId());
+ if (val != null) {
+ if ((this.typeCheck() instanceof AtomType) && ST.nslookup(this.getId()) < 0) {
+ errors.add(new SemanticError("name '" + this.getId() + "' is not defined."));
+ } else {
+ // System.out.println("exist " + this.typeCheck());
+ }
+ }
+
+ if (exprlist != null) {
+ errors.addAll(exprlist.checkSemantics(ST, _nesting));
}
return errors;
@@ -38,6 +46,10 @@ public class AtomNode implements Node {
// ENHANCE: return more specific types
@Override
public Type typeCheck() {
+ if (this.val == null) {
+ return new VoidType();
+ }
+
Pattern booleanVariable = Pattern.compile("^(True|False)$");
Pattern continueBreakVariable = Pattern.compile("^(continue|break)$");
// this regex should match every possible atom name written in this format: CHAR (CHAR | DIGIT)*
diff --git a/src/ast/nodes/ExprListNode.java b/src/ast/nodes/ExprListNode.java
new file mode 100644
index 0000000..c1a2ebc
--- /dev/null
+++ b/src/ast/nodes/ExprListNode.java
@@ -0,0 +1,61 @@
+package ast.nodes;
+
+import ast.types.*;
+import java.util.ArrayList;
+import semanticanalysis.SemanticError;
+import semanticanalysis.SymbolTable;
+
+/**
+ * Node for the `expr_list` statement of the grammar.
+ */
+public class ExprListNode implements Node {
+
+ private final ArrayList<Node> exprs;
+
+ public ExprListNode(ArrayList<Node> _exprs) {
+ this.exprs = _exprs;
+ }
+
+ @Override
+ public ArrayList<SemanticError> checkSemantics(SymbolTable ST, int _nesting) {
+ ArrayList<SemanticError> errors = new ArrayList();
+
+ for (var param : exprs) {
+ errors.addAll(param.checkSemantics(ST, _nesting));
+ }
+
+ return errors;
+ }
+
+ public int getSize() {
+ return exprs.size();
+ }
+
+ public Node getElem(int i) {
+ return exprs.get(i);
+ }
+
+ @Override
+ public Type typeCheck() {
+ return new VoidType();
+ }
+
+ // TODO: code generation for expr list
+ @Override
+ public String codeGeneration() {
+ return "";
+ }
+
+ @Override
+ public String toPrint(String prefix) {
+ String str = prefix + "Paramlist\n";
+
+ prefix += " ";
+ for (var param : exprs) {
+ str += param.toPrint(prefix);
+ }
+
+ return str;
+ }
+
+}
diff --git a/src/ast/nodes/ForStmtNode.java b/src/ast/nodes/ForStmtNode.java
index 28fe783..610d0a0 100644
--- a/src/ast/nodes/ForStmtNode.java
+++ b/src/ast/nodes/ForStmtNode.java
@@ -1,20 +1,20 @@
package ast.nodes;
+import ast.types.*;
import java.util.ArrayList;
-
import semanticanalysis.SemanticError;
import semanticanalysis.SymbolTable;
-import ast.types.*;
/**
* Node for the `for_stmt` statement of the grammar.
*/
public class ForStmtNode implements Node {
- private Node exprList;
+
+ private ExprListNode exprList;
private Node block;
public ForStmtNode(Node exprList, Node block) {
- this.exprList = exprList;
+ this.exprList = (ExprListNode) exprList;
this.block = block;
}
@@ -22,9 +22,7 @@ public class ForStmtNode implements Node {
public ArrayList<SemanticError> checkSemantics(SymbolTable ST, int _nesting) {
ArrayList<SemanticError> errors = new ArrayList<SemanticError>();
- ExprNode expr = (ExprNode) exprList;
-
- ST.insert(expr.getId(), expr.typeCheck(), _nesting, "");
+ // ST.insert(expr.getId(), expr.typeCheck(s), _nesting, "");
errors.addAll(exprList.checkSemantics(ST, _nesting));
errors.addAll(block.checkSemantics(ST, _nesting));
diff --git a/src/ast/nodes/ParamdefNode.java b/src/ast/nodes/ParamdefNode.java
index 5164537..adadf72 100644
--- a/src/ast/nodes/ParamdefNode.java
+++ b/src/ast/nodes/ParamdefNode.java
@@ -12,7 +12,7 @@ import semanticanalysis.SymbolTable;
public class ParamdefNode extends AtomNode {
public ParamdefNode(String val) {
- super(val);
+ super(val, null);
}
@Override
diff --git a/src/ast/nodes/TestlistCompNode.java b/src/ast/nodes/TestlistCompNode.java
new file mode 100644
index 0000000..070b1a1
--- /dev/null
+++ b/src/ast/nodes/TestlistCompNode.java
@@ -0,0 +1,61 @@
+package ast.nodes;
+
+import ast.types.*;
+import java.util.ArrayList;
+import semanticanalysis.SemanticError;
+import semanticanalysis.SymbolTable;
+
+/**
+ * Node for the `testlist_comp` statement of the grammar.
+ */
+public class TestlistCompNode implements Node {
+
+ private final ArrayList<Node> exprs;
+
+ public TestlistCompNode(ArrayList<Node> _exprs) {
+ this.exprs = _exprs;
+ }
+
+ @Override
+ public ArrayList<SemanticError> checkSemantics(SymbolTable ST, int _nesting) {
+ ArrayList<SemanticError> errors = new ArrayList();
+
+ for (var param : exprs) {
+ errors.addAll(param.checkSemantics(ST, _nesting));
+ }
+
+ return errors;
+ }
+
+ public int getSize() {
+ return exprs.size();
+ }
+
+ public Node getElem(int i) {
+ return exprs.get(i);
+ }
+
+ @Override
+ public Type typeCheck() {
+ return new VoidType();
+ }
+
+ // TODO: code generation for expr list
+ @Override
+ public String codeGeneration() {
+ return "";
+ }
+
+ @Override
+ public String toPrint(String prefix) {
+ String str = prefix + "Testlist_comp\n";
+
+ prefix += " ";
+ for (var param : exprs) {
+ str += param.toPrint(prefix);
+ }
+
+ return str;
+ }
+
+}
diff --git a/test/trailers.py b/test/trailers.py
new file mode 100644
index 0000000..278a2d4
--- /dev/null
+++ b/test/trailers.py
@@ -0,0 +1,13 @@
+
+def mult(nums):
+ ret = []
+ for a, b in nums:
+ ret.append(a * b)
+ return ret
+
+print(mult([(2, 4), (5, 2)]))
+
+
+# left, right = 1, 2
+# print(left)
+# print(right)