4 using System.Collections;
\r
6 using Castle.Rook.Compiler.AST;
\r
7 using Castle.Rook.Compiler.Services;
\r
11 language = "CSharp";
\r
12 namespace = "Castle.Rook.Compiler.Parser";
\r
15 class RookBaseParser extends Parser;
\r
18 k = 2; // two token lookahead
\r
20 codeGenMakeSwitchThreshold = 2; // Some optimizations
\r
21 codeGenBitsetTestThreshold = 3;
\r
22 defaultErrorHandler = false; // Don't generate parser error handlers
\r
24 analyzerDebug = false;
\r
25 codeGenDebug = false;
\r
33 OPERATOR = "operator";
\r
36 TYPE; METHOD_CALL; SUPER_CTOR_CALL; POST_INC; POST_DEC; EXPR; ELIST; INDEX_OP;
\r
37 UNARY_MINUS; UNARY_PLUS; TYPECAST; ARRAY_DECLARATOR;
\r
38 NUM_INT; NUM_DOUBLE; NUM_FLOAT; NUM_LONG;
\r
43 public IErrorReport ErrorReport;
\r
45 private bool withinStatic, withinFinal, withinAbstract, withinNew, withinOverride;
\r
47 private ISymbolTable topLevelScope;
\r
49 AccessLevel currentAccessLevel = AccessLevel.Public;
\r
51 public override void reportError(RecognitionException ex)
\r
53 LexicalPosition lpos = new LexicalPosition( ex.getLine(), ex.getColumn() );
\r
55 ErrorReport.Error( ex.getFilename(), lpos, ex.Message );
\r
58 // TODO: Research for a better way to set lexical information
\r
60 private void SetLexical(IASTNode node, IToken t)
\r
62 node.Position.Line = t.getLine();
\r
63 node.Position.Column = t.getColumn();
\r
66 private Stack scopes = new Stack();
\r
68 private void PushScope(IASTNode node, ScopeType scopeType)
\r
70 if (node.DefiningSymbolTable != null)
\r
72 throw new ArgumentException("We can't override a scope");
\r
75 node.DefiningSymbolTable = new SymbolTable( GetCurrentScope(), scopeType );
\r
77 ISymbolTable scope = node.DefiningSymbolTable;
\r
79 if (scope == null) throw new ArgumentNullException("null scope?");
\r
84 private void PopScope()
\r
89 private ISymbolTable GetCurrentScope()
\r
91 if (scopes.Count == 0) return topLevelScope;
\r
93 return scopes.Peek() as ISymbolTable;
\r
97 qualified_name returns [String ident]
\r
98 { String name = String.Empty; ident = null; }
\r
100 t:IDENT { name = t.getText(); }
\r
101 ( options{greedy=true;}:
\r
103 DOT { name += "."; }
\r
105 COLONCOLON { name += "::"; }
\r
107 t2:IDENT { name += t2.getText(); }
\r
112 identifier returns [Identifier ident]
\r
113 { ident = null; TypeReference tr = null; }
\r
115 ident=name (tr=type { ident.TypeReference = tr; })?
\r
118 identifier_withtype returns [Identifier ident]
\r
119 { ident = null; TypeReference tr = null; }
\r
121 ident=name tr=type { ident.TypeReference = tr; }
\r
124 type returns [ TypeReference tr ]
\r
125 { tr = null; String n; }
\r
127 COLON n=qualified_name
\r
129 tr = new TypeReference(n);
\r
131 // (LBRACK RBRACK)? // We do not support multi-dimensional arrays yet
\r
134 name returns [Identifier ident]
\r
137 t1:IDENT { ident = new OpaqueIdentifier(t1.getText()); }
\r
139 t2:STATICIDENT { ident = new StaticVarIdentifier(t2.getText()); }
\r
141 t3:INSTIDENT { ident = new InstanceVarIdentifier(t3.getText()); }
\r
144 // qualified_symbol returns[String name]
\r
145 // { name = null; }
\r
147 // t:SYMBOL { name = t.getText().Substring(1); }
\r
148 // (options{greedy=true;}:DOT t2:IDENT { name += "." + t2.getText(); } )*
\r
154 (options { greedy=true; }:(STATEMENT_END | SEMI | EOF))
\r
160 (options { greedy=true; generateAmbigWarnings=false; }:(STATEMENT_END|EOF) )?
\r
163 sourceUnit[CompilationUnit cunit] returns[SourceUnit unit]
\r
165 topLevelScope = cunit.DefiningSymbolTable;
\r
166 unit = new SourceUnit(cunit, getFilename());
\r
167 PushScope(unit, ScopeType.SourceUnit);
\r
172 ("namespace" qualified_name) => namespace_declaration[unit.Namespaces]
\r
174 suite[unit.Statements]
\r
179 cunit.SourceUnits.Add(unit);
\r
181 if (!ErrorReport.HasErrors && scopes.Count != 0)
\r
182 ErrorReport.Error("Invalid scope count. " +
\r
183 "Something seems to be very wrong. Contact Castle's team and report the " +
\r
184 "code that caused this error.");
\r
188 namespace_declaration[IList namespaces]
\r
189 options { defaultErrorHandler=true; }
\r
191 NamespaceDescriptor nsdec = new NamespaceDescriptor();
\r
192 PushScope(nsdec, ScopeType.Namespace);
\r
193 namespaces.Add(nsdec); String qn = null;
\r
194 TypeDefinitionStatement typeDef = null;
\r
197 t:"namespace" qn=qualified_name statement_term
\r
198 { nsdec.Name = qn; }
\r
199 (typeDef=type_def_statement { nsdec.TypeDefinitions.Add(typeDef); } )*
\r
200 END { PopScope(); }
\r
204 { IStatement stmt = null; }
\r
206 (stmt=statement { if (stmt != null) stmts.Add(stmt); } )*
\r
209 type_suite[IList stmts]
\r
210 { IStatement stmt = null; }
\r
214 stmt=statement { if (stmt != null) stmts.Add(stmt); }
\r
216 method_scope[stmts]
\r
222 // def method <- will be static
\r
225 // class << override
\r
226 // def method <- will be override
\r
230 // def method <- will be new
\r
234 // def method <- will be final (not virtual or sealed)
\r
237 method_scope[IList stmts]
\r
238 { IStatement stmt = null; int index=0; }
\r
243 "self" { withinStatic = true; }
\r
245 "override" { index = 1; withinOverride = true; }
\r
247 "abstract" { index = 2; withinAbstract = true; }
\r
249 "new" { index = 3; withinNew = true; }
\r
251 "final" { index = 4; withinFinal = true; }
\r
256 (access_level stmt=statement { if (stmt != null) stmts.Add(stmt); } )*
\r
261 withinStatic = false;
\r
262 else if (index == 1)
\r
263 withinOverride = false;
\r
264 else if (index == 2)
\r
265 withinAbstract = false;
\r
266 else if (index == 3)
\r
268 else if (index == 4)
\r
269 withinFinal = false;
\r
277 "public"^ { currentAccessLevel = AccessLevel.Public; }
\r
279 "private"^ { currentAccessLevel = AccessLevel.Private; }
\r
281 "protected"^ { currentAccessLevel = AccessLevel.Protected; }
\r
283 "internal"^ { currentAccessLevel = AccessLevel.Internal; }
\r
285 /* nothing - inherits the access level defined previously */
\r
289 statement returns[IStatement stmt]
\r
293 (declaration_statement) => stmt=declaration_statement
\r
295 // property_def_statement
\r
297 // operator_def_statement
\r
299 stmt=type_def_statement
\r
301 // stmt=while_statement
\r
303 // stmt=until_statement
\r
305 // stmt=for_statement
\r
307 // stmt=if_statement
\r
309 // (unless_statement) => stmt=unless_statement
\r
311 stmt=expression_statement
\r
313 // stmt=return_statement
\r
315 stmt=require_statement
\r
320 declaration_statement returns [MultipleVariableDeclarationStatement stmt]
\r
322 stmt = new MultipleVariableDeclarationStatement(currentAccessLevel);
\r
323 Identifier ident = null;
\r
324 IExpression initExp = null;
\r
327 ident=identifier_withtype { stmt.AddIdentifier(ident); }
\r
329 COMMA ident=identifier_withtype { stmt.AddIdentifier(ident); }
\r
332 ASSIGN initExp=test { stmt.AddInitExp(initExp); }
\r
333 (COMMA initExp=test { stmt.AddInitExp(initExp); } )*
\r
337 constructor_def_statement returns [ConstructorDefinitionStatement mdstmt]
\r
339 mdstmt = new ConstructorDefinitionStatement( currentAccessLevel );
\r
344 LPAREN (methodParams[mdstmt])? RPAREN
\r
347 suite[mdstmt.Statements]
\r
351 method_def_statement returns [MethodDefinitionStatement mdstmt]
\r
353 mdstmt = new MethodDefinitionStatement( currentAccessLevel );
\r
354 String qn = null; TypeReference retType = null;
\r
357 DEF^ modifier[mdstmt] qn=qualified_name
\r
359 if (qn.StartsWith("self."))
\r
361 mdstmt.IsStatic = true;
\r
362 mdstmt.Name = qn.Substring( "self.".Length );
\r
368 PushScope(mdstmt, ScopeType.Method);
\r
371 LPAREN (methodParams[mdstmt])? RPAREN (retType=type)?
\r
374 { mdstmt.ReturnType = retType; }
\r
376 suite[mdstmt.Statements]
\r
383 modifier[MethodDefinitionStatement mdstmt]
\r
385 "override" { mdstmt.IsOverride = true; }
\r
387 { withinOverride }? { mdstmt.IsOverride = true; }
\r
389 "new" { mdstmt.IsNewSlot = true; }
\r
391 { withinNew }? { mdstmt.IsNewSlot = true; }
\r
393 "abstract" { mdstmt.IsAbstract = true; }
\r
395 { withinAbstract }? { mdstmt.IsAbstract = true; }
\r
397 "final" { mdstmt.IsFinal = true; }
\r
399 { withinFinal }? { mdstmt.IsFinal = true; }
\r
401 { withinStatic }? { mdstmt.IsStatic = true; }
\r
407 require_statement returns[RequireDirectiveStatement rd]
\r
408 { rd = null; String ident = null; }
\r
410 "require" ident=qualified_name { rd = new RequireDirectiveStatement(ident); }
\r
413 type_def_statement returns [TypeDefinitionStatement tdstmt]
\r
414 { tdstmt = null; currentAccessLevel = AccessLevel.Public; }
\r
416 tdstmt=class_def_statement
\r
419 class_def_statement returns [TypeDefinitionStatement tdstmt]
\r
420 { tdstmt = null; String qn = null; }
\r
421 // TODO: Create ClassDefinitionStatement
\r
422 // and support modifiers like visibility and abstract etc
\r
425 { tdstmt = new TypeDefinitionStatement( currentAccessLevel, t.getText() );
\r
426 PushScope(tdstmt, ScopeType.Type);
\r
428 ( (LTHAN|SL) qn=qualified_name { tdstmt.BaseTypes.Add( new TypeReference(qn) ); }
\r
429 (COMMA qn=qualified_name { tdstmt.BaseTypes.Add( new TypeReference(qn) ); } )*
\r
432 type_suite[tdstmt.Statements]
\r
433 END { PopScope(); }
\r
436 methodParams[MethodDefinitionStatement mdstmt]
\r
437 { ParameterVarIdentifier param = null; }
\r
439 param=methodParam { mdstmt.AddFormalParameter( param ); }
\r
440 (COMMA param=methodParam { mdstmt.AddFormalParameter( param ); } )*
\r
443 methodParam returns [ParameterVarIdentifier param]
\r
444 { IExpression exp = null; Identifier ident = null; param = null; }
\r
447 ident=identifier { param = ParameterVarIdentifier.FromIdentifier(ParameterType.Ordinary, ident); }
\r
449 (STAR identifier_withtype) => STAR ident=identifier_withtype
\r
450 { param = ParameterVarIdentifier.FromIdentifier(ParameterType.Params, ident); }
\r
452 STAR ident=identifier { param = ParameterVarIdentifier.FromIdentifier(ParameterType.List, ident); }
\r
454 BAND ident=identifier { param = ParameterVarIdentifier.FromIdentifier(ParameterType.Block, ident); }
\r
456 (ASSIGN exp=expression { param.InitExpression = exp; } )?
\r
459 expression_statement returns[IStatement stmt]
\r
460 { stmt = null; PostfixCondition pfc = null; IExpression exp = null; IExpression rhs = null;
\r
461 AugType rel = AugType.Undefined; }
\r
464 (compound) => exp=compound
\r
468 rel=augassign rhs=test { exp = new AugAssignmentExpression(exp, rhs, rel); }
\r
470 (ASSIGN rhs=test { exp = new AssignmentExpression(exp, rhs); } )+
\r
473 exp=flow_expressions
\r
476 pfc=postFixCondition
\r
477 { exp.PostfixCondition = pfc; }
\r
479 { stmt = new ExpressionStatement(exp); }
\r
481 stmt=method_def_statement
\r
483 stmt=constructor_def_statement
\r
486 augassign returns [AugType rel]
\r
487 { rel = AugType.Undefined; }
\r
488 : PLUS_ASSIGN { rel = AugType.PlusAssign; }
\r
489 | MINUS_ASSIGN { rel = AugType.MinusAssign; }
\r
490 | STAR_ASSIGN { rel = AugType.MultAssign; }
\r
491 | DIV_ASSIGN { rel = AugType.DivAssign; }
\r
492 | MOD_ASSIGN { rel = AugType.ModAssign; }
\r
493 | BAND_ASSIGN { rel = AugType.BitwiseAndAssign; }
\r
494 | BOR_ASSIGN { rel = AugType.BitwiseOrAssign; }
\r
495 | BXOR_ASSIGN { rel = AugType.BitwiseXorAssign; }
\r
496 // | LEFTSHIFTEQUAL
\r
497 // | RIGHTSHIFTEQUAL
\r
498 // | DOUBLESTAREQUAL
\r
499 // | DOUBLESLASHEQUAL
\r
502 postFixCondition returns[PostfixCondition pfc]
\r
503 { pfc = null; IExpression exp; }
\r
506 ("if" { pfc = new PostfixCondition(PostfixConditionType.If); }
\r
507 |"unless" { pfc = new PostfixCondition(PostfixConditionType.Unless); }
\r
508 |"while" { pfc = new PostfixCondition(PostfixConditionType.While); }
\r
509 |"until" { pfc = new PostfixCondition(PostfixConditionType.Until); }
\r
511 exp=test { pfc.Condition = exp; }
\r
515 compound returns[CompoundExpression cexp]
\r
516 { cexp = new CompoundExpression(); }
\r
518 (DO^|BEGIN^) { PushScope(cexp, ScopeType.Compound); }
\r
520 suite[cexp.Statements]
\r
521 END { PopScope(); }
\r
524 flow_expressions returns[IExpression exp]
\r
527 "redo" { exp = new RedoExpression(); }
\r
529 "break" { exp = new BreakExpression(); }
\r
531 "next" { exp = new NextExpression(); }
\r
533 "retry" { exp = new RetryExpression(); }
\r
541 lambda returns [LambdaExpression lexp]
\r
542 { BlockExpression bexp=null; lexp = null; }
\r
544 "lambda"^ bexp=block
\r
545 { lexp = new LambdaExpression(bexp); }
\r
548 block returns [BlockExpression bexp]
\r
549 { bexp = new BlockExpression(); }
\r
551 { PushScope(bexp, ScopeType.Block); }
\r
554 (DO nothing (blockargs[bexp])? (statement_term)? suite[bexp.Statements] END)
\r
556 (LCURLY nothing (blockargs[bexp])? (statement_term)? suite[bexp.Statements] RCURLY)
\r
561 raise returns [RaiseExpression rexp]
\r
562 { rexp = null; IExpression exp; }
\r
564 "raise" exp=expression { rexp = new RaiseExpression(exp); }
\r
567 yield returns [YieldExpression rexp]
\r
568 { rexp = new YieldExpression(); }
\r
570 "yield" expressionList[rexp.ExpColl]
\r
573 blockargs[BlockExpression bexp]
\r
574 { ParameterVarIdentifier ident = null; }
\r
576 BOR ident=methodParam
\r
577 { bexp.AddBlockFormalParameter(ident); }
\r
578 (options {greedy=true;}:COMMA ident=methodParam { bexp.AddBlockFormalParameter(ident); } )*
\r
583 test returns [IExpression exp]
\r
584 { exp = null; IExpression rhs = null; }
\r
586 // (block) => exp=block
\r
588 exp=and_test ("or" rhs=and_test { exp = new BinaryExpression(exp, rhs, BinaryOp.Or); })*
\r
597 and_test returns [IExpression exp]
\r
598 { exp = null; IExpression rhs = null; }
\r
600 exp=not_test ("and" rhs=not_test { exp = new BinaryExpression(exp, rhs, BinaryOp.And); })*
\r
603 not_test returns [IExpression exp]
\r
604 { exp = null; IExpression inner = null; }
\r
606 ("not"|LNOT) inner=not_test { exp = new UnaryExpression(inner, UnaryOp.Not); }
\r
611 comparison returns [IExpression exp]
\r
612 { exp = null; IExpression rhs = null; BinaryOp op = BinaryOp.Undefined; }
\r
614 exp=expression (op=comp_op rhs=expression { exp = new BinaryExpression(exp, rhs, op); } )*
\r
617 comp_op returns [BinaryOp op]
\r
618 { op = BinaryOp.Undefined; }
\r
620 LTHAN { op = BinaryOp.LessThan; }
\r
622 GT { op = BinaryOp.GreaterThan; }
\r
624 EQUAL { op = BinaryOp.Equal; }
\r
626 GE { op = BinaryOp.GreaterEqual; }
\r
628 LE { op = BinaryOp.LessEqual; }
\r
630 NOT_EQUAL { op = BinaryOp.NotEqual; }
\r
632 "is" { op = BinaryOp.IsA; }
\r
640 expressionList[IList expColl]
\r
641 { IExpression exp = null; }
\r
643 exp=expression { expColl.Add(exp); }
\r
644 (options {greedy=true;}:COMMA exp=expression { expColl.Add(exp); } )*
\r
647 expression returns [IExpression exp]
\r
648 { exp = null; IExpression rhs = null; }
\r
650 exp=xor_expr (BXOR rhs=xor_expr { exp = new BinaryExpression(exp, rhs, BinaryOp.Xor); })*
\r
653 xor_expr returns [IExpression exp]
\r
654 { exp = null; IExpression rhs = null; }
\r
656 exp=and_expr (options {greedy=true;}:BOR rhs=and_expr { exp = new BinaryExpression(exp, rhs, BinaryOp.Or2); })*
\r
659 and_expr returns [IExpression exp]
\r
660 { exp = null; IExpression rhs = null; }
\r
662 // shift_expr (BAND shift_expr)*
\r
663 exp=arith_expr (BAND rhs=arith_expr { exp = new BinaryExpression(exp, rhs, BinaryOp.And2); })*
\r
666 // shift_expr: arith_expr ((LEFTSHIFT|RIGHTSHIFT) arith_expr)*
\r
669 arith_expr returns [IExpression exp]
\r
670 { exp = null; IExpression rhs = null; }
\r
672 exp=term ((t:PLUS|MINUS) rhs=term { exp = new BinaryExpression(exp, rhs, t != null ? BinaryOp.Plus : BinaryOp.Minus); })*
\r
675 term returns [IExpression exp]
\r
676 { exp = null; IExpression rhs = null; BinaryOp op = BinaryOp.Undefined; }
\r
681 STAR { op = BinaryOp.Mult; }
\r
682 | SLASH { op = BinaryOp.Div; }
\r
683 | PERCENT { op = BinaryOp.Mod; }
\r
685 rhs=unary { exp = new BinaryExpression(exp, rhs, op); }
\r
689 unary returns [IExpression exp]
\r
690 { exp = null; IExpression inner = null; UnaryOp op = UnaryOp.Plus; }
\r
693 PLUS { op = UnaryOp.Plus; }
\r
694 | MINUS { op = UnaryOp.Minus; }
\r
695 | BNOT { op = UnaryOp.BitwiseNot; }
\r
697 inner=unary { exp = new UnaryExpression(inner, op); }
\r
702 primary returns [IExpression exp]
\r
705 exp=atom (exp=trailer[exp])*
\r
708 atom returns [IExpression exp]
\r
711 (range) => exp=range
\r
712 | LPAREN (exp=test)? RPAREN // LPAREN (testlist)? RPAREN
\r
713 | LBRACK (exp=listmaker)? RBRACK
\r
714 | LCURLY (exp=dictmaker)? RCURLY
\r
717 | "self" { exp = SelfReferenceExpression.Instance; }
\r
718 | "base" { exp = BaseReferenceExpression.Instance; }
\r
721 varref returns [VariableReferenceExpression vre]
\r
722 { Identifier ident = null; vre = null; }
\r
725 { vre = new VariableReferenceExpression(ident); }
\r
728 constantref returns [ConstExpression lre]
\r
732 { lre = new ConstExpression(t1.getText(), ConstExpressionType.IntLiteral); }
\r
734 { lre = new ConstExpression(t2.getText(), ConstExpressionType.LongLiteral); }
\r
736 { lre = new ConstExpression(t3.getText(), ConstExpressionType.FloatLiteral); }
\r
738 // { lre = new ConstExpression(t4.getText(), ConstExpressionType.SymbolLiteral); }
\r
739 | t5:STRING_LITERAL
\r
740 { lre = new ConstExpression(t5.getText(), ConstExpressionType.StringLiteral); }
\r
742 { lre = new ConstExpression(t6.getText(), ConstExpressionType.CharLiteral); }
\r
745 trailer[IExpression inner] returns [IExpression exp]
\r
746 { exp = null; BlockExpression temp = null; String qp = String.Empty; }
\r
749 { exp = new MethodInvocationExpression(inner); }
\r
750 (arglist[(exp as MethodInvocationExpression).Arguments])?
\r
759 // LBRACK subscriptlist RBRACK // TODO: Array/indexer access
\r
761 // (DOT|COLONCOLON) => qp=qualified_postfix { exp = new MemberAccessExpression(inner, qp); }
\r
762 COLONCOLON t1:IDENT { exp = new MemberAccessExpression(inner, t1.getText()); }
\r
764 DOT "nil?" { exp = new NullCheckExpression(inner); }
\r
766 DOT t:IDENT { exp = new MemberAccessExpression(inner, t.getText()); }
\r
769 range returns[IExpression rex]
\r
770 { rex = null; IExpression lhs = null; IExpression rhs = null; }
\r
772 LPAREN lhs=expression (t:DOTDOT|DOTDOTDOT) rhs=expression RPAREN
\r
773 { rex = new RangeExpression(lhs, rhs, t != null); }
\r
778 // subscript (options {greedy=true;}:COMMA subscript)*
\r
786 arglist[IList expcoll]
\r
787 { IExpression exp; }
\r
789 exp=argument { expcoll.Add(exp); }
\r
790 (options {greedy=true;}:COMMA exp=argument { expcoll.Add(exp); } )*
\r
793 ( STAR test (COMMA DOUBLESTAR test)?
\r
797 | STAR test (COMMA DOUBLESTAR test)?
\r
802 argument returns [IExpression exp]
\r
805 exp=test //(ASSIGN test)?
\r
808 listmaker returns [ListExpression exp]
\r
809 { exp = new ListExpression(); IExpression item; }
\r
813 (options {greedy=true;}:COMMA item=test { exp.Add(item); } )*
\r
816 dictmaker returns [DictExpression exp]
\r
817 { exp = new DictExpression(); IExpression key, value; }
\r
819 key=expression MAPASSIGN value=test
\r
820 { exp.Add(key, value); }
\r
821 (options {greedy=true;}:COMMA key=expression MAPASSIGN value=test
\r
822 { exp.Add(key, value); } )*
\r
828 class RookLexer extends Lexer;
\r
833 testLiterals=false; // don't automatically test for literals
\r
834 k=4; // four characters of lookahead
\r
835 charVocabulary='\u0003'..'\uFFFF';
\r
836 // without inlining some bitset tests, couldn't do unicode;
\r
837 codeGenBitsetTestThreshold=20;
\r
840 private int lastToken = 0;
\r
842 private int getProperType()
\r
845 if (lastToken == STATEMENT_END || lastToken == SEMI )
\r
847 result = Token.SKIP;
\r
851 result = STATEMENT_END;
\r
856 protected internal override IToken makeToken(int type) {
\r
858 return base.makeToken(type);
\r
873 DOTDOTDOT : "..." ;
\r
880 DIV_ASSIGN : "/=" ;
\r
882 PLUS_ASSIGN : "+=" ;
\r
885 MINUS_ASSIGN : "-=" ;
\r
888 STAR_ASSIGN : "*=" ;
\r
890 MOD_ASSIGN : "%=" ;
\r
892 SR_ASSIGN : ">>=" ;
\r
894 BSR_ASSIGN : ">>>=" ;
\r
898 SL_ASSIGN : "<<=" ;
\r
902 BXOR_ASSIGN : "^=" ;
\r
904 BOR_ASSIGN : "|=" ;
\r
907 BAND_ASSIGN : "&=" ;
\r
912 COLONCOLON : "::" ;
\r
915 options { paraphrase = "a new line"; }
\r
920 $setType(getProperType());
\r
923 (SL_NEWLINE | WS | SL_COMMENT)+
\r
928 options { paraphrase = "a new line"; }
\r
930 ( '\r' '\n' | '\n' | '\r')
\r
933 $setType(getProperType());
\r
935 ( (WS | SL_COMMENT)+ )?
\r
943 ( options {generateAmbigWarnings=false;}:
\r
953 options { paraphrase = "comments"; }
\r
955 ( options { greedy = true; }: ~('\n'|'\r'|'\uffff') )*
\r
956 {$setType(Token.SKIP); }
\r
961 ( options { greedy=true; }:' ' | '\t' | '\f' )+
\r
962 { $setType(Token.SKIP); }
\r
965 // multiple-line comments
\r
969 // ( /* '\r' '\n' can be matched in one alternative or by matching
\r
970 // '\r' in one iteration and '\n' in another. I am trying to
\r
971 // handle any flavor of newline that comes in, but the language
\r
972 // that allows both "\r\n" and "\r" and "\n" to all be valid
\r
973 // newline is ambiguous. Consequently, the resulting grammar
\r
974 // must be ambiguous. I'm shutting this warning off.
\r
977 // generateAmbigWarnings=false;
\r
980 // { LA(2)!='/' }? '*'
\r
981 // | '\r' '\n' {newline();}
\r
982 // | '\r' {newline();}
\r
983 // | '\n' {newline();}
\r
984 // | ~('*'|'\n'|'\r')
\r
987 // {$setType(Token.SKIP);}
\r
990 // character literals
\r
992 : '\'' ( ESC | ~'\'' ) '\''
\r
997 : '"' (ESC|~('"'|'\\'))* '"'
\r
1000 // escape sequence -- note that this is protected; it can only be called
\r
1001 // from another lexer rule -- it will not ever directly return a token to
\r
1003 // There are various ambiguities hushed in this rule. The optional
\r
1004 // '0'...'9' digit matches should be matched here rather than letting
\r
1005 // them go back to STRING_LITERAL to be matched. ANTLR does the
\r
1006 // right thing by matching immediately; hence, it's ok to shut off
\r
1007 // the FOLLOW ambig warnings.
\r
1019 | ('u')+ HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
\r
1023 warnWhenFollowAmbig = false;
\r
1028 warnWhenFollowAmbig = false;
\r
1036 warnWhenFollowAmbig = false;
\r
1043 // hexadecimal digit (again, note it's protected!)
\r
1046 : ('0'..'9'|'A'..'F'|'a'..'f')
\r
1049 // a dummy rule to force vocabulary to be all characters (except special
\r
1050 // ones that ANTLR uses internally (0 to 2)
\r
1057 options {testLiterals=true;}
\r
1058 : ('a'..'z'|'A'..'Z'|'_'|'$') ('a'..'z'|'A'..'Z'|'_'|'0'..'9'|'$')* ('?'|'!')?
\r
1076 // a numeric literal
\r
1079 {boolean isDecimal=false; Token t=null;}
\r
1080 : '.' {_ttype = DOT;}
\r
1081 ( ('0'..'9')+ (EXPONENT)? (f1:FLOAT_SUFFIX {t=f1;})?
\r
1083 if (t != null && t.getText().toUpperCase().indexOf('F')>=0) {
\r
1084 _ttype = NUM_FLOAT;
\r
1087 _ttype = NUM_DOUBLE; // assume double
\r
1092 | ( '0' {isDecimal = true;} // special case for just '0'
\r
1095 // the 'e'|'E' and float suffix stuff look
\r
1096 // like hex digits, hence the (...)+ doesn't
\r
1097 // know when to stop: ambig. ANTLR resolves
\r
1098 // it correctly by matching immediately. It
\r
1099 // is therefor ok to hush warning.
\r
1101 warnWhenFollowAmbig=false;
\r
1105 | ('0'..'7')+ // octal
\r
1107 | ('1'..'9') ('0'..'9')* {isDecimal=true;} // non-zero decimal
\r
1109 ( ('l'|'L') { _ttype = NUM_LONG; }
\r
1111 // only check to see if it's a float if looks like decimal so far
\r
1113 ( '.' ('0'..'9')* (EXPONENT)? (f2:FLOAT_SUFFIX {t=f2;})?
\r
1114 | EXPONENT (f3:FLOAT_SUFFIX {t=f3;})?
\r
1115 | f4:FLOAT_SUFFIX {t=f4;}
\r
1118 if (t != null && t.getText().toUpperCase() .indexOf('F') >= 0) {
\r
1119 _ttype = NUM_FLOAT;
\r
1122 _ttype = NUM_DOUBLE; // assume double
\r
1128 // a couple protected methods to assist in matching floating point numbers
\r
1132 ('e'|'E') ('+'|'-')? ('0'..'9')+
\r
1144 ( Int DOTDOT ) => Int {$setType(NUM_INT);}
\r
1146 ( Int DOTDOTDOT ) => Int {$setType(NUM_INT);}
\r
1149 '0' ('x' | 'X') ( '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' )+ {$setType(NUM_INT);} ('l' | 'L' {$setType(NUM_LONG);})?
\r
1151 // '0' Int {$setType(NUM_INT);}
\r
1153 // | ('l' | 'L') {$setType(NUM_LONG);}
\r
1156 Int {$setType(NUM_INT);}
\r
1158 FloatTrailer {$setType(NUM_FLOAT);}
\r
1160 ('l' | 'L') {$setType(NUM_LONG);}
\r
1162 // | // Int or float
\r
1163 // ( NonZeroDigit (Int)?
\r
1164 // ( ('l' | 'L') {$setType(NUM_LONG);}
\r
1165 // | FloatTrailer {$setType(NUM_FLOAT);}
\r
1166 // | {$setType(NUM_INT);}
\r
1169 // | '.' Int (Exponent)? {$setType(FLOAT);}
\r
1170 // | '.' {$setType(DOT);} // DOT (non number; e.g., field access)
\r
1174 Int : ( '0' .. '9' )+ ;
\r
1177 NonZeroDigit : '1' .. '9' ;
\r
1184 '.' Int (Exponent)?
\r
1191 : ('e' | 'E') ( '+' | '-' )? Int
\r
1194 /** Consume a newline and any whitespace at start of next line */
\r
1197 '\\' ('\r')? '\n' (' '|'\t')* { newline(); $setType(Token.SKIP); }
\r