/// <summary> /// Process a given interchange element (chunk). /// </summary> /// <param name="processor"></param> /// <param name="node">Last node that was parsed. This is used for annotations.</param> /// <param name="chunk">Interchange chunk to be processed.</param> /// <returns>Returns the new interchange parse node (or null in case of error).</returns> protected virtual InterchangeUnitNode ProcessInterchangeElement(InterchangeFormatProcessor processor, InterchangeUnitNode node, InterchangeChunk chunk) { InterchangeFormatParser parser = this.GetInterchangeParser(chunk); InterchangeElementNode nodeForAnnotation = (node == null) ? null : node.GetAnnotatedNode(); node = parser.ParseInterchangeElement(nodeForAnnotation); if (node == null) { return(null); } return(node.FileIn(processor, chunk, chunk)); }
protected virtual AnnotationNode ParseAnnotation(InterchangeElementNode nodeForAnnotation) { // TODO : Move constants out of code into a the InterchangeFormatConstants class // TODO : Move error messages out of code into a the InterchangeFormatErrors class // PARSE: <annotation> ::= ’Annotation’ ’key:’ quotedString ’value:’ quotedString <elementSeparator> AnnotationNode result = this.CreateAnnotationNode(nodeForAnnotation); Token token = this.GetNextTokenxx(); StringToken str = token as StringToken; if (str == null) { this.ReportParserError(result, "Missing annotation key.", token); } result.Key = str; token = this.GetNextTokenxx(); KeywordToken cmd = token as KeywordToken; if ((cmd == null) || (cmd.Value != "value:")) { this.ReportParserError("Missing annotation #value: keyword.", token); } token = this.GetNextTokenxx(); str = token as StringToken; if (str == null) { this.ReportParserError(result, "Missing annotation value.", token); } result.Value = str; token = this.GetNextTokenxx(); if (!(token is EofToken)) { this.ReportParserError(result, "Unexpected code found after annotation value.", token); result.Key = null; // This is to avoid something like: Annotation key: 'x' value: 'y' crash: 'yes'. result.Value = null; // This is to avoid something like: Annotation key: 'x' value: 'y' crash: 'yes'. return(result); } return(result); }
protected internal virtual InterchangeUnitNode ParseInterchangeElement(InterchangeElementNode nodeForAnnotation) { // TODO : Move constants out of code into a the InterchangeFormatConstants class // TODO : Move error messages out of code into a the InterchangeFormatErrors class // PARSE: <interchangeElement> ::= <classDefinition> | <classInitialization> | <globalDefinition> | // <globalValueInitialization> | <poolDefinition> | <poolVariableDefinition> | <poolValueInitialization> | // <methodDefinition> | <classMethodDefinition> | <programInitialization> | comment <elementSeparator> // PARSE: The above definitions expand to: // ’Class’ ’named:’ <classNameString> .... <elementSeparator> // <className> ’initializer’ <elementSeparator> // ’Global’ ’variable:’ <globalNameString> <elementSeparator> // ’Global’ ’constant:’ <globalNameString> <elementSeparator> // <globalName> ’initializer’ <elementSeparator> // ’Pool’ ’named:’ <poolNameString> <elementSeparator> // <poolName> ’variable:’ <poolVariableNameString> <elementSeparator> // <poolName> ’constant:’ <poolVariableNameString> <elementSeparator> // <poolName> ’initializerFor:’ <poolVariableNameString> <elementSeparator> // <className> ’method’ <elementSeparator> // <className> ’classMethod’ <elementSeparator> // ’Global’ ’initializer’ <elementSeparator> // comment <elementSeparator> ... NB: This will NEVER be returned by GetNextTokenxx(). Token token = this.GetNextTokenxx(); if (token is EofToken) { return(null); // Most probably just a comment ... } // The abode syntax shows us that we are dealing with the following pattern: // identifier indetifier_or_keyword undefined_token* // Comments are ignored and discarded by GetNextTokenxx(). IdentifierToken id = token as IdentifierToken; if (id == null) { this.ReportParserError("Expected identifier.", token); return(null); } token = this.GetNextTokenxx(); IdentifierOrKeywordToken cmd = token as IdentifierOrKeywordToken; if (cmd == null) { this.ReportParserError("Expected identifier or keyword.", token); return(null); } // <classDefinition> ::= ’Class’ ’named:’ <classNameString> .... <elementSeparator> if ((id.Value == "Class") && (cmd.Value == "named:")) { return(this.ParseClassDefinition()); // Discard <id> and <cmd> } // <globalDefinition> ::= ’Global’ ’variable:’ <globalNameString> <elementSeparator> if ((id.Value == "Global") && (cmd.Value == "variable:")) { return(this.ParseGlobalVariableDefinition()); // Discard <id> and <cmd> } // <globalDefinition> ::= ’Global’ ’constant:’ <globalNameString> <elementSeparator> if ((id.Value == "Global") && (cmd.Value == "constant:")) { return(this.ParseGlobalConstantDefinition()); // Discard <id> and <cmd> } // <poolDefinition> ::= ’Pool’ ’named:’ <poolNameString> <elementSeparator> if ((id.Value == "Pool") && (cmd.Value == "named:")) { return(this.ParsePoolDefinition()); // Discard <id> and <cmd> } // <programInitialization> ::= ’Global’ ’initializer’ <elementSeparator> if ((id.Value == "Global") && (cmd.Value == "initializer")) { return(this.ParseProgramInitialization()); // Discard <id> and <cmd> } // <methodDefinition> ::= <className> ’method’ <elementSeparator> if (cmd.Value == "method") { return(this.ParseInstanceMethodDefinition(id)); // Discard <cmd> } // <classMethodDefinition> ::= <className> ’classMethod’ <elementSeparator> if (cmd.Value == "classMethod") { return(this.ParseClassMethodDefinition(id)); // Discard <cmd> } // <classInitialization> ::= <className> ’initializer’ <elementSeparator> // <globalValueInitialization> ::= <globalName> ’initializer’ <elementSeparator> if (cmd.Value == "initializer") { return(this.ParseGlobalInitialization(id)); // Discard <cmd> } // <poolVariableDefinition> ::= <poolName> ’variable:’ <poolVariableNameString> <elementSeparator> if (cmd.Value == "variable:") { return(this.ParsePoolVariableDefinition(id)); // Discard <cmd> } // <poolVariableDefinition> ::= <poolName> ’constant:’ <poolVariableNameString> <elementSeparator> if (cmd.Value == "constant:") { return(this.ParsePoolConstantDefinition(id)); // Discard <cmd> } // <poolValueInitialization> ::= <poolName> ’initializerFor:’ <poolVariableNameString> <elementSeparator> if (cmd.Value == "initializerFor:") { return(this.ParsePoolValueInitialization(id)); } // SPECIAL CASE .... Not really interchange element, but handled like one for simplicity. // <annotation> ::= ’Annotation’ ’key:’ quotedString ’value:’ quotedString <elementSeparator> if ((id.Value == "Annotation") && (cmd.Value == "key:")) { if (nodeForAnnotation == null) { this.ReportParserError("Annotation must follow an interchange element", cmd); } return(this.ParseAnnotation(nodeForAnnotation)); } this.ReportParserError("Unrecognized interchange element.", token); return(null); }
protected virtual AnnotationNode CreateAnnotationNode(InterchangeElementNode nodeForAnnotation) { return(new AnnotationNode(nodeForAnnotation)); }