Exemplo n.º 1
0
		[STAThread] // Required by ICSharpCode.TextEditor
		public static void Main(string[] args)
		{
			BMultiMap<string,string> options = new BMultiMap<string,string>();

			var argList = args.ToList();
			UG.ProcessCommandLineArguments(argList, options, "", ShortOptions, TwoArgOptions);
			if (!options.ContainsKey("nologo"))
				Console.WriteLine("LeMP macro compiler (pre-alpha)");

			string _;
			if (options.TryGetValue("help", out _) || options.TryGetValue("?", out _)) {
				ShowHelp(KnownOptions.OrderBy(p => p.Key));
				return;
			}
			if (options.ContainsKey("editor")) {
				Console.WriteLine("Starting editor...");
				System.Windows.Forms.Application.EnableVisualStyles();
				System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
				System.Windows.Forms.Application.Run(new TextEditor.LempDemoForm());
				return;
			}

			Severity minSeverity = Severity.Note;
			#if DEBUG
			minSeverity = Severity.Debug;
			#endif
			var filter = new SeverityMessageFilter(MessageSink.Console, minSeverity);

			Compiler c = ProcessArguments(options, filter, typeof(Macros), argList);
			Compiler.WarnAboutUnknownOptions(options, MessageSink.Console, KnownOptions);
			if (c != null) {
				c.AddMacros(typeof(global::LeMP.StandardMacros).Assembly);
				c.MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude"));
				c.MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LeMP"));
				using (LNode.PushPrinter(Ecs.EcsNodePrinter.PrintPlainCSharp))
					c.Run();
			} else if (args.Length == 0) {
				ShowHelp(KnownOptions.OrderBy(p => p.Key));

				Console.WriteLine();
				Console.WriteLine("LeMP started without arguments. Starting editor (--editor)");

				var thread = new ThreadEx(() => {
					System.Windows.Forms.Application.EnableVisualStyles();
					System.Windows.Forms.Application.Run(new TextEditor.LempDemoForm());
				});
				thread.Thread.SetApartmentState(ApartmentState.STA);
				thread.Start();

				Console.WriteLine("Press Enter to run unit tests. Using the editor? Keep the terminal open.");
				Console.ReadLine();

				RunTests.Run(new Loyc.Syntax.Lexing.TokenTests());
				RunTests.Run(new Loyc.Syntax.Les.LesLexerTests());
				RunTests.Run(new Loyc.Syntax.Les.LesParserTests());
				RunTests.Run(new Loyc.Syntax.Les.LesPrinterTests());
				RunLeMPTests();
				Ecs.Program.RunEcsTests();
			}
		}
Exemplo n.º 2
0
		public static void Main(params string[] args)
		{
			IDictionary<string, Pair<string, string>> KnownOptions = LeMP.Compiler.KnownOptions;
			if (args.Length != 0) {
				BMultiMap<string,string> options = new BMultiMap<string,string>();

				var argList = args.ToList();
				UG.ProcessCommandLineArguments(argList, options, "", LeMP.Compiler.ShortOptions, LeMP.Compiler.TwoArgOptions);
				if (!options.ContainsKey("nologo"))
					Console.WriteLine("LLLPG/LeMP macro compiler");

				string _;
				if (options.TryGetValue("help", out _) || options.TryGetValue("?", out _) || args.Length == 0) {
					LeMP.Compiler.ShowHelp(KnownOptions.OrderBy(p => p.Key));
					return;
				}

				Severity minSeverity = Severity.Note;
				#if DEBUG
				minSeverity = Severity.Debug;
				#endif
				var filter = new SeverityMessageFilter(MessageSink.Console, minSeverity);

				LeMP.Compiler c = LeMP.Compiler.ProcessArguments(options, filter, typeof(LeMP.Prelude.Les.Macros), argList);
				LeMP.Compiler.WarnAboutUnknownOptions(options, MessageSink.Console, KnownOptions);
				if (c != null) {
					c.MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LeMP.Prelude"));
					c.MacroProcessor.PreOpenedNamespaces.Add(Loyc.LLPG.Macros.MacroNamespace);
					c.AddMacros(Assembly.GetExecutingAssembly());
					c.AddMacros(typeof(LeMP.Prelude.Macros).Assembly);
					c.Run();
				}
			} else {
				LeMP.Compiler.ShowHelp(KnownOptions.OrderBy(p => p.Key));
				Tests();
				Ecs.Program.Main(args); // do EC# tests
			}
		}
Exemplo n.º 3
0
		void WhereClausesOpt(ref LNode name)
		{
			TokenType la0;
			#line 1163 "EcsParserGrammar.les"
			var list = new BMultiMap<Symbol,LNode>();
			#line default
			// Line 1164: (WhereClause)*
			for (;;) {
				la0 = LA0;
				if (la0 == TT.ContextualKeyword)
					list.Add(WhereClause());
				else
					break;
			}
			#line 1165 "EcsParserGrammar.les"
			if ((list.Count != 0)) {
				if ((!name.CallsMin(S.Of, 2))) {
					Error("'{0}' is not generic and cannot use 'where' clauses.", name.ToString());
				} else {
					var tparams = name.Args.ToRWList();
					for (int i = 1; i < tparams.Count; i++) {
						var wheres = list[TParamSymbol(tparams[i])];
						tparams[i] = tparams[i].PlusAttrs(wheres);
						wheres.Clear();
					}
					name = name.WithArgs(tparams.ToRVList());
					if ((list.Count > 0)) {
						Error(list[0].Value, "There is no type parameter named '{0}'", list[0].Key);
					}
				}
			}
			#line default
		}
Exemplo n.º 4
0
		public virtual int Generate(string inputFilePath, string inputFileContents, string defaultNamespace, IntPtr[] outputFileContents, out uint outputSize, IVsGeneratorProgress progressCallback)
		{
			string inputFolder = Path.GetDirectoryName(inputFilePath);
			string oldCurDir = Environment.CurrentDirectory;
			try {
 				Environment.CurrentDirectory = inputFolder; // --macros should be relative to file being processed

				var sourceFile = new StringCharSourceFile(inputFileContents, inputFilePath);
				var sink = ToMessageSink(progressCallback);
			
				var c = new Compiler(sink, sourceFile);

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

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

				Symbol minSeverity = MessageSink.Note;
				var filter = new SeverityMessageFilter(MessageSink.Console, minSeverity);

				if (LEL.Compiler.ProcessArguments(c, options)) {
					LEL.Compiler.WarnAboutUnknownOptions(options, MessageSink.Console, KnownOptions);
					if (c != null)
					{
						c.MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("LEL.Prelude"));
						c.MacroProcessor.PreOpenedNamespaces.Add(GSymbol.Get("Loyc.LLParserGenerator"));
						c.AddMacros(typeof(Loyc.LLParserGenerator.Macros).Assembly);
						c.Run();
					}

					var outputBytes = Encoding.UTF8.GetBytes(c.Output.ToString());
					c.Output = null; // no longer needed
					outputSize = (uint)outputBytes.Length;
					outputFileContents[0] = Marshal.AllocCoTaskMem(outputBytes.Length);
					Marshal.Copy(outputBytes, 0, outputFileContents[0], outputBytes.Length);
				}
				else
				{
					outputFileContents[0] = IntPtr.Zero;
					outputSize = 0;
				}
				return VSConstants.S_OK;
			} finally {
				Environment.CurrentDirectory = oldCurDir;
			}
		}
Exemplo n.º 5
0
		public static void WarnAboutUnknownOptions(BMultiMap<string, string> options, IMessageSink sink, IDictionary<string, Pair<string, string>> knownOptions)
		{
			foreach (var opt in options.Keys) {
				if (!knownOptions.ContainsKey(opt))
					sink.Write(Severity.Warning, "Command line", "Unrecognized option '--{0}'", opt);
			}
		}
Exemplo n.º 6
0
		public static bool ProcessArguments(Compiler c, BMultiMap<string, string> options)
		{
			string value;
			var filter = c.Sink as SeverityMessageFilter ?? new SeverityMessageFilter(c.Sink, Severity.Note);
			if (options.TryGetValue("verbose", out value))
			{
				if (value != "false") {
					try { // Enum.TryParse() does not exist before .NET 4 so use Enum.Parse
						filter.MinSeverity = (Severity)Enum.Parse(typeof(Severity), value);
					} catch (Exception) { // Docs say OverflowException, but that just sounds wrong
						filter.MinSeverity = Severity.Verbose;
					}
				}
			}
			
			IMessageSink sink = c.Sink = filter;
			
			if (options.TryGetValue("max-expand", out value))
				TryCatch("While parsing max-expand", sink, () => c.MaxExpansions = int.Parse(value));

			foreach (var macroDll in options["macros"])
			{
				Assembly assembly;
				TryCatch("While opening " + macroDll, sink, () =>
				{
					if (macroDll.Contains('\\') || macroDll.Contains('/')) {
						// Avoid "Absolute path information is required" exception
						string fullPath = Path.Combine(Environment.CurrentDirectory, macroDll);
						assembly = Assembly.LoadFile(fullPath);
					} else
						assembly = Assembly.LoadFrom(macroDll);
					c.AddMacros(assembly);
				});
			}
			foreach (var macroDll in options["macros-longname"])
			{
				Assembly assembly;
				TryCatch("While opening " + macroDll, sink, () =>
				{
					assembly = Assembly.Load(macroDll);
					c.AddMacros(assembly);
				});
			}
			if (options.TryGetValue("noparallel", out value) && (value == null || value == "true"))
				c.Parallel = false;
			if (options.TryGetValue("outext", out c.OutExt) && c.OutExt != null && !c.OutExt.StartsWith("."))
				c.OutExt = "." + c.OutExt;
			if (options.TryGetValue("inlang", out value)) {
				ApplyLanguageOption(sink, "--inlang", value, ref c.InLang);
			}
			if (options.TryGetValue("outlang", out value)) {
				IParsingService lang = null;
				ApplyLanguageOption(sink, "--outlang", value, ref lang);
				c.OutLang = lang.Printer ?? c.OutLang;
			}
			if (options.TryGetValue("forcelang", out value) && (value == null || value == "true"))
				c.ForceInLang = true;
			if (!options.ContainsKey("outlang") && c.OutExt != null && FileNameToLanguage(c.OutExt) == null)
				sink.Write(Severity.Error, "--outext", "No language was found for extension «{0}»", c.OutExt);
			double num;
			if (options.TryGetValue("timeout", out value)) {
				if (!double.TryParse(value, out num) || !(num >= 0))
					sink.Write(Severity.Error, "--timeout", "Invalid or missing timeout value", c.OutExt);
				else
					c.AbortTimeout = TimeSpan.FromSeconds(num);
			}

			return true;
		}
Exemplo n.º 7
0
		public static Compiler ProcessArguments(BMultiMap<string, string> options, SeverityMessageFilter sink, Type prelude, List<string> inputFiles)
		{
			if (inputFiles.Count == 0)
			{
				sink.Write(Severity.Error, null, "No input provided, stopping.");
				return null;
			}
			Compiler c = new Compiler(sink, prelude);
			c.Files = new List<InputOutput>(OpenSourceFiles(sink, inputFiles));
			return ProcessArguments(c, options) ? c : null;
		}
Exemplo n.º 8
0
		/// <summary>Processes command-line arguments to build a BMultiMap and 
		/// sends those options to the other overload of this method.</summary>
		/// <param name="args">Arg list from which to extract options. **NOTE**:
		/// discovered options are removed from the list. This parameter 
		/// cannot be an array.</param>
		/// <param name="warnAboutUnknownOptions">Whether this method should
		/// call <see cref="WarnAboutUnknownOptions"/> for you.</param>
		/// <param name="autoOpenInputFiles">Whether to open input files 
		/// for you by calling <see cref="OpenSourceFiles(IMessageSink, IEnumerable{string})"/>.
		/// </param>
		/// <param name="inputFiles">A list of input files to open if 
		/// autoOpenInputFiles is true. If this is null, The input files are 
		/// assumed to be those command-line arguments left over after the options 
		/// are removed.</param>
		/// <returns>The map of options (key-value pairs and, for options that 
		/// don't have a value, key-null pairs).</returns>
		/// <remarks>
		/// Note: If you get your command-line arguments as a single 
		/// string, use <see cref="G.SplitCommandLineArguments(string)"/> first 
		/// to split it into an array.
		/// <para/>
		/// This method doesn't check for --help. To implement --help, call 
		/// <see cref="MaybeShowHelp"/> on the return value.
		/// </remarks>
		public BMultiMap<string, string> ProcessArguments(IList<string> args, bool warnAboutUnknownOptions, bool autoOpenInputFiles, IList<string> inputFiles = null)
		{
			BMultiMap<string,string> options = new BMultiMap<string,string>();

			UG.ProcessCommandLineArguments(args, options, "", ShortOptions, TwoArgOptions);
			if (inputFiles == null && autoOpenInputFiles)
				inputFiles = args;
			if (!ProcessArguments(options, warnAboutUnknownOptions, inputFiles))
				return null;
			return options;
		}
Exemplo 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) { 
					AbortTimeout = TimeSpan.FromSeconds(10),
					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;
			}
		}
Exemplo n.º 10
0
		private bool? ParseBoolOption(BMultiMap<string, string> options, string key, IMessageSink sink)
		{
			string value;
			if (!options.TryGetValue(key, out value))
				return null;
			if (value == null)
				return true;
			if (value.Equals("true", StringComparison.InvariantCultureIgnoreCase) || value == "1")
				return true;
			if (value.Equals("false", StringComparison.InvariantCultureIgnoreCase) || value == "0")
				return false;
			if (sink != null)
				sink.Error("--" + key, "Expected boolean `true` or `false`");
			return null;
		}
Exemplo n.º 11
0
		private double? ParseNumericOption(BMultiMap<string, string> options, string key, IMessageSink sink, double? min = null, double? max = null)
		{
			string value;
			if (!options.TryGetValue(key, out value))
				return null;
			double num;
			if (double.TryParse(value ?? "", out num)) {
				if ((min == null || num >= min.Value) && 
					(max == null || num <= max.Value))
					return num;
			}
			if (sink != null) {
				if (min != null && max != null)
					sink.Error("--" + key, "Expected numeric value between {0} and {1}", min.Value, max.Value);
				else
					sink.Error("--" + key, "Expected numeric value");
			}
			return null;
		}
Exemplo n.º 12
0
		/// <summary>Processes all standard command-line arguments from 
		/// <see cref="KnownOptions"/>, except --help.</summary>
		/// <param name="options">A set of options, presumably derived from command-
		/// line options using <see cref="UG.ProcessCommandLineArguments"/></param>
		/// <param name="warnAboutUnknownOptions">Whether to warn (to <see cref="Sink"/>) 
		/// about options not listed in <see cref="KnownOptions"/>.</param>
		/// <param name="inputFiles">Files to open with <see cref="OpenSourceFiles"/></param>
		/// <returns>true, unless inputFiles != null and all input files failed to open.</returns>
		/// <remarks>
		/// This method calls AddStdMacros() unless options includes "nostdmacros".
		/// </remarks>
		public bool ProcessArguments(BMultiMap<string, string> options, bool warnAboutUnknownOptions, IList<string> inputFiles = null)
		{
			Compiler c = this;
			string value;
			bool? flag;
			double? num;
			var filter = c.Sink as SeverityMessageFilter ?? new SeverityMessageFilter(c.Sink, Severity.NoteDetail);

			if (warnAboutUnknownOptions)
				WarnAboutUnknownOptions(options, Sink, KnownOptions);

			if (options.TryGetValue("verbose", out value))
			{
				if (value != "false") {
					try { // Enum.TryParse() does not exist before .NET 4 so use Enum.Parse
						filter.MinSeverity = (Severity)Enum.Parse(typeof(Severity), value);
					} catch (Exception) { // Docs say OverflowException, but that just sounds wrong
						filter.MinSeverity = Severity.Verbose;
					}
				}
			}
			
			IMessageSink sink = c.Sink = filter;
			
			if ((num = ParseNumericOption(options, "max-expand", sink, 0, 99999)) != null)
				c.MaxExpansions = (int)num.Value;

			foreach (var macroDll in options["macros"])
			{
				Assembly assembly;
				TryCatch("While opening " + macroDll, sink, () =>
				{
					if (macroDll.Contains('\\') || macroDll.Contains('/')) {
						// Avoid "Absolute path information is required" exception
						string fullPath = Path.Combine(Environment.CurrentDirectory, macroDll);
						assembly = Assembly.LoadFile(fullPath);
					} else
						assembly = Assembly.LoadFrom(macroDll);
					c.AddMacros(assembly);
				});
			}
			foreach (string macroDll in options["macros-longname"])
			{
				Assembly assembly;
				TryCatch("While opening " + macroDll, sink, () =>
				{
					assembly = Assembly.Load(macroDll);
					c.AddMacros(assembly);
				});
			}
			if ((flag = ParseBoolOption(options, "noparallel", sink)) != null)
				c.Parallel = flag.Value;
			if (options.TryGetValue("outext", out c.OutExt)) {
				if (c.OutExt != null && !c.OutExt.StartsWith("."))
					c.OutExt = "." + c.OutExt;
			}
			if (options.TryGetValue("inlang", out value)) {
				ApplyLanguageOption(sink, "--inlang", value, ref c.InLang);
			}
			if (options.TryGetValue("outlang", out value)) {
				IParsingService lang = null;
				ApplyLanguageOption(sink, "--outlang", value, ref lang);
				c.OutLang = (lang as ILNodePrinter) ?? c.OutLang;
			}
			if ((flag = ParseBoolOption(options, "forcelang", sink)) != null)
				c.ForceInLang = flag.Value;
			if (!options.ContainsKey("outlang") && c.OutExt != null && ParsingService.GetServiceForFileName(c.OutExt) == null)
				sink.Error("--outext", "No language was found for extension «{0}»", c.OutExt);
			if ((num = ParseNumericOption(options, "timeout", sink)) != null)
				c.AbortTimeout = TimeSpan.FromSeconds(num.Value);

			foreach (string exprStr in options["set"])
				SetPropertyHelper(exprStr, quote: false);
			foreach (string exprStr in options["snippet"])
				SetPropertyHelper(exprStr, quote: true);

			if (!options.TryGetValue("nostdmacros", out value) && !options.TryGetValue("no-std-macros", out value))
				AddStdMacros();

			if (options.TryGetValue("preserve-comments", out value))
				PreserveComments = value == null || !value.ToString().ToLowerInvariant().IsOneOf("false", "0");

			// Printing options
			if ((num = ParseNumericOption(options, "o-indent-spaces", sink, 0, 20)) != null)
				OutOptions.IndentString = num.Value <= 0 ? "\t" : new string(' ', (int)num.Value);
			if ((flag = ParseBoolOption(options, "o-allow-change-parens", sink)) != null)
				OutOptions.AllowChangeParentheses = flag.Value;
			if ((flag = ParseBoolOption(options, "o-omit-comments", sink)) != null)
				OutOptions.OmitComments = flag.Value;
			if ((flag = ParseBoolOption(options, "o-omit-unknown-trivia", sink)) != null)
				OutOptions.OmitUnknownTrivia = flag.Value;
			if ((flag = ParseBoolOption(options, "o-explicit-trivia", sink)) != null)
				OutOptions.PrintTriviaExplicitly = flag.Value;
			if ((flag = ParseBoolOption(options, "o-compatibility-mode", sink)) != null)
				OutOptions.CompatibilityMode = flag.Value;
			if ((flag = ParseBoolOption(options, "o-compact-mode", sink)) != null)
				OutOptions.CompactMode = flag.Value;

			if (inputFiles != null) {
				this.Files = new List<InputOutput>(OpenSourceFiles(Sink, inputFiles));
				if (inputFiles.Count != 0 && Files.Count == 0)
					return false;
			}

			return true;
		}