From 7adcdbb2a09e447598e588ffbf1d229634ad622a Mon Sep 17 00:00:00 2001 From: tempiaa <tempiaa@eurecom.fr> Date: Fri, 12 Jun 2020 12:16:18 +0200 Subject: [PATCH] Added syntax check rules to AvaterExpression solvers, added tests --- .../AvatarExpressionAttribute.java | 12 + .../AvatarExpressionSolver.java | 259 ++++++++++++++---- .../AvatarExpressionTest.java | 39 ++- 3 files changed, 242 insertions(+), 68 deletions(-) diff --git a/src/main/java/avatartranslator/AvatarExpressionAttribute.java b/src/main/java/avatartranslator/AvatarExpressionAttribute.java index bcf8ffe035..290b018dd3 100644 --- a/src/main/java/avatartranslator/AvatarExpressionAttribute.java +++ b/src/main/java/avatartranslator/AvatarExpressionAttribute.java @@ -239,6 +239,18 @@ public class AvatarExpressionAttribute { } } + + public int getAttributeType() { + if (isState) { + return AvatarExpressionSolver.IMMEDIATE_BOOL; + } else if (block.getAttribute(accessIndex - SpecificationBlock.ATTR_INDEX).getType() == AvatarType.BOOLEAN) { + return AvatarExpressionSolver.IMMEDIATE_BOOL; + } else { + return AvatarExpressionSolver.IMMEDIATE_INT; + } + } + + public boolean isState() { return isState; } diff --git a/src/main/java/avatartranslator/AvatarExpressionSolver.java b/src/main/java/avatartranslator/AvatarExpressionSolver.java index e73a5c237c..d3bcceef3f 100644 --- a/src/main/java/avatartranslator/AvatarExpressionSolver.java +++ b/src/main/java/avatartranslator/AvatarExpressionSolver.java @@ -50,8 +50,10 @@ import avatartranslator.modelchecker.SpecificationState; * @version 1.0 17/04/2020 */ public class AvatarExpressionSolver { - private static final int IMMEDIATE_NO = 0; - private static final int IMMEDIATE_INT = 1; + protected static final int IMMEDIATE_NO = 0; + protected static final int IMMEDIATE_INT = 1; + protected static final int IMMEDIATE_BOOL = 2; + private AvatarExpressionSolver left, right; private char operator; @@ -59,7 +61,7 @@ public class AvatarExpressionSolver { private boolean isLeaf; //variable private boolean isNot; private boolean isNegated; - private int isImmediateValue; //0: No; 1: Boolean; 2: Int + private int isImmediateValue; //0: No; 1: Int; 2: Boolean; private int intValue; private AvatarExpressionAttribute leaf; @@ -93,6 +95,48 @@ public class AvatarExpressionSolver { public boolean buildExpression(AvatarSpecification spec) { boolean returnVal; + returnVal = buildExpressionRec(spec); + if (returnVal == false) { + return false; + } + + return checkIntegrity(); + } + + public boolean buildExpression(AvatarBlock block) { + boolean returnVal; + + returnVal = buildExpressionRec(block); + if (returnVal == false) { + return false; + } + + return checkIntegrity(); + } + + public boolean buildExpression() { + boolean returnVal; + + returnVal = buildExpressionRec(); + if (returnVal == false) { + return false; + } + + return checkIntegrity(); + } + + public boolean builExpression(AvatarExpressionAttribute attribute) { + this.expression = attribute.toString(); + isLeaf = true; + isImmediateValue = IMMEDIATE_NO; + leaf = attribute; + return true; + } + + + public boolean buildExpressionRec(AvatarSpecification spec) { + boolean returnVal; + removeUselessBrackets(); if (!expression.matches("^.+[\\+\\-<>=:;\\$&\\|\\*/].*$")) { @@ -103,11 +147,11 @@ public class AvatarExpressionSolver { checkNegatedNoBrackets(); if (expression.equals("true")) { intValue = 1; - isImmediateValue = IMMEDIATE_INT; + isImmediateValue = IMMEDIATE_BOOL; returnVal = true; } else if (expression.equals("false")) { intValue = 0; - isImmediateValue = IMMEDIATE_INT; + isImmediateValue = IMMEDIATE_BOOL; returnVal = true; } else if (expression.matches("-?\\d+")) { intValue = Integer.parseInt(expression); @@ -145,13 +189,13 @@ public class AvatarExpressionSolver { left = new AvatarExpressionSolver(leftExpression); right = new AvatarExpressionSolver(rightExpression); //System.out.println("Expression " + expression + " ; " + leftExpression + " ; " + rightExpression + "\n"); - returnVal = left.buildExpression(spec); - returnVal &= right.buildExpression(spec); + returnVal = left.buildExpressionRec(spec); + returnVal &= right.buildExpressionRec(spec); return returnVal; } - public boolean buildExpression(AvatarBlock block) { + public boolean buildExpressionRec(AvatarBlock block) { boolean returnVal; removeUselessBrackets(); @@ -164,11 +208,11 @@ public class AvatarExpressionSolver { checkNegatedNoBrackets(); if (expression.equals("true")) { intValue = 1; - isImmediateValue = IMMEDIATE_INT; + isImmediateValue = IMMEDIATE_BOOL; returnVal = true; } else if (expression.equals("false")) { intValue = 0; - isImmediateValue = IMMEDIATE_INT; + isImmediateValue = IMMEDIATE_BOOL; returnVal = true; } else if (expression.matches("-?\\d+")) { intValue = Integer.parseInt(expression); @@ -206,21 +250,14 @@ public class AvatarExpressionSolver { left = new AvatarExpressionSolver(leftExpression); right = new AvatarExpressionSolver(rightExpression); //System.out.println("Expression " + expression + " ; " + leftExpression + " ; " + rightExpression + "\n"); - returnVal = left.buildExpression(block); - returnVal &= right.buildExpression(block); + returnVal = left.buildExpressionRec(block); + returnVal &= right.buildExpressionRec(block); return returnVal; } - public boolean builExpression(AvatarExpressionAttribute attribute) { - this.expression = attribute.toString(); - isLeaf = true; - isImmediateValue = IMMEDIATE_NO; - leaf = attribute; - return true; - } - public boolean buildExpression() { + public boolean buildExpressionRec() { boolean returnVal; removeUselessBrackets(); @@ -233,11 +270,11 @@ public class AvatarExpressionSolver { checkNegatedNoBrackets(); if (expression.equals("true")) { intValue = 1; - isImmediateValue = IMMEDIATE_INT; + isImmediateValue = IMMEDIATE_BOOL; returnVal = true; } else if (expression.equals("false")) { intValue = 0; - isImmediateValue = IMMEDIATE_INT; + isImmediateValue = IMMEDIATE_BOOL; returnVal = true; } else if (expression.matches("-?\\d+")) { intValue = Integer.parseInt(expression); @@ -274,8 +311,8 @@ public class AvatarExpressionSolver { left = new AvatarExpressionSolver(leftExpression); right = new AvatarExpressionSolver(rightExpression); //System.out.println("Expression " + expression + " ; " + leftExpression + " ; " + rightExpression + "\n"); - returnVal = left.buildExpression(); - returnVal &= right.buildExpression(); + returnVal = left.buildExpressionRec(); + returnVal &= right.buildExpressionRec(); return returnVal; } @@ -346,43 +383,55 @@ public class AvatarExpressionSolver { for (i = 0, index = -1; i < expression.length(); i++) { a = expression.charAt(i); switch (a) { - case '=': + case '|': if (level == 0) { index = i; - priority = 2; + priority = 5; + } + break; + case '&': + if (level == 0 && priority < 5) { + index = i; + priority = 4; + } + break; + case '=': + if (level == 0 && priority < 4) { + index = i; + priority = 3; } subVar = true; break; case '$': - if (level == 0) { + if (level == 0 && priority < 4) { index = i; - priority = 2; + priority = 3; } subVar = true; break; case '<': - if (level == 0) { + if (level == 0 && priority < 3) { index = i; priority = 2; } subVar = true; break; case '>': - if (level == 0) { + if (level == 0 && priority < 3) { index = i; priority = 2; } subVar = true; break; case ':': - if (level == 0) { + if (level == 0 && priority < 3) { index = i; priority = 2; } subVar = true; break; case ';': - if (level == 0) { + if (level == 0 && priority < 3) { index = i; priority = 2; } @@ -400,12 +449,6 @@ public class AvatarExpressionSolver { priority = 1; } break; - case '|': - if (level == 0 && priority < 2) { - index = i; - priority = 1; - } - break; case '/': if (level == 0 && priority == 0) { index = i; @@ -416,11 +459,6 @@ public class AvatarExpressionSolver { index = i; } break; - case '&': - if (level == 0 && priority == 0) { - index = i; - } - break; case '(': level++; subVar = true; @@ -442,7 +480,7 @@ public class AvatarExpressionSolver { public int getResult() { int res; if (isLeaf) { - if (isImmediateValue == IMMEDIATE_INT) { + if (isImmediateValue != IMMEDIATE_NO) { res = intValue; } else { return 0; @@ -462,7 +500,7 @@ public class AvatarExpressionSolver { public int getResult(SpecificationState ss) { int res; if (isLeaf) { - if (isImmediateValue == IMMEDIATE_INT) { + if (isImmediateValue != IMMEDIATE_NO) { res = intValue; } else { res = leaf.getValue(ss); @@ -482,7 +520,7 @@ public class AvatarExpressionSolver { public int getResult(SpecificationState ss, AvatarStateMachineElement asme) { int res; if (isLeaf) { - if (isImmediateValue == IMMEDIATE_INT) { + if (isImmediateValue != IMMEDIATE_NO) { res = intValue; } else { res = leaf.getValue(ss, asme); @@ -502,7 +540,7 @@ public class AvatarExpressionSolver { public int getResult(SpecificationBlock sb) { int res; if (isLeaf) { - if (isImmediateValue == IMMEDIATE_INT) { + if (isImmediateValue != IMMEDIATE_NO) { res = intValue; } else { res = leaf.getValue(sb); @@ -573,8 +611,14 @@ public class AvatarExpressionSolver { if (isLeaf) { if (isImmediateValue == IMMEDIATE_NO) { retS = leaf.toString(); - } else { + } else if (isImmediateValue == IMMEDIATE_INT){ retS = String.valueOf(intValue); + } else { + if (intValue == 0) { + retS = "false"; + } else { + retS = "true"; + } } if (isNegated) { retS = "-(" + retS + ")"; @@ -646,6 +690,51 @@ public class AvatarExpressionSolver { } } + private boolean checkIntegrity() { + int optype, optypel, optyper; + boolean returnVal; + + if (isLeaf) { + if (isNot) { + return getReturnType() == IMMEDIATE_BOOL; + } else if (isNegated) { + return getReturnType() == IMMEDIATE_INT; + } else { + return true; + } + } + + optype = getType(); + optypel = left.getReturnType(); + optyper = right.getReturnType(); + + switch(optype) { + case IMMEDIATE_NO: + returnVal = false; //Error + break; + case IMMEDIATE_INT: + returnVal = (optypel == IMMEDIATE_INT && optyper == IMMEDIATE_INT) ? true : false; + break; + case IMMEDIATE_BOOL: + returnVal = (optypel == IMMEDIATE_BOOL && optyper == IMMEDIATE_BOOL) ? true : false; + break; + case 3: + returnVal = (optypel == optyper) ? true : false; + break; + default: + returnVal = false; + } + + if (returnVal == false) { + return false; + } + + returnVal = left.checkIntegrity(); + returnVal &= right.checkIntegrity(); + + return returnVal; + } + private void removeUselessBrackets() { while (expression.startsWith("(") && expression.endsWith(")")) { if (getClosingBracket(1) == expression.length() - 1) { @@ -673,5 +762,79 @@ public class AvatarExpressionSolver { } return -1; } + + private int getType() { + int optype; + + if (isLeaf) { + if (isImmediateValue == IMMEDIATE_NO) { + return leaf.getAttributeType(); + } else { + return isImmediateValue; + } + } + + switch (operator) { + case '=': + case '$': + optype = 3; //BOTH sides must have the same type + break; + case '<': + case '>': + case ':': + case ';': + case '-': + case '+': + case '/': + case '*': + optype = IMMEDIATE_INT; + break; + case '|': + case '&': + optype = IMMEDIATE_BOOL; + break; + default: + optype = IMMEDIATE_NO; //ERROR + break; + } + + return optype; + } + + private int getReturnType() { + int optype; + + if (isLeaf) { + if (isImmediateValue == IMMEDIATE_NO) { + return leaf.getAttributeType(); + } else { + return isImmediateValue; + } + } + + switch (operator) { + case '<': + case '>': + case ':': + case ';': + case '-': + case '+': + case '/': + case '*': + optype = IMMEDIATE_INT; + break; + case '|': + case '&': + case '=': + case '$': + optype = IMMEDIATE_BOOL; + break; + default: + optype = IMMEDIATE_NO; //ERROR + break; + } + + return optype; + } } diff --git a/ttool/src/test/java/avatartranslator/AvatarExpressionTest.java b/ttool/src/test/java/avatartranslator/AvatarExpressionTest.java index 7e1ad29cc7..d941e627c3 100644 --- a/ttool/src/test/java/avatartranslator/AvatarExpressionTest.java +++ b/ttool/src/test/java/avatartranslator/AvatarExpressionTest.java @@ -104,22 +104,21 @@ public class AvatarExpressionTest { @Test public void testImmediate() { AvatarExpressionSolver e1 = new AvatarExpressionSolver("10 + 15 >= 20"); - e1.buildExpression(); + assertTrue(e1.buildExpression()); AvatarExpressionSolver e2 = new AvatarExpressionSolver("-10 / 2 - 15 * 2 + 1 == -30 -4"); - e2.buildExpression(); + assertTrue(e2.buildExpression()); AvatarExpressionSolver e3 = new AvatarExpressionSolver("not(-10 / 2 - 15 * 2 + 1 == -(60 - 26))"); - e3.buildExpression(); + assertTrue(e3.buildExpression()); AvatarExpressionSolver e4 = new AvatarExpressionSolver("1 && 0 >= 1 || 0"); - e4.buildExpression(); + assertFalse(e4.buildExpression()); AvatarExpressionSolver e5 = new AvatarExpressionSolver("true and not(false) == not(false or false)"); - e5.buildExpression(); + assertTrue(e5.buildExpression()); AvatarExpressionSolver e6 = new AvatarExpressionSolver("10 -Cabin.match"); + assertFalse(e6.buildExpression()); assertTrue(e1.getResult() == 1); assertTrue(e2.getResult() == 1); assertTrue(e3.getResult() == 0); - assertTrue(e4.getResult() == 0); assertTrue(e5.getResult() == 1); - assertTrue(e6.buildExpression() == false); } @Test @@ -128,25 +127,25 @@ public class AvatarExpressionTest { specBlock.init(block1, false); AvatarExpressionSolver e1 = new AvatarExpressionSolver("x + y"); - e1.buildExpression(block1); + assertTrue(e1.buildExpression(block1)); AvatarExpressionSolver e2 = new AvatarExpressionSolver("-x / y - 15 * z + 1 == -31"); - e2.buildExpression(block1); + assertTrue(e2.buildExpression(block1)); AvatarExpressionSolver e3 = new AvatarExpressionSolver("not(-x / z - (x + y) * 2 + 1 >= -(60 - 26))"); - e3.buildExpression(block1); + assertTrue(e3.buildExpression(block1)); AvatarExpressionSolver e4 = new AvatarExpressionSolver("(key1==true) and (key2==false)"); - e4.buildExpression(block1); + assertTrue(e4.buildExpression(block1)); AvatarExpressionSolver e5 = new AvatarExpressionSolver("(key1) and (key2)"); - e5.buildExpression(block1); + assertTrue(e5.buildExpression(block1)); AvatarExpressionSolver e6 = new AvatarExpressionSolver("(key1==key1) or (key2==key1)"); - e6.buildExpression(block1); + assertTrue(e6.buildExpression(block1)); AvatarExpressionSolver e7 = new AvatarExpressionSolver("((key1==key1) and not(key2==key1)) and (x - y == z + 3)"); - e7.buildExpression(block1); + assertTrue(e7.buildExpression(block1)); AvatarExpressionSolver e8 = new AvatarExpressionSolver("x + x*(y+z)/(x + z - x)"); - e8.buildExpression(block1); + assertTrue(e8.buildExpression(block1)); AvatarExpressionSolver e9 = new AvatarExpressionSolver("x + x*(y+z)*(x - z)"); - e9.buildExpression(block1); + assertTrue(e9.buildExpression(block1)); AvatarExpressionSolver e10 = new AvatarExpressionSolver("x*((x + y)*z + (x+z)/z)/x"); - e10.buildExpression(block1); + assertTrue(e10.buildExpression(block1)); assertTrue(e1.getResult(specBlock) == 15); assertTrue(e2.getResult(specBlock) == 1); assertTrue(e3.getResult(specBlock) == 0); @@ -165,11 +164,11 @@ public class AvatarExpressionTest { ss.setInit(as, false); AvatarExpressionSolver e1 = new AvatarExpressionSolver("block1.x + block2.y"); - e1.buildExpression(as); + assertTrue(e1.buildExpression(as)); AvatarExpressionSolver e2 = new AvatarExpressionSolver("-block1.x / block1.y - 15 * block2.z + 1 == -46"); - e2.buildExpression(as); + assertTrue(e2.buildExpression(as)); AvatarExpressionSolver e3 = new AvatarExpressionSolver("not(-block2.x / block2.z - not(block1.x + block2.y) * -2 + -(1) <= -(-4 + 7))"); - e3.buildExpression(as); + assertFalse(e3.buildExpression(as)); assertTrue(e1.getResult(ss) == 17); assertTrue(e2.getResult(ss) == 1); assertTrue(e3.getResult(ss) == 0); -- GitLab