/// <summary> /// Inserts a new tree for each token in keys. /// </summary> /// <param name="keys">The list of keys.</param> /// <param name="obj">The tree.</param> /// <returns>The new tree.</returns> public Trie InsertChain(List<string> keys, Trie obj) { var node = this; // TODO check if correct foreach (string key in keys) { Trie nnode; if (this.Items.ContainsKey(key)) { nnode = node.Items[key]; } else { nnode = new Trie(); node.Items[key] = nnode; } node = nnode; } node.Value = obj.Value; return node; }
/// <summary> /// Inserts a chain of trees. /// </summary> /// <param name="keys">The list of tokens.</param> /// <param name="obj">The tree used.</param> /// <returns>The new tree.</returns> public Trie InsertChain1(List<string> keys, Trie obj) { var node = this; // TODO this is wrong? copy? foreach (string key in keys) { Trie nnode; if (this.Items.ContainsKey(key)) { nnode = node.Items[key]; } else { nnode = new Trie(); node.Items[key] = nnode; } node = nnode; } if (node.Value.Count == 0) { node.Value = new List<ActiveItem>(); node.Value.AddRange(obj.Value); } else { node.Value.AddRange(obj.Value); } return node; }
/// <summary> /// Processes the current agenda. /// </summary> /// <param name="agenda">The agenda we want to go through.</param> public void Process(List<ActiveItem> agenda) { while (agenda.Count > 0) { var item = agenda[agenda.Count - 1]; agenda.RemoveAt(agenda.Count - 1); var lin = item.Seq; if (item.Dot < lin.Count) { var sym = lin[item.Dot]; if (sym is SymbolCat) { var newSym = (SymbolCat)sym; var fid = item.Args[newSym.Arg]; var label = newSym.Label; var items = this.chart.LookupAC(fid, label); if (items == null) { var rules = this.chart.ExpandForest(fid); foreach (ProductionApply rule in rules) { var newAI = new ActiveItem(this.chart.Offset, 0, rule.Function, rule.Function.Sequences[label].ToList<Symbol>(), rule.Domain().ToList<int>(), fid, label); agenda.Add(newAI); } List<ActiveItem> temp = new List<ActiveItem>(); temp.Add(item); this.chart.InsertAC(fid, label, temp); } else { bool isMember = false; foreach (ActiveItem ai in items) { if (ai.Equals(item)) { isMember = true; break; } } if (!isMember) { items.Add(item); var fid2 = this.chart.LookupPC(fid, label, this.chart.Offset); if (fid2.HasValue) { agenda.Add(item.ShiftOverArg(newSym.Arg, fid2.Value)); } } } } else if (sym is SymbolLit) { var newSym = (SymbolLit)sym; var fid = item.Args[newSym.Arg]; List<Production> rules; if (this.chart.Forest.ContainsKey(fid)) { rules = this.chart.Forest[fid]; } else { rules = new List<Production>(); } if (rules.Count > 0) { if (rules[0] is ProductionConst) { ProductionConst pc = (ProductionConst)rules[0]; List<string> tokens = new List<string>(pc.Tokens); ActiveItem ai2 = item.ShiftOverTokn(); if (pc.Tokens.Count > 0 && (this.currentToken == string.Empty || tokens[0] == this.currentToken)) { tokens.RemoveAt(0); Trie tt = new Trie(); tt.Value = new List<ActiveItem>() { ai2 }; this.currentAcc = this.currentAcc.InsertChain1(tokens, tt); } } } else { List<Production> newProd = new List<Production>(); Symbol[][] syms = new Symbol[0][]; if (fid == -1) { // If string string token = "\"" + this.currentToken + "\""; ConcreteFunction newFun = new ConcreteFunction(token, syms); newProd.Add(new ProductionConst(newFun, new List<string>() { token }, -1)); // nextId´+?? } else if (fid == -2) { // If int int i = 0; if (int.TryParse(this.currentToken, out i)) { ConcreteFunction newFun = new ConcreteFunction(this.currentToken, syms); newProd.Add(new ProductionConst(newFun, new List<string>() { this.currentToken }, -2)); } } else if (fid == -3) { // If float double f = 0; if (double.TryParse(this.currentToken, NumberStyles.Number, NumberFormatInfo.InvariantInfo, out f)) { ConcreteFunction newFun = new ConcreteFunction(this.currentToken, syms); newProd.Add(new ProductionConst(newFun, new List<string>() { this.currentToken }, -3)); } } if (newProd.Count > 0) { var currentProd = (ProductionConst)newProd[0]; fid = this.chart.NextId++; this.chart.Forest[fid] = newProd; var tokens2 = new List<string>(currentProd.Tokens); var item2 = item.ShiftOverArg(newSym.Arg, fid); if (tokens2.Count > 0 && (this.currentToken == string.Empty || tokens2[0] == this.currentToken)) { tokens2.RemoveAt(0); Trie tt = new Trie(); tt.Value = new List<ActiveItem>() { item2 }; this.currentAcc = this.currentAcc.InsertChain1(tokens2, tt); } } } } else if (sym is SymbolKP) { var newSym = (SymbolKP)sym; var pitem = item.ShiftOverTokn(); var tokens = new List<string>(); foreach (Symbol newSymbol in newSym.Tokens) { if (newSymbol is SymbolKS) { // TODO is this correct? tokens.AddRange(((SymbolKS)newSymbol).Tokens); } else if (newSymbol is SymbolBind) { tokens.Add("&+"); } else if (newSymbol is SymbolSoftBind) { // Ignore } else if (newSymbol is SymbolSoftSpace) { // Ignore } else if (newSymbol is SymbolCapit) { tokens.Add("&|"); } else if (newSymbol is SymbolAllCapit) { tokens.Add("&|"); } else { // If new token just ignore } } if (tokens.Count > 0 && (this.currentToken == string.Empty || tokens[0] == this.currentToken)) { tokens.RemoveAt(0); Trie tt = new Trie(); tt.Value = new List<ActiveItem>() { pitem }; this.currentAcc = this.currentAcc.InsertChain1(tokens, tt); } foreach (Alternative alt in newSym.Alts) { // TODO check if needed Symbol[] currentSym = alt.Alt1; tokens = new List<string>(alt.Alt2.ToList<string>()); if (tokens.Count > 0 && (this.currentToken == string.Empty || tokens[0] == this.currentToken)) { tokens.RemoveAt(0); Trie tt = new Trie(); tt.Value = new List<ActiveItem>() { pitem }; this.currentAcc = this.currentAcc.InsertChain1(tokens, tt); } } } else if (sym is SymbolKS) { var newSym = (SymbolKS)sym; var tokens = new List<string>(newSym.Tokens.ToList<string>()); var ai = item.ShiftOverTokn(); if (tokens.Count > 0 && (this.currentToken == string.Empty || tokens[0] == this.currentToken)) { tokens.RemoveAt(0); Trie tt = new Trie(); tt.Value = new List<ActiveItem>() { ai }; this.currentAcc = this.currentAcc.InsertChain1(tokens, tt); } } else if (sym is SymbolVar) { var newSym = (SymbolVar)sym; // TODO Not implemented throw new NotImplementedException(); } } else { int? tempfid = this.chart.LookupPC(item.FId, item.Lbl, item.Offset); if (!tempfid.HasValue) { int fid = this.chart.NextId++; var items = this.chart.LookupACo(item.Offset, item.FId, item.Lbl); if (items != null) { foreach (ActiveItem pitem in items) { var temp = pitem.Seq[pitem.Dot]; if (temp is SymbolCat) { var arg = ((SymbolCat)temp).Arg; agenda.Add(pitem.ShiftOverArg(arg, fid)); } else if (temp is SymbolLit) { var arg = ((SymbolLit)temp).Arg; agenda.Add(pitem.ShiftOverArg(arg, fid)); } } } this.chart.InsertPC(item.FId, item.Lbl, item.Offset, fid); var newProd = new ProductionApply(item.Fun, item.Args.ToArray<int>()); if (this.chart.Forest.ContainsKey(fid)) { this.chart.Forest[fid].Add(newProd); } else { this.chart.Forest[fid] = new List<Production>() { newProd }; } } else { int fid = tempfid.Value; var labels = this.chart.LabelsAC(fid); foreach (int k in labels.Keys) { var newAI = new ActiveItem(this.chart.Offset, 0, item.Fun, item.Fun.Sequences[k].ToList<Symbol>(), item.Args, fid, k); agenda.Add(newAI); } var rules = this.chart.Forest[fid]; var rule = new ProductionApply(item.Fun, item.Args.ToArray<int>()); bool isMember = false; foreach (Production p in rules) { if (p is ProductionApply) { if (rule.Equals((ProductionApply)p)) { isMember = true; } } } if (!isMember) { rules.Add(rule); } } } } }
/// <summary> /// Initializes a new instance of the ParseState class. /// </summary> /// <param name="concrete">The concrete used to parse.</param> public ParseState(Concrete concrete) { this.concrete = concrete; this.startCat = concrete.GetStartCat(); this.items = new Trie(); this.chart = new Chart(concrete); ConcreteCategory tempcat = concrete.GetStartCat(); for (int fid = tempcat.FirstFID; fid <= tempcat.LastFID; fid++) { var prods = this.chart.ExpandForest(fid); foreach (ProductionApply k in prods) { k.Function.FixSymbols(); int lbl = 0; foreach (Symbol[] sym in k.Function.Sequences) { var activeItem = new ActiveItem(0, 0, k.Function, sym.ToList<Symbol>(), k.Domain().ToList<int>(), fid, lbl); this.items.Value.Add(activeItem); lbl++; } } } this.items.InsertChain(new List<string>(), this.items); }
/// <summary> /// Parse the next token. /// </summary> /// <param name="token">The token we want to parse.</param> /// <returns>Returns true if parsed correctly.</returns> public bool Next(string token) { // Temporary store token instead of callback this.currentToken = token; this.currentAcc = this.items.Lookup(token); this.Process(this.items.Value); this.items = this.currentAcc; this.chart.Shift(); return !this.items.IsEmpty(); }