From 1efee5e539631d384a15c54c3ac4780f48a54e8a Mon Sep 17 00:00:00 2001 From: bill Date: Mon, 1 Mar 2021 17:54:09 +0800 Subject: [PATCH] Fixed precedence on '-'. Passed additional tests. Comments on bad.py. Updated worklog. --- WORKLOG.md | 13 +++++++------ src/main/cup/chocopy/pa1/ChocoPy.cup | 13 +++++++++---- src/test/data/pa1/student_contributed/bad.py | 10 +++++++--- src/test/data/pa1/student_contributed/good.py | 4 +++- 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/WORKLOG.md b/WORKLOG.md index 5d30c78..68007bb 100644 --- a/WORKLOG.md +++ b/WORKLOG.md @@ -1,11 +1,9 @@ # Compiler Construction PA1 Worklog ## Team: -
Apoorva Ranade(ar6496) -
Sanjar Ahmadov(sa5640) -
Yinqi Sun(ys3540) -
+**Apoorva Ranade**(ar6496)   **Sanjar Ahmadov**(sa5640)   **Yinqi Sun**(ys3540)
+ ## Indentation: - A stack is maintained by the lexer to keep track of indentations. A count is accumulated for the number of whitespace characters before the first token. If the count changes from the previous line count, a stack operation is performed. If count increases, another value is added to the stack. If count decreases, the topmost value is popped from the stack. - The file: src/main/jflex/chocopy/pa1/ChocoPy.jflex, lines from 100 to 182, contain the code for the stack. @@ -13,8 +11,11 @@ ## Challenges: - Shift-reduce errors while parsing the grammar. One approach to fix is to change the grammar. We chose to fix this issue by adding a precedence as in the case of expr by adding right precedence for if and else. - - Handling errors was another challenge. This required debugging and small changes to program flow. - - Understanding the giving code was a small challenge and took some time before we could start coding. + - '-' can either be a minus operator or a negative sign, and these two have different precedence. We solved this by assigning '-' the correct precedence at the production rule where we know whether it is a minus operator or a negative sign. + - File: src/main/jflex/chocopy/pa1/ChocoPy.cup Line: 459 + - Handling errors was another challenge. This required debugging and small changes to program flow. It's also a collaborative effort between group members that completed different part of the project. + - Understanding the giving code was a small challenge since some parts are compiled into binary and it become harder for us to debug through the source code, therefore it took us some time before we could start coding. + - Differences between ChocoPy and Python sometimes get us confused. For example, ChocoPy doesn't allow a function body without any statements and global (unscoped) statements in between (class/function/variable) definitions. This made us fail tests that we didn't thought we should. We then thoroughly read the reference manual and make our implementation conform to the manual whenever we can. ## Improvements: - Added more tests to rigorously check program flow and indentation. diff --git a/src/main/cup/chocopy/pa1/ChocoPy.cup b/src/main/cup/chocopy/pa1/ChocoPy.cup index 1bcb484..44d7cfe 100644 --- a/src/main/cup/chocopy/pa1/ChocoPy.cup +++ b/src/main/cup/chocopy/pa1/ChocoPy.cup @@ -239,6 +239,7 @@ terminal String LBR; terminal String RBR; terminal String ARROW; terminal String IS; +terminal String UMINUS; /* Returned by the lexer for erroneous tokens. Since it does not appear in @@ -282,6 +283,7 @@ precedence left NOT; precedence nonassoc EQUAL, NEQ, LT, GT, LEQ, GEQ, IS; precedence left PLUS, MINUS; precedence left MUL, DIV, MOD; +precedence left UMINUS; precedence left DOT, COMMA, LBR, RBR; precedence right IF, ELSE; @@ -295,8 +297,11 @@ start with program; /* program */ program ::= program_head:d opt_stmt_list:s - {: RESULT = new Program(d.isEmpty() ? getLeft(s) : getLeft(d), - sxright, d, s, errors); + {: + ComplexSymbolFactory.Location left = d.isEmpty() ? getLeft(s) : getLeft(d); + if(left == null) + left = new ComplexSymbolFactory.Location(1,1); + RESULT = new Program(left, sxright, d, s, errors); :} ; @@ -400,7 +405,7 @@ else_body ::= ELSE:el COLON block:b {: RES simple_stmt ::= PASS:p {: RESULT = null; :} | expr:e {: RESULT = new ExprStmt(exleft, exright, e); :} | RETURN:r expr:e {: RESULT = new ReturnStmt(rxleft, exright, e); :} - | RETURN {: RESULT = null; :} + | RETURN:r {: RESULT = new ReturnStmt(rxleft, rxright, null); :} | opt_target:ot expr:e {: RESULT = new AssignStmt(getLeft(ot), exright, ot, e); :} ; @@ -451,7 +456,7 @@ pexpr ::= identifier:id {: RESULT = id; :} | pexpr:p1 MUL:bo pexpr:p2 {: RESULT = new BinaryExpr(p1xleft, p2xright, p1, bo, p2); :} | pexpr:p1 DIV:bo pexpr:p2 {: RESULT = new BinaryExpr(p1xleft, p2xright, p1, bo, p2); :} | pexpr:p1 MOD:bo pexpr:p2 {: RESULT = new BinaryExpr(p1xleft, p2xright, p1, bo, p2); :} - | MINUS:m pexpr:p {: RESULT = new UnaryExpr(mxleft, pxright, m, p); :} + | MINUS:m pexpr:p {: RESULT = new UnaryExpr(mxleft, pxright, m, p); :} %prec UMINUS ; expr_list ::= expr:e {: RESULT = single(e); :} diff --git a/src/test/data/pa1/student_contributed/bad.py b/src/test/data/pa1/student_contributed/bad.py index 68e3773..95bf0f0 100644 --- a/src/test/data/pa1/student_contributed/bad.py +++ b/src/test/data/pa1/student_contributed/bad.py @@ -4,8 +4,10 @@ def fun5(): c = 6 def fun6(): print("Hello") - c = 4 + 5 + c = 4 + 5 # Indentation error +# Global statements in between definitions +# (not allowed in the language manual) if True: if True: print("Hello") @@ -16,11 +18,11 @@ if True: else: print("Again") else: - print("And Again") + print("And Again") # Unmatched Else class Thor(object): y:int = 0 - print("Right place?") + print("Right place?") # Statement in class class Stones(object): y:int = 0 @@ -30,6 +32,8 @@ class Stones(object): return 2+3 print("Wrong Place") +# Functions without `statements' +# (not allowed in the language manual) def fun1(): def fun2(): print("Hello") diff --git a/src/test/data/pa1/student_contributed/good.py b/src/test/data/pa1/student_contributed/good.py index 093076f..874fa40 100644 --- a/src/test/data/pa1/student_contributed/good.py +++ b/src/test/data/pa1/student_contributed/good.py @@ -73,8 +73,10 @@ f.bar(4) a=[[[1],[2]],[[3],[4]]] print(a[0][0][1]*a[1][1][0]) -multiline_string="Hi World, +multiline_string="Hi World,\ Here I am" +expr_precedence = -a + b * (c + d) + stone="Blue" print(get_stones(stone)) \ No newline at end of file