Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        public override void GenerateAbstractCode(List <C.CsStmt> code)
        {
            code.Add(new C.SimpleStmt($"{Name} {Target}"));
            var ite = new C.IfThenElse($"Main.Peek() is {Name}", $"{Target} = {"Main.Pop()".CastAs(Name)}");

            ite.AddElse($"ERROR = \"the top of the stack is not of type {Name}\"");
            ite.AddElse($"{Target} = {Name.DefaultValue()}");
            code.Add(ite);
        }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
        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);
        }
Exemplo n.º 5
0
        public override void GenerateAbstractCode(List <C.CsStmt> code)
        {
            // initialise lists
            GenerateInitialisationCode(code);
            foreach (var sa in SiblingActions)
            {
                if (sa is PopSeveral ps)
                {
                    ps.GenerateInitialisationCode(code);
                }
            }

            var loop = new C.WhileStmt();

            loop.Condition = "Main.Count > 0";
            var ite = new C.IfThenElse($"Main.Peek() is {Name}", $"{Target}.Add(Main.Pop() as {Name})");

            foreach (var sa in SiblingActions)
            {
                if (sa is PopSeveral ps)
                {
                    ite.AddBranch($"Main.Peek() is {ps.Name}", $"{ps.Target}.Add(Main.Pop() as {ps.Name})");
                }
            }
            ite.ElseBranch.Add(new C.SimpleStmt("break"));
            loop.Code.Add(ite);
            code.Add(loop);

            // reverse the order because of stack vs list differences
            code.Add(new C.SimpleStmt($"{Target}.Reverse()"));
            foreach (var sa in SiblingActions)
            {
                if (sa is PopSeveral ps)
                {
                    code.Add(new C.SimpleStmt($"{ps.Target}.Reverse()"));
                }
            }

            // produce the rest of the code (usually push new)
            foreach (var sa in SiblingActions)
            {
                if (!(sa is PopSeveral))
                {
                    sa.GenerateAbstractCode(code);
                }
            }
        }
Exemplo n.º 6
0
 // 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);
         }
     }
 }
Exemplo n.º 7
0
 // 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);
         }
     }
 }
Exemplo n.º 8
0
        private void GenerateTokeniser(C.CsClass cls)
        {
            var skipmark = new List <string>();

            var tok = new C.CsMethod
            {
                IsPublic = false,
                Name     = "NextToken",
                RetType  = "Tuple<TokenType, string>"
            };

            // init phase
            tok.AddCode("TokenType t = TokenType.TUndefined;");
            tok.AddCode("string s = \"\";");
            // EOF phase
            tok.AddCode(new C.IfThenElse("Pos >= Input.Length",
                                         "return new Tuple<TokenType, string>(TokenType.TEOF, \"\")"));
            // skip
            if (Tokens.ContainsKey("skip"))
            {
                string cond = String.Join(" || ", Tokens["skip"].Select(t => $"Input[Pos] == '{t.Value}'"));
                tok.AddCode(new C.WhileStmt($"Pos < Input.Length && ({cond})", "Pos++"));
                Tokens["skip"].ForEach(t => skipmark.Add(t.Value));
            }
            else
            {
                Console.WriteLine($"[IR] It is suspicious that there are no tokens of type 'skip'");
            }

            // EOF after skip
            var megaIf = new C.IfThenElse("Pos >= Input.Length",
                                          "return new Tuple<TokenType, string>(TokenType.TEOF, \"\")");

            tok.AddCode(megaIf);
            // mark
            if (Tokens.ContainsKey("mark"))
            {
                Tokens["mark"].ForEach(t => skipmark.Add(t.Value));
                GenerateBranches("mark", megaIf, null);
            }
            else
            {
                Console.WriteLine("[IR] It is suspicious that there are no tokens of type 'word'");
            }

            // word
            if (Tokens.ContainsKey("word"))
            {
                GenerateBranches("word", megaIf, skipmark);
            }
            else
            {
                Console.WriteLine("[IR] It is suspicious that there are no tokens of type 'word'");
            }
            // number etc
            foreach (var tt in Tokens.Keys.Where(tt => tt != "skip" && tt != "word" && tt != "mark"))
            {
                GenerateBranches(tt, megaIf, skipmark);
            }
            tok.AddCode("return new Tuple<TokenType, string>(t, s);");

            cls.AddMethod(tok);
        }
Exemplo n.º 9
0
        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;
            }
        }
Exemplo n.º 10
0
        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);
        }