2
0
Эх сурвалжийг харах

expression parsing refactoring

Vladislav Folts 9 жил өмнө
parent
commit
ac4b9c1c78

BIN
bin/compiled.zip


+ 35 - 15
src/eberon/EberonContextExpression.ob

@@ -53,11 +53,20 @@ TYPE
     END;
     PSimpleList = POINTER TO SimpleList;
 
+    TermList = RECORD(ExpressionTree.TermList)
+    END;
+
+    ETFactor = RECORD(ExpressionTree.Factor)
+        PROCEDURE ETFactor(cx: ContextHierarchy.PNode);
+
+        cx: ContextHierarchy.PNode;
+    END;
+
     BeginTypePromotionAndMsg = RECORD(ContextHierarchy.Message)
         result: EberonTypePromotion.PCombined;
     END;
 
-    CurrentTypePromotionMsg = RECORD(ContextHierarchy.Message)
+    InvertTypePromotionMsg = RECORD(ContextHierarchy.Message)
         result: EberonTypePromotion.PMaybe;
     END;
 
@@ -254,8 +263,11 @@ BEGIN
         IF p # NIL THEN
             msg.result := p.makeOr();
         END;
-    ELSIF msg IS CurrentTypePromotionMsg THEN
-        msg.result := setTermTypePromotion(SELF);
+    ELSIF msg IS InvertTypePromotionMsg THEN
+        p <- setTermTypePromotion(SELF);
+        IF p # NIL THEN
+            p.invert()
+        END;
     ELSE
         result := SUPER(msg);
     END;
@@ -271,18 +283,6 @@ BEGIN
     END;
 END;
 
-PROCEDURE Factor.handleLogicalNot();
-BEGIN
-    SUPER();
-
-    msg <- CurrentTypePromotionMsg();
-    void <- SELF.handleMessage(msg);
-    p <- msg.result;
-    IF p # NIL THEN
-        p.invert();
-    END;
-END;
-
 PROCEDURE Ops.plus(type: Types.PType): ExpressionTree.BinaryOperator;
 VAR
     result: ExpressionTree.BinaryOperator;
@@ -442,6 +442,10 @@ BEGIN
     SUPER(op);
 END;
 
+PROCEDURE SimpleList.makeTerm(): ExpressionTree.PTermList;
+    RETURN NEW TermList();
+END;
+
 PROCEDURE SimpleList.addOp(op: STRING);
 BEGIN
     SUPER(op);
@@ -453,6 +457,22 @@ BEGIN
     END;
 END;
 
+PROCEDURE TermList.makeFactor(cx: ContextHierarchy.PNode): ExpressionTree.PFactor;
+    RETURN NEW ETFactor(cx);
+END;
+
+PROCEDURE ETFactor.ETFactor(cx: ContextHierarchy.PNode)
+    | cx(cx);
+END;
+
+PROCEDURE ETFactor.logicalNot();
+BEGIN
+    SUPER();
+
+    msg <- InvertTypePromotionMsg();
+    void <- SELF.cx.handleMessage(msg);
+END;
+
 BEGIN
     NEW(globalOps);
 END EberonContextExpression.

+ 31 - 44
src/ob/ContextExpression.ob

@@ -1,7 +1,7 @@
 MODULE ContextExpression;
 IMPORT 
     Chars, CodeGenerator, ConstValue, ContextHierarchy, 
-    Designator, Errors, Expression, ExpressionTree, Operator, 
+    Designator, Errors, Expression, ExpressionTree, 
     Procedure, Scope, String, Types;
 TYPE
     ExpressionHandler* = RECORD(ContextHierarchy.Node)
@@ -27,13 +27,12 @@ TYPE
     PFactor = POINTER TO Factor;
 
     Factor* = RECORD(ExpressionHandler)
-        PROCEDURE handleLogicalNot*();
+        PROCEDURE Factor*(parent: ContextHierarchy.PNode);
 
-        expression: Expression.PType;
-        logicalNot: BOOLEAN;
+        factor: ExpressionTree.PFactor;
     END;
 
-    Term* = RECORD(ExpressionHandler)
+    Term* = RECORD(ContextHierarchy.Node)
         PROCEDURE Term*(parent: ContextHierarchy.PNode); 
 
         list: ExpressionTree.PTermList;
@@ -81,17 +80,6 @@ TYPE
 VAR
     globalOps: ExpressionTree.POps;
 
-PROCEDURE promoteExpressionType(cx: ContextHierarchy.Root; left, right: Expression.PType);
-BEGIN
-    IF left # NIL THEN
-        rightType <- right.type();
-        leftType <- left.type();
-        IF (leftType # NIL) & (rightType # NIL) THEN
-            ExpressionTree.checkImplicitCast(cx, rightType, leftType);
-        END;
-    END;
-END;
-
 PROCEDURE ExpressionNode.ExpressionNode(parent: PExpressionHandler; node: ExpressionTree.PNode)
     | SUPER(parent),
       node(node);
@@ -145,6 +133,16 @@ PROCEDURE expressionFromConst(type: Types.PType; value: ConstValue.PType; code:
     RETURN Expression.make(code, type, NIL, value);
 END;
 
+PROCEDURE Factor.Factor(parent: ContextHierarchy.PNode)
+    | SUPER(parent);
+BEGIN
+    IF parent^ IS Factor THEN
+        SELF.factor := parent.factor;
+    ELSE
+        SELF.factor := parent^(Term).list.makeFactor(SELF(POINTER));
+    END;
+END; 
+
 PROCEDURE Factor.handleLiteral(s: STRING);
 BEGIN
     IF s = "NIL" THEN
@@ -154,53 +152,42 @@ BEGIN
     ELSIF s = "FALSE" THEN
         SELF.handleExpression(expressionFromConst(Types.basic.bool, NEW ConstValue.Int(0), "false"));
     ELSIF s = "~" THEN
-        SELF.handleLogicalNot();
+        SELF.factor.logicalNot();
     END;
 END;
 
-PROCEDURE Factor.handleLogicalNot();
-BEGIN
-    SELF.logicalNot := TRUE;
-END;
-
 PROCEDURE Factor.handleExpression(e: Expression.PType);
 BEGIN
-    SELF.expression := e;
+    SELF.factor.expression := e;
 END;
 
 PROCEDURE Factor.endParse(): BOOLEAN;
+VAR
+    const: ConstValue.PType;
 BEGIN
-    IF SELF.logicalNot THEN
-        ExpressionTree.notTypeId(SELF.expression);
-        ExpressionTree.checkTypeMatch(SELF.expression.type(), Types.basic.bool);
-        SELF.expression := Operator.not(SELF.expression);
+    IF SELF.factor.expression = NIL THEN
+        d <- SELF.attributes.designator;
+        info <- d.info();
+        IF info IS Types.PConst THEN
+            const := info.value;
+        END;
+        SELF.factor.expression := Expression.make(d.code(), d.type(), d, const);
+    END;
+
+    parent <- SELF.parent();
+    IF parent^ IS Term THEN
+        parent.list.addFactor(SELF.factor);
     END;
-    SELF.parent()^(ExpressionHandler).handleExpression(SELF.expression);
     RETURN TRUE;
 END;
 
 PROCEDURE Term.Term(parent: ContextHierarchy.PNode)
     | SUPER(parent),
-      list(NEW ExpressionTree.TermList());
+      list(parent(PSimpleExpression).list.makeTerm());
 END; 
 
-PROCEDURE Term.handleExpression(e: Expression.PType);
-BEGIN
-    SELF.list.addExpression(e);
-END;
-
 PROCEDURE Term.endParse(): BOOLEAN;
-VAR
-    const: ConstValue.PType;
 BEGIN
-    IF SELF.list.expression = NIL THEN
-        d <- SELF.attributes.designator;
-        info <- d.info();
-        IF info IS Types.PConst THEN
-            const := info.value;
-        END;
-        SELF.list.addExpression(Expression.make(d.code(), d.type(), d, const));
-    END;
     SELF.parent()(PSimpleExpression).list.addTerm(SELF.list);
     RETURN TRUE;
 END;

+ 44 - 10
src/ob/ExpressionTree.ob

@@ -27,9 +27,17 @@ TYPE
     END;
     POps* = POINTER TO Ops;
 
+    Factor* = RECORD
+    	PROCEDURE logicalNot*();
+
+    	not: BOOLEAN;
+        expression*: Expression.PType;
+    END;
+    PFactor* = POINTER TO Factor;
+
     PTermItemOp = POINTER TO TermItemOp;
     TermItem* = RECORD
-        expression-: Expression.PType;
+        factor: PFactor;
         next: PTermItemOp;
     END;
 
@@ -40,7 +48,8 @@ TYPE
     END;
 
     TermList* = RECORD (TermItem)
-        PROCEDURE addExpression*(e: Expression.PType);
+        PROCEDURE makeFactor*(cx: ContextHierarchy.PNode): PFactor;
+        PROCEDURE addFactor*(f: PFactor);
         PROCEDURE addOp*(op: STRING);
 
         last: PTermItemOp;
@@ -60,6 +69,7 @@ TYPE
     END;
 
     SimpleList* = RECORD (SimpleItem)
+        PROCEDURE makeTerm*(): PTermList;
         PROCEDURE addTerm*(t: PTermList);
         PROCEDURE addOp*(op: STRING);
 
@@ -233,7 +243,7 @@ BEGIN
         type.description() + "'");
 END;
 
-PROCEDURE checkTypeMatch*(from, to: Types.PType);
+PROCEDURE checkTypeMatch(from, to: Types.PType);
 BEGIN
     IF ~Cast.areTypesMatch(from, to) THEN
         throwTypeMismatch(from, to);
@@ -290,7 +300,7 @@ BEGIN
     RETURN result;
 END;
 
-PROCEDURE notTypeId*(e: Expression.PType);
+PROCEDURE notTypeId(e: Expression.PType);
 BEGIN
     d <- e.designator();
     IF d # NIL THEN
@@ -399,13 +409,24 @@ BEGIN
     RETURN o;
 END;
 
+PROCEDURE makeFromFactor*(f: Factor): Expression.PType;
+BEGIN
+    result <- f.expression;
+    IF f.not THEN
+        notTypeId(result);
+        checkTypeMatch(result.type(), Types.basic.bool);
+        result := Operator.not(result);
+    END;
+    RETURN result;
+END;
+
 PROCEDURE makeFromTermList(list: TermList; root: ContextHierarchy.Root): Expression.PType;
 BEGIN
-	result <- list.expression;
+	result <- makeFromFactor(list.factor^);
 	next <- list.next;
 	WHILE next # NIL DO
         notTypeId(result);
-		e <- next.expression;
+		e <- makeFromFactor(next.factor^);
         notTypeId(e);
         type <- result.type();
         o <- mulOp(next.op, type);
@@ -683,6 +704,11 @@ PROCEDURE Ops.plusExpect(): STRING;
     RETURN "numeric type or SET";
 END;
 
+PROCEDURE Factor.logicalNot();
+BEGIN
+    SELF.not := ~SELF.not;
+END;
+
 PROCEDURE TermItemOp.TermItemOp(op: STRING)
     | op(op);
 END;
@@ -695,12 +721,16 @@ PROCEDURE ItemOp.ItemOp(op: STRING)
     | op(op);
 END;
 
-PROCEDURE TermList.addExpression(e: Expression.PType);
+PROCEDURE TermList.makeFactor(cx: ContextHierarchy.PNode): PFactor;
+    RETURN NEW Factor();
+END;
+
+PROCEDURE TermList.addFactor(f: PFactor);
 BEGIN
-    IF SELF.expression = NIL THEN
-        SELF.expression := e;
+    IF SELF.factor = NIL THEN
+        SELF.factor := f;
     ELSE
-        SELF.last.expression := e;
+        SELF.last.factor := f;
     END;
 END;
 
@@ -715,6 +745,10 @@ BEGIN
     SELF.last := next;
 END;
 
+PROCEDURE SimpleList.makeTerm(): PTermList;
+    RETURN NEW TermList();
+END;
+
 PROCEDURE SimpleList.addTerm(t: PTermList);
 BEGIN
     IF SELF.term = NIL THEN

+ 1 - 1
test/expected/logical.js

@@ -6,7 +6,7 @@ b1 = b1 && b2;
 b1 = !b2;
 b1 = b1 && b2 || !b1;
 b1 = b2 && !b1;
-b1 = b2 || !!b1;
+b1 = b2 || b1;
 b1 = b2 || !!(b1 && b2);
 b1 = !b1 && !b2;
 }();

+ 6 - 2
test/test_unit.js

@@ -66,7 +66,10 @@ return {
          "+1",
          "p1()",
          "p1() + p1()",
-         "p2()"),
+         "p2()",
+         "~FALSE",
+         "~TRUE"
+         ),
     fail(["", "not parsed"],
          ["12a", "not parsed"],
          ["noResult()", "procedure returning no result cannot be used in an expression"],
@@ -77,7 +80,8 @@ return {
          ["-INTEGER", "type name 'INTEGER' cannot be used as an expression"],
          ["+INTEGER", "type name 'INTEGER' cannot be used as an expression"],
          ["~BOOLEAN", "type name 'BOOLEAN' cannot be used as an expression"],
-         ["INTEGER", "type name 'INTEGER' cannot be used as an expression"]
+         ["INTEGER", "type name 'INTEGER' cannot be used as an expression"],
+         ["~~INTEGER", "type name 'INTEGER' cannot be used as an expression"]
          )
     ),
 "string expression": testWithContext(