// syntactical clauses:
//note: the pattern \textit{[class_declaration]*} always matches with the parsed file,
//note: so the rule will continue in sequence in any case (supposing that no error has
//note: occurred into clause \textit{class_declaration}) and the end of file will be
//note: checked. If not reached, it doesn't write the message \samp{"file read successfully"},
world ::= #ignore(C++) [class_declaration]* #empty
			=> {
				traceLine("file parsed successfully");
				saveProject("Scripts/Tutorial/SolarSystem0.xml");
			};
//note: once keyword \samp{"class"} has been matched, there is no ambiguity : we are
//note: handling a class declaration and the rule must continue in sequence. To require
//note: that, instruction \samp{\#continue} is written after pattern \samp{"class"}.
//note: If a pattern of the sequence doesn't match the parsed file, the parser throws
//note: a syntax error automatically.
class_declaration ::= IDENT:"class" #continue
//note: the identifier that matches with clause call \textit{IDENT} is assigned to
//note: the local variable \samp{sClassName} : on contrary of other types of script,
//note: a new variable is considered as local, instead of an new attribute added to
//note: the current node \samp{\textbf{this}},
			IDENT:sClassName
//note: about parsing, classes are modeled into node
//note: \textbf{project.listOfClasses[}\textit{sClassName}\textbf{]}. Its attribute
//note: \samp{name} contains the value of \textit{sClassName}.
				=> insert project.listOfClasses[sClassName].name = sClassName;
//note: if the class inherits from a parent, \samp{\textbf{':'}} is necessary followed by
//note: an identifier (pattern \samp{\#continue}), and the identifier that matches with
//note: clause call \textit{IDENT} is assigned to the local variable \samp{sClassName},
			[':' #continue IDENT:sParentName
//note: this class inherits from a parent, so the optional attribute \samp{parent}
//note: of the class is populated with the value of \textit{sParentName},
				=> insert project.listOfClasses[sClassName].parent = sParentName;
			]?
			class_body(project.listOfClasses[sClassName]);
//note: clause \samp{class_body} expects an argument: the class node into which the
//note: class members must be described (\samp{myClass : \textbf{node}}),
class_body(myClass : node) ::= '{'
		[attribute_decl(myClass) | method_decl(myClass)]* '}';
//note: the class is populated with the characteristics of the attribute once 
//note: its declaration has finished. Otherwise, it may confuse with the beginning
//note: of a method declaration. To avoid this ambiguity, we should have factorized
//note: the type declaration and the name of the member into a common clause, for
//note: example.
attribute_decl(myClass : node) ::=
			=> local myType;
			type_specifier(myType) IDENT:sAttributeName ';'
			=> {
//note: about parsing, attributes are modeled into node
//note: \textbf{myClass.listOfAttributes[}\textit{sAttributeName}\textbf{]},
				insert myClass.listOfAttributes[sAttributeName].name = sAttributeName;
//note: the type is allocated on the stack, so it is copied into branch \samp{type}
//note: (no node reference) integrally,
				setall myClass.listOfAttributes[sAttributeName].type = myType;
			};
//note: the class is populated with the characteristics of the method once 
//note: the opened parenthesis is recognized,
method_decl(myClass : node) ::=
			=> local myType;
			[IDENT:"void" | type_specifier(myType)]
			IDENT:sMethodName '('
//note: from here, there is no doubt that we are parsing a method declaration,
			#continue
				=> {
//note: about parsing, methods are modeled into node
//note: \textbf{myClass.listOfMethods[}\textit{sMethodName}\textbf{]},
					insert myClass.listOfMethods[sMethodName].name = sMethodName;
//note: attribute \samp{name} is compulsory into a \textit{type} node, so if
//note: condition \samp{myType.name} returns \samp{false}, there is no return
//note: type (\samp{void}),
					if myType.name
						setall myClass.listOfMethods[sMethodName].type = myType;
				}
			[parameters_decl(myClass.listOfMethods[sMethodName])]? ')' ';';
parameters_decl(myMethod : node) ::=
				parameter(myMethod)
//note: a parameter declaration is expected after the comma,
				[',' #continue parameters_decl(myMethod)]*;
parameter(myMethod : node) ::=
			[parameter_mode]?:sMode
			=> local myType;
			type_specifier(myType)
			IDENT:sParameterName
				=> {
//note: about parsing, parameters are modeled into node
//note: \textbf{myMethod.listOfParameters[}\textit{sParameterName}\textbf{]},
					insert myMethod.listOfParameters[sParameterName].name = sParameterName;
					setall myMethod.listOfParameters[sParameterName].type = myType;
					if sMode {
						insert myMethod.listOfParameters[sParameterName].name = sMode;
					}
				};
parameter_mode ::= IDENT:{"in", "inout", "out"};
type_specifier(myType : node) ::=
	basic_type(myType)
//note: about parsing, \textbf{myType.isArray} contains \samp{true} if type is an array,
	['[' #continue ']' => insert myType.isArray = true; ]?;
basic_type(myType : node) ::=
//note: about parsing, \textbf{myType.name} contains the name of basic type,
	["int" | "boolean" | "double" | "string"]:myType.name
		|
	class_specifier(myType);
class_specifier(myType : node) ::=
//note: about parsing, \textbf{myType.isAggregation} contains \samp{true} if
//note: the object is aggregated,
	["aggregate" => insert myType.isAggregation = true; ]?
//note: about parsing, \textbf{myType.isObject} contains \samp{true} because
//note: this type is a class specifier,
	IDENT:myType.name => {insert myType.isObject = true; };

//note: the lexical clause \textit{IDENT} recognizes identifiers and might be replaced by
//note: the predefined clause \samp{\#readIdentifier}, which does the same work,
IDENT ::= #!ignore ['a'..'z'|'A'..'Z'|'_']
					['a'..'z'|'A'..'Z'|'_'|'0'..'9']*;
