public LNode Call(string funcName) { return(F.Call(GSymbol.Get(funcName))); }
public bool RemoveTag(string key) { return(RemoveTag(GSymbol.GetIfExists(key))); }
public ValueT GetTag(string key) { return(GetTag(GSymbol.GetIfExists(key))); }
public LNode Var(LNode type, string name, LNode initValue = null) { return(Var(type, GSymbol.Get(name), initValue)); }
public static Symbol NextTempName(IMacroContext ctx, string prefix = "tmp_") { return(GSymbol.Get(prefix + ctx.IncrementTempCounter())); }
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)); }
public LNode Call(string target, params LNode[] args) { return(Call(GSymbol.Get(target), args)); }
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); }
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; } }
protected virtual Symbol GenerateSetName(Rule currentRule) { return(GSymbol.Get(string.Format("{0}_set{1}", currentRule.Name.Name, _setNameCounter++))); }
Symbol NamespaceToSymbol(LNode node) { // quick & dirty, probably not cheap return(GSymbol.Get(node.Print(NodeStyle.Expression))); }
public static Symbol NextTempName() { return(GSymbol.Get("tmp_" + _nextTempCounter++)); }
public Rule MakeRecognizerVersion() { var scanName = GSymbol.Get("Scan_" + Name.Name); return(_recognizer = _recognizer ?? MakeRecognizerVersion(scanName)); }
internal static HashSet <Symbol> SymbolSet(params string[] input) { return(new HashSet <Symbol>(input.Select(s => GSymbol.Get(s)))); }
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()"), }); }
static Symbol PickVarNameForRuleName(Symbol name) { return(GSymbol.Get("got_" + name)); }
public void GetNonexistantId() { Assert.AreEqual(GSymbol.GetById(876543210), null); Assert.AreEqual(GSymbol.GetById(-876543210), null); }
static Symbol LiteralToVarName(object literal) { string prefix = literal is char? "ch" : "lit"; return(GSymbol.Get(prefix + LiteralToIdent(literal))); }
/// <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))); }
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")); }
public LNode Dot(params string[] symbols) { return(Dot(symbols.SelectArray(s => Id(GSymbol.Get(s))))); }
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)))); }
/// <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")); }
void ParseBQStringValue() { var value = ParseStringCore(_startPosition); _value = GSymbol.Get(value.ToString()); }
[DebuggerStepThrough] static Symbol _(string s) { return(GSymbol.Get(s)); }
public override void Configure(global::LeMP.Compiler c) { c.MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("Loyc.LLPG")); base.Configure(c); }
public bool HasTag(string key) { return(HasTag(GSymbol.GetIfExists(key))); }
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; } }
public void SetTag(string key, ValueT val) { SetTag(GSymbol.Get(key), val); }
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())); }