📄 ocl.g
字号:
)? ;/* ------------------------------------ typeExpression ::= ("oclAsType" | "oclIsKindOf" | "oclIsTypeOf") LPAREN type RPAREN*/typeExpression[ASTExpression source, boolean followsArrow] returns [ASTTypeArgExpression n]{ ASTType t = null; n = null; }: { MyToken opToken = (MyToken) LT(1); } ( "oclAsType" | "oclIsKindOf" | "oclIsTypeOf" ) LPAREN t=type RPAREN { n = new ASTTypeArgExpression(opToken, source, t, followsArrow); } ;/* ------------------------------------ elemVarsDeclaration ::= idList [ ":" type ]*/elemVarsDeclaration returns [ASTElemVarsDeclaration n]{ List idList; ASTType t = null; n = null; }: idList=idList ( COLON t=type )? { n = new ASTElemVarsDeclaration(idList, t); } ;/* ------------------------------------ variableInitialization ::= id ":" type "=" expression*/variableInitialization returns [ASTVariableInitialization n]{ ASTType t; ASTExpression e; n = null; }: name:IDENT COLON t=type EQUAL e=expression { n = new ASTVariableInitialization((MyToken) name, t, e); } ;/* ------------------------------------ ifExpression ::= "if" expression "then" expression "else" expression "endif"*/ifExpression returns [ASTExpression n]{ ASTExpression cond, t, e; n = null; }: i:"if" cond=expression "then" t=expression "else" e=expression "endif" { n = new ASTIfExpression((MyToken) i, cond, t, e); } ;/* ------------------------------------ literal ::= "true" | "false" | INT | REAL | STRING | "#" id | collectionLiteral | emptyCollectionLiteral | undefinedLiteral | tupleLiteral*/literal returns [ASTExpression n]{ n = null; }: t:"true" { n = new ASTBooleanLiteral(true); } | f:"false" { n = new ASTBooleanLiteral(false); } | i:INT { n = new ASTIntegerLiteral((MyToken) i); } | r:REAL { n = new ASTRealLiteral((MyToken) r); } | s:STRING { n = new ASTStringLiteral((MyToken) s); } | HASH enumLit:IDENT { n = new ASTEnumLiteral((MyToken) enumLit); } | n=collectionLiteral | n=emptyCollectionLiteral | n=undefinedLiteral | n=tupleLiteral ;/* ------------------------------------ collectionLiteral ::= ( "Set" | "Sequence" | "Bag" ) "{" collectionItem { "," collectionItem } "}"*/collectionLiteral returns [ASTCollectionLiteral n]{ ASTCollectionItem ci; n = null; }: { MyToken op = (MyToken) LT(1); } ( "Set" | "Sequence" | "Bag" ) { n = new ASTCollectionLiteral(op); } LBRACE ci=collectionItem { n.addItem(ci); } ( COMMA ci=collectionItem { n.addItem(ci); } )* RBRACE ;/* ------------------------------------ collectionItem ::= expression [ ".." expression ]*/collectionItem returns [ASTCollectionItem n]{ ASTExpression e; n = new ASTCollectionItem(); }: e=expression { n.setFirst(e); } ( DOTDOT e=expression { n.setSecond(e); } )? ;/* ------------------------------------ emptyCollectionLiteral ::= "oclEmpty" "(" collectionType ")" Hack for avoiding typing problems with e.g. Set{}*/emptyCollectionLiteral returns [ASTEmptyCollectionLiteral n]{ ASTType t = null; n = null; }: "oclEmpty" LPAREN t=collectionType RPAREN { n = new ASTEmptyCollectionLiteral(t); } ;/* ------------------------------------ undefinedLiteral ::= "oclUndefined" "(" type ")" OCL extension*/undefinedLiteral returns [ASTUndefinedLiteral n]{ ASTType t = null; n = null; }: "oclUndefined" LPAREN t=type RPAREN { n = new ASTUndefinedLiteral(t); } ;/* ------------------------------------ tupleLiteral ::= "Tuple" "{" tupleItem { "," tupleItem } "}"*/tupleLiteral returns [ASTTupleLiteral n]{ ASTTupleItem ti; n = null; List tiList = new ArrayList(); }: "Tuple" LBRACE ti=tupleItem { tiList.add(ti); } ( COMMA ti=tupleItem { tiList.add(ti); } )* RBRACE { n = new ASTTupleLiteral(tiList); } ;/* ------------------------------------ tupleItem ::= id ":" expression*/tupleItem returns [ASTTupleItem n]{ ASTExpression e; n = null; }: name:IDENT COLON e=expression { n = new ASTTupleItem((MyToken) name, e); } ;/* ------------------------------------ type ::= simpleType | collectionType | tupleType*/type returns [ASTType n]{ n = null; }: { MyToken tok = (MyToken) LT(1); /* remember start of type */ } ( n=simpleType | n=collectionType | n=tupleType ) { n.setStartToken(tok); } ;/* ------------------------------------ simpleType ::= id A simple type may be a basic type (Integer, Real, Boolean, String), an enumeration type, an object type, or OclAny.*/simpleType returns [ASTSimpleType n]{ n = null; }: name:IDENT { n = new ASTSimpleType((MyToken) name); } ;/* ------------------------------------ collectionType ::= ( "Collection" | "Set" | "Sequence" | "Bag" ) "(" type ")"*/collectionType returns [ASTCollectionType n]{ ASTType elemType = null; n = null; }: { MyToken op = (MyToken) LT(1); } ( "Collection" | "Set" | "Sequence" | "Bag" ) LPAREN elemType=type RPAREN { n = new ASTCollectionType(op, elemType); } ;/* ------------------------------------ tupleType ::= "Tuple" "(" tuplePart { "," tuplePart } ")"*/tupleType returns [ASTTupleType n]{ ASTTuplePart tp; n = null; List tpList = new ArrayList(); }: "Tuple" LPAREN tp=tuplePart { tpList.add(tp); } ( COMMA tp=tuplePart { tpList.add(tp); } )* RPAREN { n = new ASTTupleType(tpList); } ;/* ------------------------------------ tuplePart ::= id ":" type*/tuplePart returns [ASTTuplePart n]{ ASTType t; n = null; }: name:IDENT COLON t=type { n = new ASTTuplePart((MyToken) name, t); } ;// ------------------------------------// OCL lexer// ------------------------------------{ import java.io.PrintWriter; import org.tzi.use.util.Log; import org.tzi.use.util.StringUtil; import org.tzi.use.parser.ParseErrorHandler; import org.tzi.use.parser.MyToken;}class GOCLLexer extends Lexer;options { importVocab=GOCL; // MyLexer.reportError depends on defaultErrorHandler == true for // providing correct column number information defaultErrorHandler = true; // don't automatically test all tokens for literals testLiterals = false; k = 2;}{ protected int fTokColumn = 1; private PrintWriter fErr; private ParseErrorHandler fParseErrorHandler; public void consume() throws CharStreamException { if (inputState.guessing == 0 ) { if (text.length() == 0 ) { // remember token start column fTokColumn = getColumn(); } } super.consume(); } public String getFilename() { return fParseErrorHandler.getFileName(); } protected Token makeToken(int t) { MyToken token = new MyToken(getFilename(), getLine(), fTokColumn); token.setType(t); if (t == EOF ) token.setText("end of file or input"); return token; } public void reportError(RecognitionException ex) { fParseErrorHandler.reportError( ex.getLine() + ":" + ex.getColumn() + ": " + ex.getMessage()); } /** * Returns true if word is a reserved keyword. */ public boolean isKeyword(String word) { ANTLRHashString s = new ANTLRHashString(word, this); boolean res = literals.get(s) != null; Log.trace(this, "keyword " + word + ": " + res); return res; } public void traceIn(String rname) throws CharStreamException { traceIndent(); traceDepth += 1; System.out.println("> lexer " + rname + ": c == '" + StringUtil.escapeChar(LA(1), '\'') + "'"); } public void traceOut(String rname) throws CharStreamException { traceDepth -= 1; traceIndent(); System.out.println("< lexer " + rname + ": c == '" + StringUtil.escapeChar(LA(1), '\'') + "'"); } public void init(ParseErrorHandler handler) { fParseErrorHandler = handler; }}// Whitespace -- ignoredWS: ( ' ' | '\t' | '\f' | ( "\r\n" | '\r' | '\n' ) { newline(); } ) { $setType(Token.SKIP); } ;// Single-line commentsSL_COMMENT: ("//" | "--") (~('\n'|'\r'))* ('\n'|'\r'('\n')?) { $setType(Token.SKIP); newline(); } ;// multiple-line commentsML_COMMENT: "/*" ( options { generateAmbigWarnings = false; } : { LA(2)!='/' }? '*' | '\r' '\n' { newline(); } | '\r' { newline(); } | '\n' { newline(); } | ~('*'|'\n'|'\r') )* "*/" { $setType(Token.SKIP); } ;// Use paraphrases for nice error messages//EOF options { paraphrase = "\"end of file\""; } : EOF;ARROW options { paraphrase = "'->'"; } : "->";AT options { paraphrase = "'@'"; } : '@';BAR options { paraphrase = "'|'"; } : '|';COLON options { paraphrase = "':'"; } : ':';COLON_COLON options { paraphrase = "'::'"; } : "::";COLON_EQUAL options { paraphrase = "':='"; } : ":=";COMMA options { paraphrase = "','"; } : ',';DOT options { paraphrase = "'.'"; } : '.';DOTDOT options { paraphrase = "'..'"; } : "..";EQUAL options { paraphrase = "'='"; } : '=';GREATER options { paraphrase = "'>'"; } : '>';GREATER_EQUAL options { paraphrase = "'>='"; } : ">=";HASH options { paraphrase = "'#'"; } : '#';LBRACE options { paraphrase = "'{'"; } : '{';LBRACK options { paraphrase = "'['"; } : '[';LESS options { paraphrase = "'<'"; } : '<';LESS_EQUAL options { paraphrase = "'<='"; } : "<=";LPAREN options { paraphrase = "'('"; } : '(';MINUS options { paraphrase = "'-'"; } : '-';NOT_EQUAL options { paraphrase = "'<>'"; } : "<>";PLUS options { paraphrase = "'+'"; } : '+';RBRACE options { paraphrase = "'}'"; } : '}';RBRACK options { paraphrase = "']'"; } : ']';RPAREN options { paraphrase = "')'"; } : ')';SEMI options { paraphrase = "';'"; } : ';';SLASH options { paraphrase = "'/'"; } : '/';STAR options { paraphrase = "'*'"; } : '*';protectedINT: ('0'..'9')+ ;protectedREAL: INT ( '.' INT )? ( ('e'|'E') ('+'|'-')? INT )? ;RANGE_OR_INT: ( INT ".." ) => INT { $setType(INT); } | ( INT '.' INT) => REAL { $setType(REAL); } | ( INT ('e'|'E')) => REAL { $setType(REAL); } | INT { $setType(INT); } ;// String literalsSTRING{ char c1; StringBuffer s = new StringBuffer(); }: '\'' { s.append('\''); } ( c1=ESC { s.append(c1); } | c2:~('\''|'\\') { s.append(c2); } )* '\'' { s.append('\''); } { $setText(s.toString()); } ;// escape sequence -- note that this is protected; it can only be called// from another lexer rule -- it will not ever directly return a token to// the parser// There are various ambiguities hushed in this rule. The optional// '0'...'7' digit matches should be matched here rather than letting// them go back to STRING_LITERAL to be matched. ANTLR does the// right thing by matching immediately; hence, it's ok to shut off// the FOLLOW ambig warnings.protectedESC returns [char c]{ c = 0; int h0,h1,h2,h3; }: '\\' ( 'n' { c = '\n'; } | 'r' { c = '\r'; } | 't' { c = '\t'; } | 'b' { c = '\b'; } | 'f' { c = '\f'; } | '"' { c = '"'; } | '\'' { c = '\''; } | '\\' { c = '\\'; } | ('u')+ h3=HEX_DIGIT h2=HEX_DIGIT h1=HEX_DIGIT h0=HEX_DIGIT { c = (char) (h0 + h1 * 16 + h2 * 16 * 16 + h3 * 16 * 16 * 16); } | o1:'0'..'3' { c = (char) Character.digit(o1, 8); } ( options { warnWhenFollowAmbig = false; } : o2:'0'..'7' { c = (char) (c * 8 + Character.digit(o2, 8)); } ( options { warnWhenFollowAmbig = false; } : o3:'0'..'7' { c = (char) (c * 8 + Character.digit(o3, 8)); } )? )? | d1:'4'..'7' { c = (char) Character.digit(d1, 8); } ( options { warnWhenFollowAmbig = false; } : d2:'0'..'7' { c = (char) (c * 8 + Character.digit(d2, 8)); } )? ) ;// hexadecimal digit (again, note it's protected!)protectedHEX_DIGIT returns [int n]{ n = 0; }: ( c1:'0'..'9' { n = Character.digit(c1, 16); } | c2:'A'..'F' { n = Character.digit(c2, 16); } | c3:'a'..'f' { n = Character.digit(c3, 16); } ) ;// An identifier. Note that testLiterals is set to true! This means// that after we match the rule, we look in the literals table to see// if it's a literal or really an identifer.IDENT options { testLiterals = true; paraphrase = "an identifier"; } : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')* ;// A dummy rule to force vocabulary to be all characters (except// special ones that ANTLR uses internally (0 to 2)protectedVOCAB: '\3'..'\377' ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -