Commits

Jesse McGrew committed cc2f1d4

Improved 'for', 'switch', ICL parsing
Added FLOAT to simple_constant
Use BLOCK for compound statements

Comments (0)

Files changed (4)

Rellor/Inform6.g3

 	GT='>';
 	LTE='<=';
 	GTE='>=';
+	EQEQ='==';
 	NOTEQ='~=';
 	BITAND='&';
 	BITOR='|';
 	PERCENT='%';
 	DOT='.';
 	DOTDOT='..';
+	SUPERCLASS='::';
 	HASH='#';
 	HASHHASH='##';
 	LPAREN='(';
 	INC='++';
 	DEC='--';
 	COLON=':';
+	QUESTION='?';
+	AT='@';
 
     // emitted by parser
     INT;
     ROUTINE;
     UNINITIALIZED;
 	OLD_OBJECTLOOP;
+	BLOCK;
+	CASE;
 
     OBJECT;
     NEARBY;
 
 property_value
     :	arg_expr
-    |	LSQUARE id* SEMI switch_statements RSQUARE
-        -> ^(ROUTINE[$LSQUARE] OMITTED ^(LOCALS id*)? switch_statements)
+    |	LSQUARE id* SEMI switch_body RSQUARE
+        -> ^(ROUTINE[$LSQUARE] OMITTED ^(LOCALS id*)? switch_body)
     ;
 
 id_not_seg
 		 $name = $n.text;}
 		STAR?
 		(l+=id {DefineLocalVar(l.Tree, $routineScope);})* SEMI
-		switch_statements
+		switch_body
 		RSQUARE
-        -> ^(ROUTINE[$LSQUARE] $n ^(FLAGS STAR?)? ^(LOCALS $l*)? switch_statements)
+        -> ^(ROUTINE[$LSQUARE] $n ^(FLAGS STAR?)? ^(LOCALS $l*)? switch_body)
     ;
 
 array_directive
     ;
 
 for_stmt
+	:	kFOR '(' for_exprs ')' statement
+		-> ^(kFOR for_exprs statement)
+	;
+
+for_exprs returns [bool used_semicolon]
 scope Quirks;
-@init { $Quirks::no_superclass = true; }
-    :	kFOR '(' (init=any_expr_opt)
-        { $Quirks::no_superclass = false; }
-        (	(':'|';') (cond=any_expr_opt) (':'|';') (inc=any_expr_opt) ')' statement
-            -> ^(kFOR $init $cond $inc statement)
-        |	'::' ')' statement
-            -> ^(kFOR $init OMITTED OMITTED statement)
-        )
-    ;
-
-any_expr_opt
-    :	any_expr
-    |	/* nothing */ -> OMITTED
-    ;
+	:	{$Quirks::no_superclass = true;}
+		(	init=any_expr
+			-> $init
+		|	/* nothing */
+			-> OMITTED
+		)
+		{$Quirks::no_superclass = false;}
+		(	('::' | (':' | ';' {$used_semicolon = true;}) (':' | ';' {$used_semicolon = true;}))
+			-> $for_exprs OMITTED
+		|	(':' | ';' {$used_semicolon = true;}) cond=any_expr (':' | ';' {$used_semicolon = true;})
+			-> $for_exprs $cond
+		)
+		(	step=any_expr
+			-> $for_exprs $step
+		|	/* nothing */
+			-> $for_exprs OMITTED
+		)
+	;
 
 objectloop_stmt
     :	(i5_objectloop_stmt)=> i5_objectloop_stmt
 	;
 
 switch_stmt
-    :	kSWITCH^ '('! any_expr ')'! '{'! switch_statements '}'!
+    :	kSWITCH^ '('! any_expr ')'! '{'! switch_body '}'!
     ;
 
-switch_statements
-    :	((case_label (','^ case_label)* ':'^)? statement)+
-    |	/* nada */ -> ';'
+switch_body
+    :	stmt_in_switch_body*
+		-> ^(BLOCK stmt_in_switch_body*)
     ;
 
-case_label
-    :	simple_constant (kTO^ simple_constant)?
+stmt_in_switch_body
+	:	case_label ':' statement
+		-> {$case_label.is_default}?	^(DEFAULT[$case_label.start] statement)
+		->								^(CASE case_label statement)
+	|	statement
+	;
+
+case_label returns [bool is_default]
+    :	kDEFAULT {$is_default = true;}
+	|	case_ranges
     ;
 
+case_ranges
+	:	case_range
+		(	(',' case_range)+
+			-> ^(OR case_range+)
+		|	/* no more */
+			-> case_range
+		)
+	;
+
+case_range
+	:	simple_constant
+		(	kTO simple_constant
+			-> ^(kTO simple_constant+)
+		|	/* no more */
+			-> simple_constant
+		)
+	;
+
 continue_stmt
     :	kCONTINUE ';'!
     ;
     ;
 
 block
-    :	'{'! statement+ '}'!
-    |	'{' '}' -> ';'
+    :	ob='{' statement+ '}'
+		-> ^(BLOCK[$ob] statement+)
+    |	ob='{' '}' -> SEMI[$ob]
     ;
 
 expr_stmt
     :	DEC_INT				-> INT<node=NumberTree>[$DEC_INT, ParseDecInt($DEC_INT.Text)]
     |	HEX_INT				-> INT<node=NumberTree>[$HEX_INT, ParseHexInt($HEX_INT.Text)]
     |	BIN_INT				-> INT<node=NumberTree>[$BIN_INT, ParseBinInt($BIN_INT.Text)]
+	|	FLOAT				-> INT<node=NumberTree>[$FLOAT, ParseFloat($FLOAT.Text)]
     |	CHAR_LITERAL		-> INT<node=NumberTree>[$CHAR_LITERAL, ParseCharLiteral($CHAR_LITERAL.Text)]
     ;
 

Rellor/Inform6.g3.lexer.cs

         public const int IclChannel = 3;
 
         private int keyword;
-        private bool allowIcl;
+        private bool allowIcl = true;
 
         public override Antlr.Runtime.IToken Emit()
         {
             Contract.Ensures(Contract.Result<Antlr.Runtime.IToken>() is RellorToken);
             Contract.Ensures(keyword == 0);
 
-            if (state.type != ICL_COMMENT)
+            if (state.type != ICL_COMMENT && state.type != WS)
                 allowIcl = false;
 
             RellorToken t = new RellorToken(input, state.type, state.channel, state.tokenStartCharIndex, CharIndex - 1)

Rellor/Inform6.g3.parser.cs

             return Convert.ToInt32(str.Substring(2), 2);
         }
 
+        private static int ParseFloat(string str)
+        {
+            Contract.Requires(str != null);
+            //XXX
+            throw new NotImplementedException();
+        }
+
         private static int ParseCharLiteral(string str)
         {
             Contract.Requires(str != null);

RellorC/Program.cs

     {
         static void Main(string[] args)
         {
-            const string SText = @"[ Main; (123-->456)(789); foo.bar(baz); (1-->4) = 5; ];";
+            const string SText =
+@"
+[ Main;
+    switch (foo) {
+        1: print 1;
+        2, 3: print 23;
+        4 to 6: print 456;
+        7, 9 to 10: print 7910;
+        default: print ""default"";
+    }
+];";
+/*@"
+[ Main;
+    for (::) 0; for (:;) 0;
+    for (1::) 1; for (1:;) 1;
+    for (:2:) 2;
+    for (1:2:) 3;
+    for (::4) 4; for (:;4) 4;
+    for (1::4) 5; for (1:;4) 5;
+    for (:2:4) 6;
+    for (1:2:4) 7;
+    for (x::y::z) super; for (x:y::z:t::w) super; for ((x::y):z:t) {super; class;}
+];";*/
 /*@"
 [ Main; hello(""world"");
     kitchen.general = 12345;