/*
* This file is part of the OpenJML project.
* Author: David R. Cok
*/
package org.jmlspecs.openjml;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import com.sun.tools.javac.parser.Tokens.ITokenKind;
import com.sun.tools.javac.tree.JCTree;
/**
* This class defines the scanner tokens that represent JML syntax.
*
* @author David Cok
*/
// These are represented as enums. I'm not sure that is the best design since,
// although Enums are nice, they are not extensible. That is how Token is
// implemented, and we could not extend that.
// TODO - we should think about how to re-design JmlToken so that it is extensible.
public enum JmlTokenKind implements ITokenKind {
// STARTJMLCOMMENT("<JMLSTART>"),
ENDJMLCOMMENT("<JMLEND>"),
// These are statement types
ASSUME("assume"), // Keep this one first of the method statement tokens
ASSERT("assert"),
COMMENT("comment"), // For comments in BasicBlock programs
HAVOC("havoc"), // Just used in ESC
DEBUG("debug"),
SET("set"),
DECREASES("decreases"),
LOOP_INVARIANT("loop_invariant"),
HENCE_BY("hence_by"),
REFINING("refining"),
REACHABLE("reachable"),
UNREACHABLE("unreachable"), // Keep this one last of the method statement tokens
// These are modifiers
PURE("pure",org.jmlspecs.annotation.Pure.class), // Keep this one the first of the modifiers (see the modifiers Map below)
CODE_JAVA_MATH("code_java_math",org.jmlspecs.annotation.CodeJavaMath.class),
CODE_SAFE_MATH("code_safe_math",org.jmlspecs.annotation.CodeSafeMath.class),
EXTRACT("extract",org.jmlspecs.annotation.Extract.class),
GHOST("ghost",org.jmlspecs.annotation.Ghost.class),
IMMUTABLE("immutable",org.jmlspecs.annotation.Immutable.class), // FIXME - this is an extension - comment
INSTANCE("instance",org.jmlspecs.annotation.Instance.class),
MODEL("model",org.jmlspecs.annotation.Model.class),
NONNULL("non_null",org.jmlspecs.annotation.NonNull.class),
NULLABLE("nullable",org.jmlspecs.annotation.Nullable.class),
NULLABLE_BY_DEFAULT("nullable_by_default",org.jmlspecs.annotation.NullableByDefault.class),
NON_NULL_BY_DEFAULT("non_null_by_default",org.jmlspecs.annotation.NonNullByDefault.class), // TODO: In some code, but not in JML
FUNCTION("function",org.jmlspecs.annotation.Function.class),
HELPER("helper",org.jmlspecs.annotation.Helper.class),
UNINITIALIZED("uninitialized",org.jmlspecs.annotation.Uninitialized.class),
MONITORED("monitored",org.jmlspecs.annotation.Monitored.class),
OPTIONS(null,org.jmlspecs.annotation.Options.class),
PEER("peer",org.jmlspecs.annotation.Peer.class),
READONLY("readonly",org.jmlspecs.annotation.Readonly.class),
REP("rep",org.jmlspecs.annotation.Rep.class),
SKIP_ESC("skipesc",org.jmlspecs.annotation.SkipEsc.class),
SKIP_RAC("skiprac",org.jmlspecs.annotation.SkipRac.class),
SPEC_BIGINT_MATH("spec_bigint_math",org.jmlspecs.annotation.SpecBigintMath.class),
SPEC_JAVA_MATH("spec_java_math",org.jmlspecs.annotation.SpecJavaMath.class),
SPEC_SAFE_MATH("spec_safe_math",org.jmlspecs.annotation.SpecSafeMath.class),
SPEC_PUBLIC("spec_public",org.jmlspecs.annotation.SpecPublic.class),
SPEC_PROTECTED("spec_protected",org.jmlspecs.annotation.SpecProtected.class),
CODE_BIGINT_MATH("code_bigint_math",org.jmlspecs.annotation.CodeBigintMath.class), // Keep this one the last of the standard modifiers (see the modifiers Map below)
QUERY("query",org.jmlspecs.annotation.Query.class), // FIXME - this is an extension - comment
SECRET("secret",org.jmlspecs.annotation.Secret.class), // FIXME - this is an extension - comment
LAST("_",null), // This is a fake entry that is the end of the standard+extension modifiers list
// These are class/interface clause types
INVARIANT("invariant"),
INITIALLY("initially"),
CONSTRAINT("constraint"),
AXIOM("axiom"),
REPRESENTS("represents"),
JMLDECL("jml declaration"), // not a scannable token
IN("in"),
MAPS("maps"),
INITIALIZER("initializer"),
STATIC_INITIALIZER("static_initializer"),
MONITORS_FOR("monitors_for"),
READABLE("readable"),
WRITABLE("writable"),
// These are related to specification cases
ALSO("also"), // Keep this one first
NORMAL_BEHAVIOR("normal_behavior"),
BEHAVIOR("behavior"),
EXCEPTIONAL_BEHAVIOR("exceptional_behavior"),
ABRUPT_BEHAVIOR("abrupt_behavior"),
NORMAL_EXAMPLE("normal_example"),
EXAMPLE("example"),
EXCEPTIONAL_EXAMPLE("exceptional_example"),
MODEL_PROGRAM("model_program"),
IMPLIES_THAT("implies_that"),
FOR_EXAMPLE("for_example"),
CODE("code"), // Keep this one last
// These are the method clause types
REQUIRES("requires"), // Keep this one first
ENSURES("ensures"),
SIGNALS("signals"),
SIGNALS_ONLY("signals_only"),
DIVERGES("diverges"),
WHEN("when"),
DURATION("duration"),
WORKING_SPACE("working_space"),
FORALL("forall"),
OLD("old"),
ASSIGNABLE("assignable"),
ACCESSIBLE("accessible"),
MEASURED_BY("measured_by"),
CALLABLE("callable"),
CAPTURES("captures"), // Keep this one last
// These are only in model programs
CHOOSE("choose"),
CHOOSE_IF("choose_if"),
BREAKS("breaks"),
CONTINUES("continues"),
OR("or"),
RETURNS("returns"),
// Other misc
CONSTRUCTOR("constructor"),
FIELD("field"),
METHOD("method"),
NOWARN("nowarn"),
// These are various tokens related to JML expressions
BSEXCEPTION("\\exception"), // This is for internal use only, so it is before \result
BSRESULT("\\result"), // Keep this one the first of the backslash tokens
BSEVERYTHING("\\everything"),
BSLOCKSET("\\lockset"),
BSINDEX("\\index"),
BSVALUES("\\values"),
BSNOTHING("\\nothing"),
BSSAME("\\same"),
BSNOTSPECIFIED("\\not_specified"),
BSDISTINCT("\\distinct"),
BSDURATION("\\duration"),
BSELEMTYPE("\\elemtype"),
BSERASURE("\\erasure"),
BSFRESH("\\fresh"),
BSINVARIANTFOR("\\invariant_for"),
BSISINITIALIZED("\\is_initialized"),
BSKEY("\\key"),
BSLBLANY("\\lbl"),
BSLBLNEG("\\lblneg"),
BSLBLPOS("\\lblpos"),
BSLET("\\let"),
BSMAX("\\max"),
BSNONNULLELEMENTS("\\nonnullelements"),
BSNOTASSIGNED("\\not_assigned"),
BSNOTMODIFIED("\\not_modified"),
BSOLD("\\old"),
BSONLYACCESSED("\\only_accessed"),
BSONLYASSIGNED("\\only_assigned"),
BSONLYCALLED("\\only_called"),
BSONLYCAPTURED("\\only_captured"),
BSPAST("\\past"),
BSPRE("\\pre"),
BSREACH("\\reach"),
BSSPACE("\\space"),
BSTYPEOF("\\typeof"),
BSTYPELC("\\type"),
BSWORKINGSPACE("\\working_space"),
BSBIGINT_MATH("\\bigint_math"),
BSJAVAMATH("\\java_math"),
BSSAFEMATH("\\safe_math"),
BSNOWARN("\\nowarn"),
BSNOWARNOP("\\nowarn_op"),
BSWARN("\\warn"),
BSWARNOP("\\warn_op"),
BSINTO("\\into"),
BSSUCHTHAT("\\such_that"),
BSPEER("\\peer"),
BSREADONLY("\\readonly"),
BSREP("\\rep"),
// These are quantifier types (also \max )
BSEXISTS("\\exists"),
BSFORALL("\\forall"),
BSMIN("\\min"),
BSNUMOF("\\num_of"),
BSPRODUCT("\\product"),
BSSUM("\\sum"),
// These are JML type literals
BSTYPEUC("\\TYPE"),
BSREAL("\\real"),
BSBIGINT("\\bigint"), // Keep this one the last of the backslash tokens
// These are JML operators (in expressions)
// Note that the jmloperators set relies on this ordering
EQUIVALENCE("<==>"),
INEQUIVALENCE("<=!=>"),
IMPLIES("==>"),
REVERSE_IMPLIES("<=="),
SUBTYPE_OF("<:"), // Operands are \TYPE values
JSUBTYPE_OF("<::"), // Operands are Class<?> values, used only internally
LOCK_LT("<#"),
LOCK_LE("<#="),
// Other special character combinations
DOT_DOT(".."),
LEFT_ARROW("<-"),
RIGHT_ARROW("->"),
INFORMAL_COMMENT("(*...*)"),
SPEC_GROUP_START("{|"),
SPEC_GROUP_END("|}"),
;
/** The canonical form of the token in text */
private String name;
/** The annotation class associated with this token (for modifiers only), if any */
//@ nullable
public Class<?> annotationType = null;
/** A human readable form of the token, and how it appears in text
* @return the canonical, printable form of the token (not the internal toString() form)
*/
public String internedName() { return name; }
/** Constructs an Enum instance using an empty string */
private JmlTokenKind() { this("",null); }
/** Constructs an Enum token from a string - not available to users
* @param s The string that will be the canonical form of the token
*/
private JmlTokenKind(String s) { this(s,null); }
/** Constructs an Enum token from a string and annotation type - not available to users.
* Any modifier token should use this constructor
* @param s The string that will be the canonical form of the token
*/
private JmlTokenKind(String s, Class<?> annotationType) {
this.name = s == null ? null : s.intern();
this.annotationType = annotationType;
}
/** This is a map from string to token for backslash tokens; the input string
* includes the initial backslash.
*/
public final static Map<String,JmlTokenKind> backslashTokens = new HashMap<String,JmlTokenKind>();
/** This is a map from string to token for all of the tokens, and includes defined synonyms. */
public final static Map<String,JmlTokenKind> allTokens = new HashMap<String,JmlTokenKind>();
/** This is a set of all the modifier tokens, defined so that it is quick
* and easy to test if a token is a modifier.
*/
public final static EnumSet<JmlTokenKind> modifiers = EnumSet.range(PURE,LAST); // BSREADONLY added below
public final static EnumSet<JmlTokenKind> extensions = EnumSet.range(CODE_BIGINT_MATH, LAST);
static {
extensions.remove(CODE_BIGINT_MATH); // This is not an extension - it marks the last of non-extensions
extensions.remove(LAST); // Not real - just marks the end of any extensions
}
public final static EnumSet<JmlTokenKind> jmloperators = EnumSet.range(EQUIVALENCE, LOCK_LE);
/** This is a set of the modifiers that may be used to characterize a type. */
public final static JmlTokenKind[] typeModifiers = new JmlTokenKind[]{NULLABLE,NONNULL,BSREADONLY};
/** This is a set of all of the tokens that begin method specification clauses,
* defined so that it is quick and easy to test for a given token.
*/
public final static EnumSet<JmlTokenKind> methodClauseTokens = EnumSet.range(REQUIRES,CAPTURES);
/** This is a set of all of the tokens that begin JML statements in the body of a method,
* defined so that it is quick and easy to test for a given token.
*/
public final static EnumSet<JmlTokenKind> methodStatementTokens = EnumSet.range(ASSUME,UNREACHABLE);
/** This is the set of tokens that can occur at the beginning of a specification case */
public final static EnumSet<JmlTokenKind> specCaseTokens = EnumSet.range(ALSO,CODE);
static {
for (JmlTokenKind t: EnumSet.range(BSEXCEPTION,BSBIGINT)) {
backslashTokens.put(t.internedName(),t);
}
for (JmlTokenKind t: JmlTokenKind.values()) {
allTokens.put(t.internedName(),t);
}
//allTokens.remove(BSEXCEPTION.internedName());
modifiers.add(BSREADONLY);
// the LAST token is fake and doesn't really need to be in the modifiers set
modifiers.remove(LAST);
// Synonyms
allTokens.put("modifies".intern(),ASSIGNABLE);
allTokens.put("modifiable".intern(),ASSIGNABLE);
allTokens.put("pre".intern(),REQUIRES);
allTokens.put("post".intern(),ENSURES);
allTokens.put("exsures".intern(),SIGNALS);
allTokens.put("behaviour".intern(),BEHAVIOR);
allTokens.put("exceptional_behaviour".intern(),EXCEPTIONAL_BEHAVIOR);
allTokens.put("normal_behaviour".intern(),NORMAL_BEHAVIOR);
allTokens.put("abrupt_behaviour".intern(),ABRUPT_BEHAVIOR);
allTokens.put("decreasing".intern(),DECREASES);
allTokens.put("maintaining".intern(),LOOP_INVARIANT);
}
}