protected internal virtual InterchangeUnitNode ParseInterchangeElement(InterchangeElementNode nodeForAnnotation) { // 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); }
protected virtual AnnotationNode ParseAnnotation(InterchangeElementNode nodeForAnnotation) { // 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 somethind like: Annotation key: 'x' value: 'y' crash: 'yes'. result.Value = null; // This is to avoid somethind like: Annotation key: 'x' value: 'y' crash: 'yes'. return result; } return result; }
public AnnotationNode(InterchangeElementNode annotatedNode) { this.AnnotatedNode = annotatedNode; // Null is OK! }