Index: java/Framclipse/com.framsticks.framclipse/src/com/framsticks/framclipse/FramScript.xtext
===================================================================
--- java/Framclipse/com.framsticks.framclipse/src/com/framsticks/framclipse/FramScript.xtext	(revision 437)
+++ java/Framclipse/com.framsticks.framclipse/src/com/framsticks/framclipse/FramScript.xtext	(revision 440)
@@ -1,3 +1,3 @@
-grammar com.framsticks.framclipse.FramScript with org.eclipse.xtext.common.Terminals
+grammar com.framsticks.framclipse.FramScript with org.eclipse.xtext.common.Terminals hidden(SL_COMMENT, ML_COMMENT, WS)
 
 import "http://www.eclipse.org/emf/2002/Ecore" as ecore
@@ -54,24 +54,26 @@
 	'prop:'
 	headers += PropertyHeader*
-	'id:' name=ID 
+	'id:' name=ID
 	headers += PropertyHeader+
 	;
-	
+
 State :
-	'state:' 
+	'state:'
 	headers += PropertyHeader*
-	'id:' name=ID 
+	'id:' name=ID
 	headers += PropertyHeader+
 	;
-	
+
 Include : {Include}
-	code=Code?
-	(properties+=Property |
-	states+=State)*
+	(
+		code=Code?
+		(properties+=Property |
+		states+=State)*
+	) | {Block} statements+=Statement+
 ;
-	
+
 Header :
-	name=ID value=HEADER_VALUE ;
-	
+	name=HEADER_ID value=HEADER_VALUE ;
+
 NeuroHeader returns Header :
 {IntHeader}		name=('prefinputs:' | 'prefoutput:' | 'preflocation:' | 'vhints:') intValue=IntValue |
@@ -79,32 +81,33 @@
 {IconHeader}	name='icon:~' icon=Icon '~' |
 				Header ;
-				
-Icon : 
+
+Icon :
 	INT (',' INT)+ ;
-	
+
 PropertyHeader returns Header :
 	TypeHeader |
 	FlagsHeader |
 	Header ;
-	
+
 ShowHeader returns Header :
-	name='expdef:' value=ID |
+	name='expdef:' importURI=ID |
 	Header ;
-	
+
 FlagsHeader returns Header :
 {IntHeader}	name='flags:' intValue=INT ;
-	
+
 TypeHeader :
-	name='type:' type=PropertyType ;
-	
+	name=TYPE_HEADER type=PropertyType ;
+
+// This terminal is defined separately for use with FramScriptAuxiliaryLexer.
+terminal TYPE_HEADER : 'type:';
+
 PropertyType :
-	name=ID (min=Number (max=Number default=Number?)? enums+=ENUM_LITERAL* )? ;
-	
-terminal ENUM_LITERAL :
-	'~' !('~'|'\r'|'\n')+ ;
-
-Number :
-	'-'? (INT | DOUBLE) ;
-	
+	name=ID (min=Number max=Number default=(Number|HEADER_VALUE)? enums+=ENUM_LITERAL* )? ;
+
+Number : IntNumber | DoubleNumber ;
+IntNumber : '-'? INT ;
+DoubleNumber : '-'? DOUBLE ;
+
 CodeSection returns Code :
 	'code:~' Code '~' ;
@@ -123,12 +126,21 @@
 IncludeDeclaration :
 	'@include' importURI=STRING ;
-	
+
+/*
+ * For some reason, the '#include' keyword is not matched.
+ * It is possible it has been overshadowed by SL_COMMENT,
+ * despite the order in which the two have been defined.
+ * This has been worked around in FramScriptAuxiliaryLexer.
+ */
 PropertyIncludeDeclaration :
-	'#include' importURI=STRING ;
-	
+	PROP_INCLUDE importURI=STRING ;
+
+// keyword separated for use in FramScriptAuxiliaryLexer
+terminal PROP_INCLUDE : '#include' ;
+
 Block :
-{Block}	'{' statements+=Statement* '}' ;
-	
-Statement :	
+	'{' statements+=Statement+ '}' ;
+
+Statement :
 	( VariableDeclarationStatement |
 	ExpressionStatement |
@@ -145,4 +157,5 @@
 	WhileStatement |
 	ForStatement |
+	ForEachStatement |
 {EmptyStatement} ';' ;
 
@@ -154,9 +167,16 @@
 	
 IfStatement :
-	'if' '(' condition=Expression ')' if=Statement ('else' else=Statement)? ;
-	
-ForStatement : 
-	'for' '(' init=Assignment? ';' condition=Expression? ';' step=Assignment? ')' body=Statement ;
-	
+	'if' '(' condition=Expression ')' if=Statement (=>'else' else=Statement)? ;
+
+ForStatement :
+	'for' '(' (init=Assignment | init=VariableDeclarationStatement)? ';' condition=Expression? ';' step=Assignment? ')' body=Statement ;
+
+ForEachStatement :
+	'for' '(' (decl=Iterator|ref=[VariableDeclaration]) 'in' colection=Expression ')' body=Statement ;
+
+Iterator returns VariableDeclaration :
+	'var' name=ID
+;
+
 WhileStatement :
 	'while' '(' condition=Expression ')' body=Statement ;
@@ -182,6 +202,6 @@
 SwitchStatement :
 	'switch' condition=ParExpression '{' labels+=SwitchGroup* '}' ;
-	
-SwitchGroup : 
+
+SwitchGroup :
 	label=SwitchLabel body=SwitchBlock ;
 	
@@ -206,62 +226,85 @@
 
 Expression :
-	UnaryExpression ({Expression.left=current} op=Operator right=Expression)? | 
+	UnaryExpression ({Expression.left=current} op=Operator right=Expression)? |
 	WildcardExpression ;
-	
-UnaryExpression  :
+
+UnaryExpression :
 	QualifiedExpression2 ({UnaryExpression.arg=current} op = IncrementOperator)? |
 	op = (IncrementOperator | UnaryOperator) arg = QualifiedExpression2 |
+	FunctionLiteral |
 	Literal ;
-	
+
 QualifiedExpression2 returns QualifiedExpression :
 	QualifiedExpression |
 	(PropertyAccess|StateAccess) ({QualifiedExpression.parent=current}'.' child=QualifiedExpression )? ;
-	
+
 QualifiedExpression :
-	ArrayElementExpression ({QualifiedExpression.parent=current}'.' child=QualifiedExpression )? ;
-	
+	MemberAccess ({QualifiedExpression.parent=current}'.' child=QualifiedExpression )? ;
+
+MemberAccess returns QualifiedExpression:
+	ArrayElementExpression ( {MemberAccess.left=current} '.[' child=Expression ']')? ;
+
 ArrayElementExpression :
 	TerminalExpression ({ArrayElementExpression.array=current} ('[' indexes+=Expression ']')+ )? ;
- 
+
 TerminalExpression:
+				Cast |
+				TypeOf |
 				Invocation |
 				Array |
-				Vector | 
+				Vector |
+				Dictionary |
 {VariableRef} 	var=[VariableDeclaration];
- 				
+
+Cast :
+	type=('int'|'float'|'string') '(' expression=Expression ')' ;
+
+TypeOf :
+	'typeof' '(' expression=Expression ')' ;
+
 Invocation :
 	function=[Function] '(' (args+=Expression (',' args+=Expression)*)? ')' ;
-	
+
 WildcardExpression :
 	value=ID '.*' ;
-	
+
 PropertyAccess returns QualifiedExpression :
-	('Fields.'|'ExpParams.'|'ShowParams.'|'VisParams.') property=[Property] ;
-	
+{PropertyAccess}	('Fields'|'ExpParams'|'ShowParams'|'VisParams') ('.*' | =>('.' property=[Property]) | '.[' (=>property=[Property|STRING] | child=Expression ) ']')? ;
+
 StateAccess returns QualifiedExpression :
-	'ExpState.' state=[State] ;
-	
+{StateAccess}	'ExpState' (".*" | =>('.' state=[State]) | '.[' (=>state=[State|STRING] | child=Expression ) ']')? ;
+
+FunctionLiteral:
+	'function' function=[Function] ;
+
 Literal:
-{IntLiteral}	value=IntValue | 
-{DoubleLiteral}	value=DoubleValue | 
-{StringLiteral}	value=STRING | 
-{HexLiteral}	value=HEX | 
+{IntLiteral}	value=IntValue |
+{DoubleLiteral}	value=DoubleValue |
+{StringLiteral}	value=STRING |
+{RawStringLiteral}	value=ML_STRING |
+{HexLiteral}	value=HEX |
 {NullLiteral}	'null' ;
 
 Array :
-	'[' elements+=Expression (',' elements+=Expression)* ']' ;
+{Array}	'[' (elements+=Expression (',' elements+=Expression)*)? ']' ;
 
 Vector  :
 	'(' elements+=Expression (',' elements+=Expression)* ')' ;
 
-Operator : 
-	'+' | '-' | '*'| '/' | 
+Dictionary :
+{Dictionary}	'{' ( keys+=DictKey values+=Expression (',' keys+=DictKey values+=Expression)* )? '}' ;
+
+DictKey :
+	STRING ':' ;
+
+Operator :
+	'+' | '-' | '*'| '/' |
 	'&'| '|' | '%' |
 	'==' | '!=' | '>=' | '<=' | '<' | '>' |
 	'&&' | '||' ;
-	
+
 UnaryOperator :
-	'!' | '+' | '-' | 'typeof';
-	
+	'!' | '+' | '-';
+
 IncrementOperator :
 	'++' | '--' ;
@@ -272,17 +315,51 @@
 DoubleValue hidden() :
 	('+'|'-')? DOUBLE ;
-	
-terminal DOUBLE : 
+
+terminal DOUBLE :
 	('0'..'9')*'.'('0'..'9')+ ('e' INT)? |
 	INT 'e' INT ;
-	
-terminal HEX : 
+
+terminal ENUM_LITERAL :
+	'~' !('~'|'\r'|'\n')+ ;
+
+terminal HEX :
 	'0x' (('0'..'9')|('a'..'f')|('A'..'F'))+ ;
-	
-terminal HEADER_VALUE : 
-	':' !('~'|' '|'\t'|'\r'|'\n') !('\n'|'\r')* ('\r'? '\n') |
-	':~' -> '~'('\r'? '\n') 
-	;
-	
-terminal SL_COMMENT : ('//' | '# ')  !('\n'|'\r')* ('\r'? '\n')?;
-
+
+terminal ML_STRING :
+	'"""' -> '"""' |
+	"'''" -> "'''"
+;
+
+terminal SL_COMMENT : ('//' | '#') -> NL ;
+
+terminal HEADER_ID :
+	(
+		'name' |
+		'longname' |
+		'description' |
+		'group' |
+		'help' |
+		'info' |
+		'neurons'
+	) ':'
+;
+
+/*
+ * This rule should not match anything,
+ * so expect an error when generating the artifacts.
+ * If it is not there, something went wrong.
+ * This rule is here just to make Xtext generate a constant
+ * to be used in a custom lexer (FramScriptAuriliaryLexer),
+ * which takes context into account,
+ * so it is able to recognise HEADER_VALUE
+ * without conflicting with Framscript code syntax.
+ * It should match the following rules,
+ * but only when preceded with HEADER_ID:
+ *	'~' NL ('\\~'|!'~')* '~' NL | -> NL,
+ * where NL is defined as: '\r' '\n'? | '\n',
+ * The final NL is not matched, but it is a part of context.
+ * This token is also emitted for the default value in PropertyType.
+ */
+terminal HEADER_VALUE : 'name:';
+
+terminal fragment NL : '\r' '\n'? | '\n' ;
