private static void PopulateMap(Model.MapValue map, Symbol keyValueSeq) { // Verify if (keyValueSeq.Type != SymbolType.KeyValueSeq) { throw new InvalidOperationException($"Trying to populate map from invalid symbol '{keyValueSeq.Type}'"); } // Get the key value Symbol keyValue = keyValueSeq.Children[keyValueSeq.Children.Length - 1]; if (keyValue.Type != SymbolType.KeyValue) { throw new InvalidOperationException($"Trying to populate map entry from invalid symbol '{keyValue.Type}'"); } bool hasTypeName = keyValue.Children[0].Type == SymbolType.TypeName; string key = GetIdentifer(keyValue.Children[hasTypeName ? 1 : 0]); Model.ValueNode value = CreateValueNode(keyValue.Children[keyValue.Children.Length - 1]); if (hasTypeName) { value.TypeName = GetTypeName(keyValue.Children[0]); } // Insert it map.Add(key, value); // Recurse if (keyValueSeq.Children.Length == 2) { PopulateMap(map, keyValueSeq.Children[0]); } }
private static Model.ValueNode FromMapOrArrayValue(Symbol val) { Model.ValueNode node; string typeName; switch (val.Type) { case SymbolType.TypedMapValue: case SymbolType.TypedArrayValue: typeName = GetTypeName(val.Children[0]); node = FromMapOrArrayValue(val.Children[1]); node.TypeName = typeName; return(node); case SymbolType.MapValue: var map = new Model.MapValue(); if (val.Children.Length > 2) { PopulateMap(map, val.Children[1]); } return(map); case SymbolType.ArrayValue: var arr = new Model.ArrayValue(); if (val.Children.Length > 2) { PopulateArray(arr, val.Children[1]); } return(arr); } return(null); }
public Model.Node Parse(TokenStream strm) { // Sanity check if (strm.EoS) { return(null); } // Initialise parse state Stack <Symbol> parseStack = new Stack <Symbol>(); parseStack.Push(Symbol.ParseState(0)); Symbol lookahead = strm.Read(); // Loop until we're done bool done = false; while (!done) { // Read current parse state Symbol parseState = parseStack.Peek(); if (!parseState.IsParseState) { throw new InvalidOperationException(); } StateDefinition state = parseStates[parseState.State]; // Select next action int terminalIndex = lookahead != null ? lookahead.TerminalIndex : SYMCNT_TERMINAL - 1; var rule = state.LookaheadTable[terminalIndex]; switch (rule.Action) { case ParserAction.Shift: parseStack.Push(lookahead); lookahead = strm.Read(); parseStack.Push(Symbol.ParseState(rule.Arg)); break; case ParserAction.Reduce: GrammarRule grammarRule = grammarRules[rule.Arg]; int toRemove = grammarRule.MatchSymbols.Length; Symbol[] children = new Symbol[toRemove]; while (toRemove > 0) { Symbol s = parseStack.Pop(); if (!s.IsParseState) { children[toRemove - 1] = s; toRemove--; } } Symbol newSymbol = new Symbol(grammarRule.OutputSymbol, children); Symbol priorState = parseStack.Peek(); if (!priorState.IsParseState) { throw new InvalidOperationException(); } StateDefinition priorStateDef = parseStates[priorState.State]; int nextState = priorStateDef.GotoTable[SymbolTypeToCol(grammarRule.OutputSymbol, true)]; parseStack.Push(newSymbol); parseStack.Push(Symbol.ParseState(nextState)); break; case ParserAction.Done: done = true; break; case ParserAction.Error: if (lookahead != null) { throw new InvalidOperationException($"Unexpected symbol '{lookahead.Value}' (line {lookahead.Position.Line}, col {lookahead.Position.Column})"); } else { throw new InvalidOperationException($"Unexpected end of stream"); } } } // Locate the parse tree Symbol parseTree = null; while (parseStack.Count > 0) { Symbol sym = parseStack.Pop(); if (!sym.IsParseState) { if (parseTree != null) { throw new InvalidOperationException($"Multiple parse trees generated (got '{sym.Type}', already had '{parseTree.Type}')"); } else { parseTree = sym; } } } if (parseTree == null) { throw new InvalidOperationException($"Parse tree not generated"); } // Identify it switch (parseTree.Type) { case SymbolType.KeyValueSeq: // We're going to emit a map var map = new Model.MapValue(); PopulateMap(map, parseTree); return(map); case SymbolType.ArraySeq: // We're going to emit an array var arr = new Model.ArrayValue(); PopulateArray(arr, parseTree); return(arr); default: throw new InvalidOperationException($"Unexpected root symbol '{parseTree.Type}'"); } }