Browse Source
Property names parsed (but not used) and -test switch added (but no property/verify blocks yet).
Property names parsed (but not used) and -test switch added (but no property/verify blocks yet).
git-svn-id: https://www.prismmodelchecker.org/svn/prism/prism/trunk@3096 bbc10eb1-c90d-0410-af57-cb519fbb1720master
9 changed files with 624 additions and 167 deletions
-
235prism/src/parser/PrismParser.java
-
44prism/src/parser/PrismParser.jj
-
164prism/src/parser/ast/PropertiesFile.java
-
245prism/src/parser/ast/Property.java
-
12prism/src/parser/visitor/ASTTraverse.java
-
23prism/src/parser/visitor/ASTTraverseModify.java
-
1prism/src/parser/visitor/ASTVisitor.java
-
5prism/src/parser/visitor/TypeCheck.java
-
62prism/src/prism/PrismCL.java
@ -0,0 +1,245 @@ |
|||||
|
//============================================================================== |
||||
|
// |
||||
|
// Copyright (c) 2002- |
||||
|
// Authors: |
||||
|
// * Dave Parker <david.parker@comlab.ox.ac.uk> (University of Oxford) |
||||
|
// |
||||
|
//------------------------------------------------------------------------------ |
||||
|
// |
||||
|
// This file is part of PRISM. |
||||
|
// |
||||
|
// PRISM is free software; you can redistribute it and/or modify |
||||
|
// it under the terms of the GNU General Public License as published by |
||||
|
// the Free Software Foundation; either version 2 of the License, or |
||||
|
// (at your option) any later version. |
||||
|
// |
||||
|
// PRISM is distributed in the hope that it will be useful, |
||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
// GNU General Public License for more details. |
||||
|
// |
||||
|
// You should have received a copy of the GNU General Public License |
||||
|
// along with PRISM; if not, write to the Free Software Foundation, |
||||
|
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||
|
// |
||||
|
//============================================================================== |
||||
|
|
||||
|
package parser.ast; |
||||
|
|
||||
|
import java.util.regex.Matcher; |
||||
|
import java.util.regex.Pattern; |
||||
|
|
||||
|
import parser.type.*; |
||||
|
import parser.visitor.*; |
||||
|
import prism.PrismException; |
||||
|
import prism.PrismLangException; |
||||
|
import prism.PrismUtils; |
||||
|
|
||||
|
/** |
||||
|
* PRISM property, i.e. a PRISM expression plus other (optional info) such as name, comment, etc. |
||||
|
*/ |
||||
|
public class Property extends ASTElement |
||||
|
{ |
||||
|
/** PRISM expression representing property */ |
||||
|
private Expression expr; |
||||
|
/** Optional name for property (null if absent); */ |
||||
|
private String name; |
||||
|
/** Optional comment for property (null if absent); */ |
||||
|
private String comment; |
||||
|
|
||||
|
// Constructors |
||||
|
|
||||
|
public Property(Expression expr) |
||||
|
{ |
||||
|
this(expr, null, null); |
||||
|
} |
||||
|
|
||||
|
public Property(Expression expr, String name) |
||||
|
{ |
||||
|
this(expr, name, null); |
||||
|
} |
||||
|
|
||||
|
public Property(Expression expr, String name, String comment) |
||||
|
{ |
||||
|
this.expr = expr; |
||||
|
this.name = name; |
||||
|
this.comment = comment; |
||||
|
} |
||||
|
|
||||
|
// Mutators |
||||
|
|
||||
|
public void setExpression(Expression expr) |
||||
|
{ |
||||
|
this.expr = expr; |
||||
|
} |
||||
|
|
||||
|
public void setName(String name) |
||||
|
{ |
||||
|
this.name = name; |
||||
|
} |
||||
|
|
||||
|
public void setComment(String comment) |
||||
|
{ |
||||
|
this.comment = comment; |
||||
|
} |
||||
|
|
||||
|
// Accessors |
||||
|
|
||||
|
public Expression getExpression() |
||||
|
{ |
||||
|
return expr; |
||||
|
} |
||||
|
|
||||
|
public String getName() |
||||
|
{ |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
public String getComment() |
||||
|
{ |
||||
|
return comment; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Tests a result (specified as an object of the appropriate type: Boolean, Double, etc.) |
||||
|
* against the expected result for this Property, specified by an embedded "RESULT: xxx" |
||||
|
* string in the accompanying comment (immediately preceding it in the property specification). |
||||
|
* If the test fails or something else goes wrong, an explanatory PrismException is thrown. |
||||
|
* Otherwise, the method successfully exits, returning a boolean value that indicates |
||||
|
* whether or not a check was actually applied (i.e. if the result specification is of the |
||||
|
* form "RESULT: ?") then false is returned; otherwise true. |
||||
|
* @param result The actual result |
||||
|
* @return Whether or not the check was performed |
||||
|
*/ |
||||
|
public boolean checkAgainstExpectedResult(Object result) throws PrismException |
||||
|
{ |
||||
|
String strExpected = null; |
||||
|
Type type; |
||||
|
|
||||
|
// Extract expected result from comment |
||||
|
if (comment != null) { |
||||
|
Pattern p = Pattern.compile("RESULT:[ \t]*([^ \t\n\r]+)"); |
||||
|
Matcher matcher = p.matcher(comment); |
||||
|
if (matcher.find()) |
||||
|
strExpected = matcher.group(1); |
||||
|
if (matcher.find()) |
||||
|
throw new PrismException("Multiple RESULT specificiations for test"); |
||||
|
} |
||||
|
if (strExpected == null) { |
||||
|
throw new PrismException("Did not find RESULT specification to test against"); |
||||
|
} |
||||
|
|
||||
|
// Check for special "don't case" case |
||||
|
if (strExpected.equals("?")) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
// Check expected/actual result |
||||
|
type = expr.getType(); |
||||
|
|
||||
|
// Boolean-valued properties |
||||
|
if (type instanceof TypeBool) { |
||||
|
// Parse expected result |
||||
|
boolean boolExp; |
||||
|
strExpected = strExpected.toLowerCase(); |
||||
|
if (strExpected.equals("true")) |
||||
|
boolExp = true; |
||||
|
else if (strExpected.equals("false")) |
||||
|
boolExp = false; |
||||
|
else |
||||
|
throw new PrismException("Invalid RESULT specification \"" + strExpected + "\" for boolean-valued property"); |
||||
|
// Parse actual result |
||||
|
boolean boolRes; |
||||
|
if (!(result instanceof Boolean)) |
||||
|
throw new PrismException("Result is wrong type for (boolean-valued) property"); |
||||
|
boolRes = ((Boolean) result).booleanValue(); |
||||
|
if (boolRes != boolExp) |
||||
|
throw new PrismException("Wrong result (expected " + boolExp + ")"); |
||||
|
} |
||||
|
|
||||
|
// Integer-valued properties |
||||
|
else if (type instanceof TypeInt) { |
||||
|
// Parse expected result |
||||
|
int intExp; |
||||
|
try { |
||||
|
intExp = Integer.parseInt(strExpected); |
||||
|
} catch (NumberFormatException e) { |
||||
|
throw new PrismException("Invalid RESULT specification \"" + strExpected + "\" for integer-valued property"); |
||||
|
} |
||||
|
// Parse actual result |
||||
|
int intRes; |
||||
|
if (!(result instanceof Integer)) |
||||
|
throw new PrismException("Result is wrong type for (integer-valued) property"); |
||||
|
intRes = ((Integer) result).intValue(); |
||||
|
if (intRes != intExp) |
||||
|
throw new PrismException("Wrong result (expected " + intExp + ")"); |
||||
|
} |
||||
|
|
||||
|
// Double-valued properties |
||||
|
else if (type instanceof TypeDouble) { |
||||
|
// Parse expected result |
||||
|
double doubleExp; |
||||
|
try { |
||||
|
// See if it's a fraction |
||||
|
if (strExpected.matches("[0-9]+/[0-9]+")) { |
||||
|
int numer = Integer.parseInt(strExpected.substring(0, strExpected.indexOf('/'))); |
||||
|
int denom = Integer.parseInt(strExpected.substring(strExpected.indexOf('/') + 1)); |
||||
|
doubleExp = ((double) numer) / denom; |
||||
|
} |
||||
|
// Otherwise, just a double |
||||
|
else { |
||||
|
doubleExp = Double.parseDouble(strExpected); |
||||
|
} |
||||
|
} catch (NumberFormatException e) { |
||||
|
throw new PrismException("Invalid RESULT specification \"" + strExpected + "\" for double-valued property"); |
||||
|
} |
||||
|
// Parse actual result |
||||
|
double doubleRes; |
||||
|
if (!(result instanceof Double)) |
||||
|
throw new PrismException("Result is wrong type for (double-valued) property"); |
||||
|
doubleRes = ((Double) result).doubleValue(); |
||||
|
if (!PrismUtils.doublesAreCloseRel(doubleRes, doubleExp, 1e-5)) |
||||
|
throw new PrismException("Wrong result (expected " + doubleExp + ")"); |
||||
|
} |
||||
|
|
||||
|
// Unknown type |
||||
|
else { |
||||
|
throw new PrismException("Don't know how to test properties of type " + type); |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
// Methods required for ASTElement: |
||||
|
|
||||
|
/** |
||||
|
* Visitor method. |
||||
|
*/ |
||||
|
public Object accept(ASTVisitor v) throws PrismLangException |
||||
|
{ |
||||
|
return v.visit(this); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() |
||||
|
{ |
||||
|
// Note: don't print comment |
||||
|
String s = ""; |
||||
|
//if (comment != null) |
||||
|
//s += PrismParser.slashCommentBlock(comment); |
||||
|
if (name != null) |
||||
|
s += "\"" + name + "\": "; |
||||
|
s += expr; |
||||
|
return s; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Property deepCopy() |
||||
|
{ |
||||
|
Property prop = new Property(expr, name, comment); |
||||
|
prop.setPosition(this); |
||||
|
return prop; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
//------------------------------------------------------------------------------ |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue