public override void GenerateAbstractCode(List <C.CsStmt> code) { var cond = $"Main.Peek() is {Type}"; var guard = new C.IfThenElse(); guard.AddToBranch(cond, $"{Type} {Target} = {"Main.Pop()".CastAs(Type)}"); guard.AddToBranch(cond, $"Push(new {Name}({Target}))"); code.Add(guard); }
public override void GenerateAbstractCode(List <C.CsStmt> code) { HandleAction tmp; if (!String.IsNullOrEmpty(Flag)) { tmp = new LiftFlag { Flag = Flag }; tmp.GenerateAbstractCode(code); } code.Add(new C.SimpleStmt($"List<{Name}> {Target} = new List<{Name}>()")); var lambda = new C.ScheduleStmt(Name, "_" + Target); var ite = new C.IfThenElse(); var cond = $"_{Target} == null"; ite.AddBranch(cond); BaseAction?.GenerateAbstractCode(ite.GetThenBranch(cond)); if (!String.IsNullOrEmpty(Flag)) { tmp = new DropFlag { Flag = Flag }; tmp.GenerateAbstractCode(lambda.Code); } ite.AddToBranch(cond, "return Message.Perfect"); lambda.AddCode(ite); lambda.AddCode($"var {Target}1 = _{Target} as {Name};"); lambda.AddCode($"{Target}.Add({Target}1)"); lambda.AddCode("return Message.Consume"); code.Add(lambda); }
public override void GenerateAbstractCode(List <C.CsStmt> code) { code.Add(new C.SimpleStmt($"{Name} almost{Target}")); var cond = $"Main.Peek() is {Name}"; var ite = new C.IfThenElse(cond, $"almost{Target} = {"Main.Pop()".CastAs(Name)}"); // TODO: not always ".value", must get the type right ite.AddToBranch(cond, $"var {Target} = almost{Target}.value"); ite.AddElse($"ERROR = \"the top of the stack is not of type {Name}\""); ite.AddElse($"{Target} = {Name.DefaultValue()}"); code.Add(ite); }
// Precondition: Tokens.Contains(token_name) private void GenerateBranches(string tokenName, C.IfThenElse ite, List <string> skipMark) { if (!Tokens.ContainsKey(tokenName)) { return; } foreach (var tm in Tokens[tokenName]) { var res = tm.Special ? GenerateBranchSpecialMatch(tm.Value, tokenName) : GenerateBranchPreciseMatch(tm.Value, tokenName, skipMark); if (res != null) { ite.AddToBranch(res.Item1, res.Item2); } } }
// Precondition: Tokens.Contains(token_name) private void GenerateBranches(string token_name, C.IfThenElse ite, List <string> skipmark) { if (!Tokens.ContainsKey(token_name)) { return; } foreach (var tm in Tokens[token_name]) { Tuple <string, IEnumerable <CsStmt> > res; if (tm.Special) { res = GenerateBranchSpecialMatch(tm.Value, token_name); } else { res = GenerateBranchPreciseMatch(tm.Value, token_name, skipmark); } if (res != null) { ite.AddToBranch(res.Item1, res.Item2); } } }
private static void GenerateLexBranch(SwitchCaseStmt swLex, string hpk, IReadOnlyList <string> guardFlags, IReadOnlyList <List <HandleAction> > recipes, TokenPlan reactOn, bool matchChar) { var branchLex = new List <C.CsStmt>(); Console.WriteLine($"[IR] in '{hpk}', handle {reactOn.Value}"); bool onlyWraps = true; var ite = new C.IfThenElse(); for (int i = 0; i < guardFlags.Count; i++) { if (!String.IsNullOrEmpty(guardFlags[i])) { ite.AddBranch(guardFlags[i]); } var target = String.IsNullOrEmpty(guardFlags[i]) ? branchLex : ite.GetThenBranch(guardFlags[i]); foreach (var action in recipes[i]) { if (!(action is WrapOne)) { onlyWraps = false; } if (action != null) { if (action is WrapOne) { var fake = new List <CsStmt>(); action.GenerateAbstractCode(fake); if (fake.Count == 1 && fake[0] is IfThenElse ite2) { var newcond = guardFlags[i] + " && " + ite2.FirstThenBranchKey(); ite.RenameBranch(guardFlags[i], newcond); foreach (CsStmt stmt in ite2.FirstThenBranchValue()) { ite.AddToBranch(newcond, stmt); } } else { Console.WriteLine("[ERR] This particular usage of WRAP is not supported yet"); } } else { action.GenerateAbstractCode(target); } } else { Console.WriteLine($"[B2C] Warning: no action to handle '{hpk}'/{reactOn.Value}"); } } } string flags; if (guardFlags.Count == 1) { flags = "flag " + guardFlags[0] + " is not"; } else { flags = "neither of the flags " + String.Join(", ", guardFlags) + " are"; } branchLex.Add(ite); if (!onlyWraps) { if (guardFlags.Any(f => !String.IsNullOrEmpty(f))) { ite.AddElse($"ERROR = \"{flags} lifted when expected\""); } } if (matchChar) { swLex.Branches["'" + reactOn.Value + "'"] = branchLex; } else { swLex.Branches['"' + reactOn.Value + '"'] = branchLex; } }
public C.CsClass GenerateParser() { var p = new C.CsClass { NS = NS, Name = "Parser", Super = "BaseParser" }; p.AddUsing("EngageRuntime"); p.AddUsing("System"); p.AddUsing("System.Collections.Generic"); if (BoolFlags.Count > 0) { p.AddField(String.Join(", ", BoolFlags.OrderBy(x => x)), "bool", isPublic: false); } if (IntFlags.Count > 0) { p.AddField(String.Join(", ", IntFlags.OrderBy(x => x)), "int", isPublic: false); } // token types var tt = new C.CsEnum { IsPublic = false, Name = "TokenType" }; tt.Add("TUndefined"); tt.Add("TEOF"); tt.Add(Tokens.Keys.Where(t => t != "skip").Select(t => "T" + t)); p.AddInner(tt); // parser constructor var pc = new C.CsConstructor { InheritFromBase = true }; pc.AddArgument("input", "string"); p.AddConstructor(pc); // the parse function var pf = new C.CsMethod { Name = "Parse", RetType = "object" }; pf.AddCode("string ERROR = \"\""); pf.AddCode("TokenType type"); pf.AddCode("string lexeme"); var loop = new List <C.CsStmt>(); var pl = new C.WhileStmt("type != TokenType.TEOF", reversed: true); // main parsing loop: begin pl.AddCode("var _token = NextToken();"); pl.AddCode("lexeme = _token.Item2;"); pl.AddCode("type = _token.Item1;"); var swType = new C.SwitchCaseStmt { Expression = "type" }; var usedTokens = new HashSet <string> { "skip" }; foreach (var hpk in Handlers.Keys) { var branchType = new List <C.CsStmt>(); if (hpk == "EOF") { branchType.Add(new C.SimpleStmt("Flush()")); } if (Handlers[hpk].Count == 1) { Handlers[hpk][0].GenerateAbstractCode(branchType); } else { var swLex = new C.SwitchCaseStmt(); // much faster to switch-case on a char than on a string bool matchChar = Handlers[hpk].Select(hp => hp.ReactOn.Value).All(v => v.Length == 1); swLex.Expression = "lexeme" + (matchChar ? "[0]" : ""); // Need this dance because there may be different actions for the same token with different guards HandlerMetaCollection resortedHandlers = new HandlerMetaCollection(); foreach (var hp in Handlers[hpk]) { resortedHandlers.Add(hp); } foreach (var key in resortedHandlers.SortedKeys()) { GenerateLexBranch(swLex, hpk, resortedHandlers.GuardFlags(key), resortedHandlers.Recipes(key), key, matchChar); } branchType.Add(swLex); } swType.Branches["TokenType.T" + hpk] = branchType; usedTokens.Add(hpk); } foreach (var t in Tokens.Keys) { if (!usedTokens.Contains(t)) { Console.WriteLine($"[B2C] unused token {t}"); } foreach (B.TokenPlan tok in Tokens[t]) { if (!tok.Special) { continue; } var branchType = new List <C.CsStmt>(); string todo = tok.Value switch { "number" => "System.Int32.Parse(lexeme)", "string" => "lexeme", _ => "" }; todo = PossiblyWrap(todo, tok.Value); branchType.Add(new C.SimpleStmt($"Push({todo})")); swType.Branches["TokenType.T" + t] = branchType; } } pl.AddCode(swType); const string cond = "!System.String.IsNullOrEmpty(ERROR)"; var abend = new C.IfThenElse(); abend.AddToBranch(cond, "Console.WriteLine(\"Parser error: \" + ERROR);"); abend.AddToBranch(cond, "return null;"); pl.AddCode(abend); // main parsing loop: end pf.AddCode(pl); pf.AddCode(new C.IfThenElse($"Main.Peek() is {TopType}", "return Main.Pop()")); pf.AddCode("return null"); // TODO!!! p.AddMethod(pf); // other methods GenerateTokeniser(p); return(p); }