Esempio n. 1
0
 public LNode Call(string funcName)
 {
     return(F.Call(GSymbol.Get(funcName)));
 }
Esempio n. 2
0
 public bool RemoveTag(string key)
 {
     return(RemoveTag(GSymbol.GetIfExists(key)));
 }
Esempio n. 3
0
 public ValueT GetTag(string key)
 {
     return(GetTag(GSymbol.GetIfExists(key)));
 }
Esempio n. 4
0
 public LNode Var(LNode type, string name, LNode initValue = null)
 {
     return(Var(type, GSymbol.Get(name), initValue));
 }
Esempio n. 5
0
 public static Symbol NextTempName(IMacroContext ctx, string prefix = "tmp_")
 {
     return(GSymbol.Get(prefix + ctx.IncrementTempCounter()));
 }
Esempio n. 6
0
 public LNode Id(Token t)
 {
     return(new StdIdNode(t.Value as Symbol ?? GSymbol.Get(t.Value.ToString()),
                          new SourceRange(_file, t.StartIndex, t.Length), t.Style));
 }
Esempio n. 7
0
 public LNode Call(string target, params LNode[] args)
 {
     return(Call(GSymbol.Get(target), args));
 }
Esempio n. 8
0
        Symbol InfixOperatorName(out Token op)
        {
            TT     la0;
            Token  op2    = default(Token);
            Symbol result = default(Symbol);

            // Line 187: ( (TT.Assignment|TT.Dot|TT.NormalOp) (TT.Newline)* | &{(TT) LA($LI + 1) != TT.Newline} TT.Colon | &!{Continuators.ContainsKey(LT($LI).Value)} TT.Id (&{op.EndIndex == LT0.StartIndex} (TT.Assignment|TT.Dot|TT.NormalOp) / ) (TT.Newline (TT.Newline)* / ) )
            switch ((TT)LA0)
            {
            case TT.Assignment:
            case TT.Dot:
            case TT.NormalOp:
            {
                op = MatchAny();
                // Line 187: (TT.Newline)*
                for (;;)
                {
                    la0 = (TT)LA0;
                    if (la0 == TT.Newline)
                    {
                        Skip();
                    }
                    else
                    {
                        break;
                    }
                }
                // line 187
                result = (Symbol)op.Value;
            }
            break;

            case TT.Colon:
            {
                Check((TT)LA(0 + 1) != TT.Newline, "Expected (TT) LA($LI + 1) != TT.Newline");
                op = MatchAny();
                // line 188
                result = (Symbol)op.Value;
            }
            break;

            default:
            {
                Check(!Continuators.ContainsKey(LT(0).Value), "Did not expect Continuators.ContainsKey(LT($LI).Value)");
                op = Match((int)TT.Id);
                // Line 192: (&{op.EndIndex == LT0.StartIndex} (TT.Assignment|TT.Dot|TT.NormalOp) / )
                do
                {
                    la0 = (TT)LA0;
                    if (la0 == TT.Assignment || la0 == TT.NormalOp)
                    {
                        if (op.EndIndex == LT0.StartIndex)
                        {
                            goto match1;
                        }
                        else
                        {
                            goto match2;
                        }
                    }
                    else if (la0 == TT.Dot)
                    {
                        goto match1;
                    }
                    else
                    {
                        goto match2;
                    }
match1:
                    {
                        Check(op.EndIndex == LT0.StartIndex, "Expected op.EndIndex == LT0.StartIndex");
                        op2 = MatchAny();
                        // line 194
                        result = GSymbol.Get("'" + op.Value.ToString() + op2.Value.ToString().Substring(1));
                    }
                    break;
match2:
                    {
                        // line 197
                        result = GSymbol.Get("'" + op.Value.ToString());
                        if ((TT)LA0 == TT.Newline)
                        {
                            Error(0, "Syntax error. {0}' is used like an operator but is followed by a newline, which is not allowed unless the expression is placed in parentheses.".Localized(result));
                        }
                    }
                } while (false);
                // Line 202: (TT.Newline (TT.Newline)* / )
                la0 = (TT)LA0;
                if (la0 == TT.Newline)
                {
                    Skip();
                    // Line 202: (TT.Newline)*
                    for (;;)
                    {
                        la0 = (TT)LA0;
                        if (la0 == TT.Newline)
                        {
                            Skip();
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                else                          // line 204
                if (LT(-1).EndIndex == LT0.StartIndex)
                {
                    Error(0, "Syntax error. {0}' is used like an operator but is not followed by a space.".Localized(result));
                }
            }
            break;
            }
            return(result);
        }
Esempio n. 9
0
        protected override byte[] Generate(string inputFilePath, string inputFileContents, string defaultNamespace, IVsGeneratorProgress progressCallback)
        {
            string oldCurDir = Environment.CurrentDirectory;

            try {
                string inputFolder = Path.GetDirectoryName(inputFilePath);
                Environment.CurrentDirectory = inputFolder;                 // --macros should be relative to file being processed

                var options = new BMultiMap <string, string>();
                var argList = G.SplitCommandLineArguments(defaultNamespace);
                UG.ProcessCommandLineArguments(argList, options, "", LeMP.Compiler.ShortOptions, LeMP.Compiler.TwoArgOptions);

                string _;
                var    KnownOptions = LeMP.Compiler.KnownOptions;
                if (options.TryGetValue("help", out _) || options.TryGetValue("?", out _))
                {
                    LeMP.Compiler.ShowHelp(KnownOptions);
                }

                // Originally I wrote a conversion from IVsGeneratorProgress to
                // IMessageSink so that errors could be reported immediately and
                // directly to Visual Studio. This broke in a bizarre way when I
                // added processing on a separate thread (in order to be able to
                // abort the thread if it runs too long); I got the following
                // InvalidCastException: "Unable to cast COM object of type 'System.__ComObject'
                // to interface type 'Microsoft.VisualStudio.Shell.Interop.IVsGeneratorProgress'.
                // This operation failed because the QueryInterface call on the COM component for
                // the interface with IID '{BED89B98-6EC9-43CB-B0A8-41D6E2D6669D}' failed due to
                // the following error: No such interface supported (Exception from HRESULT:
                // 0x80004002 (E_NOINTERFACE))."
                //
                // A simple solution is to store the messages rather than reporting
                // them immediately. I'll report the errors at the very end.
                MessageHolder sink = new MessageHolder();

                var sourceFile = new InputOutput((UString)inputFileContents, Path.GetFileName(inputFilePath));

                var c = new Compiler(sink, sourceFile);
                c.Parallel = false;                 // only one file, parallel doesn't help

                if (LeMP.Compiler.ProcessArguments(c, options))
                {
                    if (options.ContainsKey("no-out-header"))
                    {
                        options.Remove("no-out-header", 1);
                        c.NoOutHeader = true;
                    }
                    LeMP.Compiler.WarnAboutUnknownOptions(options, sink, KnownOptions);
                    if (c != null)
                    {
                        if (inputFilePath.EndsWith(".les", StringComparison.OrdinalIgnoreCase))
                        {
                            c.MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude.Les"));
                        }
                        Configure(c);
                        c.Run();

                        // Report errors
                        foreach (var msg in sink.List)
                        {
                            ReportErrorToVS(progressCallback, msg.Severity, msg.Context, msg.Format, msg.Args);
                        }

                        return(Encoding.UTF8.GetBytes(c.Output.ToString()));
                    }
                }
                return(null);
            } finally {
                Environment.CurrentDirectory = oldCurDir;
            }
        }
Esempio n. 10
0
 protected virtual Symbol GenerateSetName(Rule currentRule)
 {
     return(GSymbol.Get(string.Format("{0}_set{1}", currentRule.Name.Name, _setNameCounter++)));
 }
Esempio n. 11
0
 Symbol NamespaceToSymbol(LNode node)
 {
     // quick & dirty, probably not cheap
     return(GSymbol.Get(node.Print(NodeStyle.Expression)));
 }
Esempio n. 12
0
 public static Symbol NextTempName()
 {
     return(GSymbol.Get("tmp_" + _nextTempCounter++));
 }
Esempio n. 13
0
        public Rule MakeRecognizerVersion()
        {
            var scanName = GSymbol.Get("Scan_" + Name.Name);

            return(_recognizer = _recognizer ?? MakeRecognizerVersion(scanName));
        }
Esempio n. 14
0
 internal static HashSet <Symbol> SymbolSet(params string[] input)
 {
     return(new HashSet <Symbol>(input.Select(s => GSymbol.Get(s))));
 }
Esempio n. 15
0
        public void ToBracketsLNodeTests()
        {
            var file  = EmptySourceFile.Unknown;
            var child = new TokenTree(file, new[] { new Token((int)TokenKind.Id, 6, 1, NodeStyle.Default, GSymbol.Get("x")) });

            TestToLNode(EmptySourceFile.Unknown, new List <Pair <Token, string> >()
            {
                P(new Token((int)TokenKind.LParen, 5, 1, 0, child), @"LParen(x)"),
                P(new Token((int)TokenKind.RParen, 7, 1, 0, null), @"RParen()"),
                P(new Token((int)TokenKind.LParen, 5, 1, 0, null), @"LParen()"),
                P(new Token((int)TokenKind.RParen, 7, 1, 0, null), @"RParen()"),
                P(new Token((int)TokenKind.LBrack, 5, 1, 0, child), @"LBrack(x)"),
                P(new Token((int)TokenKind.RBrack, 7, 1, 0, null), @"RBrack()"),
                P(new Token((int)TokenKind.LBrace, 5, 1, 0, child), @"LBrace(x)"),
                P(new Token((int)TokenKind.RBrace, 7, 1, 0, null), @"RBrace()"),
                P(new Token((int)TokenKind.Indent, 5, 1, 0, child), @"Indent(x)"),
                P(new Token((int)TokenKind.Dedent, 7, 1, 0, null), @"Dedent()"),
                P(new Token((int)TokenKind.LOther, 5, 1, 0, child), @"LOther(x)"),
                P(new Token((int)TokenKind.ROther, 7, 1, 0, null), @"ROther()"),
            });
        }
Esempio n. 16
0
 static Symbol PickVarNameForRuleName(Symbol name)
 {
     return(GSymbol.Get("got_" + name));
 }
Esempio n. 17
0
 public void GetNonexistantId()
 {
     Assert.AreEqual(GSymbol.GetById(876543210), null);
     Assert.AreEqual(GSymbol.GetById(-876543210), null);
 }
Esempio n. 18
0
        static Symbol LiteralToVarName(object literal)
        {
            string prefix = literal is char? "ch" : "lit";

            return(GSymbol.Get(prefix + LiteralToIdent(literal)));
        }
Esempio n. 19
0
        /// <summary>Creates a trivia node named <c>"#trivia_" + suffix</c> with the
        /// specified Value attached.</summary>
        /// <remarks>This method only adds the prefix <c>#trivia_</c> if it is not
        /// already present in the 'suffix' argument.</remarks>
        public LNode Trivia(string suffix, object value)
        {
            string name = suffix.StartsWith("#trivia_") ? suffix : "#trivia_" + suffix;

            return(LNode.Trivia(GSymbol.Get(name), value, new SourceRange(_file)));
        }
Esempio n. 20
0
        private void TestTheBasics(TagsInWList <string> a, bool startsEmpty)
        {
            // This test is run twice, once on a set that starts empty (to
            // test the one-element code paths) and again on a set that has
            // unrelated stuff in it already.
            IEnumerator <KeyValuePair <Symbol, string> > e;

            // Sanity checks
            Assert.IsNull(a.GetTag((string)null));
            Assert.IsFalse(a.RemoveTag("Nonexistant"));
            Assert.IsFalse(a.HasTag("Nonexistant"));

            a.SetTag("One", "Two");
            Assert.AreEqual(a.GetTag("One"), "Two");

            // Test the enumerator
            e = a.TagEnumerator();
            Assert.IsTrue(e.MoveNext());
            if (startsEmpty)
            {
                Assert.AreEqual(GSymbol.Get("One"), e.Current.Key);
                Assert.AreEqual("Two", e.Current.Value);
                Assert.IsFalse(e.MoveNext());
            }

            // Remove what we added
            Assert.IsNull(a.GetTag((string)null));
            Assert.IsFalse(a.RemoveTag(""));
            Assert.IsTrue(a.RemoveTag("One"));
            Assert.IsNull(a.GetTag("One"));

            if (startsEmpty)
            {
                e = a.TagEnumerator();
                Assert.IsFalse(e.MoveNext());
            }

            // Do almost the same thing again: add an attr, then remove it
            a.SetTag("One", "Two");
            Assert.AreEqual("Two", a.GetTag("One"));
            Assert.IsTrue(a.HasTag("One"));
            Assert.IsTrue(a.RemoveTag("One"));
            Assert.IsNull(a.GetTag("One"));

            // A different attribute
            a.SetTag("Two", "Three");
            Assert.AreEqual("Three", a.GetTag("Two"));
            a.SetTag("Two", "Four");
            a.SetTag("Two", "Two");
            Assert.AreEqual("Two", a.GetTag("Two"));

            // Another attribute should not disturb the first
            a.SetTag("Three", "Four");
            Assert.AreEqual("Two", a.GetTag("Two"));
            Assert.IsFalse(a.HasTag("One"));
            Assert.IsTrue(a.HasTag("Two"));
            Assert.IsTrue(a.HasTag("Three"));

            // Test the enumerator
            e = a.TagEnumerator();
            Assert.IsTrue(e.MoveNext());
            Assert.IsTrue(e.MoveNext());
            if (startsEmpty)
            {
                Assert.IsFalse(e.MoveNext());
            }

            // Clean up by removing all that we added
            Assert.IsTrue(a.RemoveTag("Two"));
            Assert.IsTrue(a.RemoveTag("Three"));
        }
Esempio n. 21
0
 public LNode Dot(params string[] symbols)
 {
     return(Dot(symbols.SelectArray(s => Id(GSymbol.Get(s)))));
 }
Esempio n. 22
0
 public void PreprocessorConflicts()
 {
     Stmt("@#error(\"FAIL!\");", F.Call(S.Error, F.Literal("FAIL!")));
     Stmt("@#if(c, Foo());", AsStyle(NodeStyle.Expression, F.Call(S.If, c, F.Call(Foo))));
     Stmt("@#region(57);", AsStyle(NodeStyle.Expression, F.Call(GSymbol.Get("#region"), Number(57))));
 }
Esempio n. 23
0
 /// <summary>Adds standard macros from LeMP.StdMacros.dll, and adds the
 /// namespaces LeMP and LeMP.Prelude to the pre-opened namespace list.</summary>
 /// <remarks>Note: prelude macros were already added by the constructor.</remarks>
 public void AddStdMacros()
 {
     MacroProcessor.AddMacros(typeof(global::LeMP.StandardMacros).Assembly);
     MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LeMP"));
     MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude"));
 }
Esempio n. 24
0
        void ParseBQStringValue()
        {
            var value = ParseStringCore(_startPosition);

            _value = GSymbol.Get(value.ToString());
        }
Esempio n. 25
0
 [DebuggerStepThrough] static Symbol _(string s)
 {
     return(GSymbol.Get(s));
 }
Esempio n. 26
0
 public override void Configure(global::LeMP.Compiler c)
 {
     c.MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("Loyc.LLPG"));
     base.Configure(c);
 }
Esempio n. 27
0
 public bool HasTag(string key)
 {
     return(HasTag(GSymbol.GetIfExists(key)));
 }
Esempio n. 28
0
        protected override byte[] Generate(string inputFilePath, string inputFileContents, string defaultNamespace, IVsGeneratorProgress progressCallback)
        {
            string oldCurDir = Environment.CurrentDirectory;

            try {
                string inputFolder = Path.GetDirectoryName(inputFilePath);
                Environment.CurrentDirectory = inputFolder;                 // --macros should be relative to file being processed

                // Originally I wrote a conversion from IVsGeneratorProgress to
                // IMessageSink so that errors could be reported immediately and
                // directly to Visual Studio. This broke in a bizarre way when I
                // added processing on a separate thread (in order to be able to
                // abort the thread if it runs too long); I got the following
                // InvalidCastException: "Unable to cast COM object of type 'System.__ComObject'
                // to interface type 'Microsoft.VisualStudio.Shell.Interop.IVsGeneratorProgress'.
                // This operation failed because the QueryInterface call on the COM component for
                // the interface with IID '{BED89B98-6EC9-43CB-B0A8-41D6E2D6669D}' failed due to
                // the following error: No such interface supported (Exception from HRESULT:
                // 0x80004002 (E_NOINTERFACE))."
                //
                // A simple solution is to store the messages rather than reporting
                // them immediately. I'll report the errors at the very end.
                MessageHolder sink = new MessageHolder();

                var sourceFile = new InputOutput((UString)inputFileContents, inputFilePath);

                Compiler.KnownOptions["no-out-header"] = Pair.Create("", "Remove explanatory comment from output file");
                Compiler.KnownOptions.Remove("parallel");                   // not applicable to single file
                Compiler.KnownOptions.Remove("noparallel");                 // not applicable to single file
                Compiler.KnownOptions.Remove("outext");                     // not allowed by IVsSingleFileGenerator

                var c = new Compiler(sink, sourceFile)
                {
                    AbortTimeout = TimeSpan.FromSeconds(10),
                    Parallel     = false                 // only one file, parallel doesn't help
                };

                var argList = G.SplitCommandLineArguments(defaultNamespace);
                var options = c.ProcessArguments(argList, true, false);
                if (argList.Count > 0)
                {
                    sink.Write(Severity.Error, "Command line", "'{0}': expected options only (try --help).", argList[0]);
                }

                string _;
                if (options.TryGetValue("help", out _) || options.TryGetValue("?", out _))
                {
                    var ms = new MemoryStream();
                    LeMP.Compiler.ShowHelp(LeMP.Compiler.KnownOptions, new StreamWriter(ms), false);
                    return(ms.GetBuffer());
                }

                LeMP.Compiler.WarnAboutUnknownOptions(options, sink, LeMP.Compiler.KnownOptions);

                if (options.ContainsKey("no-out-header"))
                {
                    c.NoOutHeader = true;
                }

                if (c.InLang == LesLanguageService.Value || inputFilePath.EndsWith(".les", StringComparison.OrdinalIgnoreCase))
                {
                    c.MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude.Les"));
                }

                Configure(c);
                c.Run();

                // Report errors
                foreach (var msg in sink.List)
                {
                    ReportErrorToVS(progressCallback, msg.Severity, msg.Context, msg.Format, msg.Args);
                }

                return(Encoding.UTF8.GetBytes(c.Output.ToString()));
            } finally {
                Environment.CurrentDirectory = oldCurDir;
            }
        }
Esempio n. 29
0
 public void SetTag(string key, ValueT val)
 {
     SetTag(GSymbol.Get(key), val);
 }
Esempio n. 30
0
            protected LNode GeneratePredictionTreeCode(PredictionTree tree, Pair <LNode, string>[] matchingCode, ref Symbol haveLoop)
            {
                var braces = F.Braces();

                Debug.Assert(tree.Children.Count >= 1);
                var alts = (Alts)_currentPred;

                if (tree.Children.Count == 1)
                {
                    return(GetPredictionSubtreeCode(tree.Children[0], matchingCode, ref haveLoop));
                }

                // From the prediction table, we can generate either an if-else chain:
                //
                //   if (la0 >= '0' && la0 <= '7') sub_tree_1();
                //   else if (la0 == '-') sub_tree_2();
                //   else break;
                //
                // or a switch statement:
                //
                //   switch(la0) {
                //   case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
                //     sub_tree_1();
                //     break;
                //   case '-':
                //     sub_tree_2();
                //     break;
                //   default:
                //     goto breakfor;
                //   }
                //
                // Assertion levels always need an if-else chain; lookahead levels
                // consider the complexity of switch vs if and decide which is most
                // appropriate. Generally "if" is slower, but a switch may require
                // too many labels since it doesn't support ranges like "la0 >= 'a'
                // && la0 <= 'z'".
                //
                // This class makes if-else chains directly (using IPGTerminalSet.
                // GenerateTest() to generate the test expressions), but the code
                // generation helper (CGH) is used to generate switch statements
                // because the required code may be more complex.
                //
                // We may or may not be generating code inside a for(;;) loop. If we
                // decide to generate a switch() statement, one of the branches will
                // usually need to break out of the for loop, but "break" can only
                // break out of the switch(). In that case, add "stop:" after the
                // switch() and use "goto stop" instead of "break".

                WList <LNode> block       = new WList <LNode>();
                LNode         laVar       = null;
                MSet <int>    switchCases = new MSet <int>();

                IPGTerminalSet[] branchSets = null;
                bool             should     = false;

                if (tree.UsesLA())
                {
                    laVar = F.Id("la" + tree.Lookahead.ToString());

                    if (!tree.IsAssertionLevel)
                    {
                        IPGTerminalSet covered = CGH.EmptySet;
                        branchSets = tree.Children.Select(branch => {
                            var set = branch.Set.Subtract(covered);
                            covered = covered.Union(branch.Set);
                            return(set);
                        }).ToArray();

                        should = CGH.ShouldGenerateSwitch(branchSets, switchCases, tree.Children.Last.IsErrorBranch);
                        if (!should)
                        {
                            switchCases.Clear();
                        }
                        else if (should && haveLoop == S.For)
                        {
                            // Can't "break" out of the for-loop when there is a nested switch,
                            haveLoop = GSymbol.Get(NextStopLabel());                             // so use "goto stop".
                        }
                    }
                }

                LNode[] branchCode = new LNode[tree.Children.Count];
                for (int i = 0; i < tree.Children.Count; i++)
                {
                    if (tree.Children[i].IsErrorBranch)
                    {
                        if (_recognizerMode)
                        {
                            branchCode[i] = F.Call(S.Return, F.False);
                        }
                        else if (alts.ErrorBranch != null && alts.ErrorBranch != DefaultErrorBranch.Value)
                        {
                            Debug.Assert(matchingCode.Length == alts.Arms.Count + 1);
                            branchCode[i] = matchingCode[alts.Arms.Count].A;
                        }
                        else
                        {
                            branchCode[i] = CGH.ErrorBranch(tree.TotalCoverage, tree.Lookahead);
                        }
                    }
                    else
                    {
                        branchCode[i] = GetPredictionSubtreeCode(tree.Children[i], matchingCode, ref haveLoop);
                    }
                }

                var code = GenerateIfElseChain(tree, branchCode, ref laVar, switchCases);

                if (laVar != null)
                {
                    block.Insert(0, F.Assign(laVar, CGH.LA(tree.Lookahead)));
                    _laVarsNeeded |= 1ul << tree.Lookahead;
                }
                else if (should)
                {
                    laVar = CGH.LA(tree.Lookahead);
                }

                if (should)
                {
                    Debug.Assert(switchCases.Count != 0);
                    code = CGH.GenerateSwitch(branchSets, branchCode, switchCases, code ?? F.Missing, laVar);
                }

                block.Add(code);
                return(F.Braces(block.ToVList()));
            }