pascalabcnet/pabcnetc_clear/ConsoleCompiler.cs

275 lines
12 KiB
C#
Raw Permalink Normal View History

2023-06-23 14:01:48 +03:00
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
2021-03-01 22:33:02 +03:00
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using PascalABCCompiler.Errors;
using System.IO;
using System.Linq;
using System.Globalization;
namespace PascalABCCompiler
{
/*class mc<T>
{
public static int meth()
{
return 3;
}
}*/
class ConsoleCompiler
{
private static string StringsPrefix = "PABCNETC_";
public static PascalABCCompiler.Compiler Compiler=null;
public static string FileName = "";
public static CompilerOptions.OutputType outputType;
public static DateTime StartTime;
private static string StringResourcesGet(string Key)
{
return StringResources.Get(StringsPrefix + Key);
}
/*public static void ShowConnectedParsers()
2021-03-01 22:33:02 +03:00
{
if (LanguageProvider.Instance.Languages.Count > 0)
2021-03-01 22:33:02 +03:00
{
Console.Write(StringResourcesGet("CONNECTED_PARSERS"));
foreach (ILanguage lang in LanguageProvider.Instance.Languages)
Console.Write(FormatTools.LanguageAndExtensionsFormatted(lang.Name, lang.FilesExtensions)+"; ");
2021-03-01 22:33:02 +03:00
Console.WriteLine();
}
}*/
2021-03-01 22:33:02 +03:00
public static bool CheckAndSplitDirective(string directive, out string name, out string value)
{
System.Diagnostics.Debug.Assert(directive[0] == '/');
directive = directive.Remove(0, 1);
name = null;
value = null;
var ss = directive.Split( new[]{':'}, 2);
name = ss[0].ToLower();
if (ss.Length > 1)
{
2021-11-17 18:59:21 +03:00
value = ss[1].Trim();
2021-03-01 22:33:02 +03:00
}
return true;
}
public static bool ApplyDirective(string name, string value, CompilerOptions co)
{
switch (name)
{
case "debug":
switch (value)
{
case "0":
co.Debug = false;
co.Optimise = true;
return true;
case "1":
co.Debug = true;
return true;
default:
Console.WriteLine("Bad value in 'Debug' directive '{0}'. Acceptable values are 0 or 1", value);
return false;
}
2021-11-17 17:10:37 +03:00
case "define":
co.ForceDefines.Add(value);
return true;
2021-03-01 22:33:02 +03:00
case "output":
2023-03-11 14:45:24 +03:00
if (!Compiler.CheckPathValid(value))
return false;
2021-03-01 22:33:02 +03:00
co.OutputFileName = Path.GetFileName(value);
if (Path.IsPathRooted(value))
{
co.OutputDirectory = Path.GetDirectoryName(value);
}
2020-07-17 07:02:36 +03:00
return true;
2021-03-01 22:33:02 +03:00
case "searchdir":
2023-06-23 14:01:48 +03:00
if (!Directory.Exists(value))
{
Console.WriteLine($"SearchDir \"{value}\" not found relative to \"{Environment.CurrentDirectory}\"");
return false;
}
co.SearchDirectories.Insert(0, value); // .Insert, чтобы определённые пользователем папки имели бОльший приоритет, чем стандартная
2021-03-01 22:33:02 +03:00
return true;
2022-05-12 19:55:45 +03:00
case "locale":
co.Locale = value;
return true;
2021-03-01 22:33:02 +03:00
default:
Console.WriteLine("No such directive name: '{0}'", name);
return false;
}
}
public static bool CheckAndApplyDirective(string directive, CompilerOptions co)
{
string name, value;
var b = CheckAndSplitDirective(directive,out name, out value);
if (!b)
return false;
b = ApplyDirective(name, value, co);
return b;
}
public static void OutputHelp()
{
Console.WriteLine("Command line: ");
Console.WriteLine("pabcnetcclear /directive1:value1 /directive2:value2 ... [inputfile]\n");
Console.WriteLine("Available directives:");
//Console.WriteLine(" /Help /H /?"); - запретил - конкурирует с pabcnetcclear /w/a.pas
2021-11-17 17:10:37 +03:00
Console.WriteLine(" /Debug:<0/1>");
Console.WriteLine(" /Define:<name>");
Console.WriteLine(" /Output:<[path\\]name>");
2021-03-01 22:33:02 +03:00
Console.WriteLine(" /SearchDir:<path>");
2022-05-12 19:55:45 +03:00
Console.WriteLine(" /Locale:<locale>");
Console.WriteLine(" /Version:");
2021-03-01 22:33:02 +03:00
Console.WriteLine();
2021-11-17 17:10:37 +03:00
Console.WriteLine("/Help show this message");
Console.WriteLine("/Output:<[path\\]name> compile into an executable called \"name\" and save it in \"path\" directory");
Console.WriteLine("/Debug:0 generates code with all .NET optimizations");
2021-03-01 22:33:02 +03:00
Console.WriteLine("/SearchDir:<path> add \"path\" to list of standart unit search directories. Last added paths would be searched first");
2022-05-12 19:55:45 +03:00
Console.WriteLine("/Locale:<locale> set locale of main thread of compiled program executable");
Console.WriteLine("/Version: outputs PascalABC.NET version");
2021-03-01 22:33:02 +03:00
}
public static int Main(string[] args)
{
// SSM 18.03.19 Делаю параметры командной строки. Формат: pabcnetc.exe /Dir1=value1 /Dir2=value2 ... fname dir
// dir - это пережиток старого - так можно было задавать каталог раньше. Пока - увы - пусть останется
// Пока сделаю только директивы /Help /H /? и /Debug=0(1)
// Имя директивы - это одно слово. Равенства может не быть - тогда value директивы равно null
// Вычленяем первое равенство и делим директиву: до него - name, после него - value. Если name или value - пустые строки, то ошибка
// 2022 г. К сожалению, директива с / конкурирует с именами каталогов в Linux. Надо писать новый консольный компилятор
2021-03-01 22:33:02 +03:00
DateTime ldt = DateTime.Now;
PascalABCCompiler.StringResourcesLanguage.LoadDefaultConfig();
Implement programming languages integration functionality (#3001) * Make standardModules Dictionary instead of LanguageId usage * Create new common string constants for pascal language * Add LanguagesData class template * Move some compiler directive string constants to Compiler project * Extract LanguagesData class to separate file Also extracted RuntimeServiceModule (IO-modules) management to new functions. * Fix pabcnetc crashing (KeyNotFoundException) * Make similar change in pabcnetc_clear * Return PABCExtensions in DomConverter.cs * Return compiler string constants to Tree Converter * Rename MoveSystemUnitForward method * Rename system unit variable * Add new parser load error (localized versions) * Fix pascal language name constant * Add system units property to parsers * Add LanguageKits directory with a test file * Implement language integrator Был реализован загрузчик комплектов дополнительных языков (всех кроме Pascal). Был пересмотрен подход к реализации ParsersController и этот класс сделан синглтоном. Добавлена загрузка стандартных модулей языков в CompilerOptions. * Squashed commit of the following: commit 8f9dc7e5a0dbe2516a2af44d8ef843b7c30e2292 Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Mon Mar 11 20:33:13 2024 +0300 fix #3050 commit 90363ced454216ef44c4919bb694b1a2c786b4b5 Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sun Mar 3 21:37:25 2024 +0300 Недобитки при сортировке строк commit c9d7ba7758d1cb4f41348f5cc9095b0350e0c005 Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sat Mar 2 13:32:14 2024 +0300 Order и OrderDescending для строк с Ordinal commit 6fbc0200bf4b413940a459f8b5d96c4597f561f4 Author: AlexanderZemlyak <92867056+AlexanderZemlyak@users.noreply.github.com> Date: Tue Feb 27 23:21:26 2024 +0300 Fix interface loop dependency check (#3047) Tests for problematic case were added commit e4d63bfef9ef22c3a21375b542d5540a593916e5 Author: bormant <bormant@mail.ru> Date: Tue Feb 27 23:18:25 2024 +0300 Fix typo: C (ru) -> C (en) (#3042) commit 0d37232d21ce81d3443ad680b21b865a2b2fe017 Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Tue Feb 27 19:15:08 2024 +0300 School - исправление пустого диапазона простых и IP-адресов commit 9fd4c7f3388b7e9b5cd6dbae1d619fa11827e30d Merge: 3cca2a89 6027083b Author: Ivan Bondarev <ibond84@googlemail.com> Date: Wed Feb 21 20:57:10 2024 +0100 Merge branch 'master' of https://github.com/pascalabcnet/pascalabcnet commit 3cca2a894940cf585772464d55ac5f4bcf8e01ae Author: Ivan Bondarev <ibond84@googlemail.com> Date: Wed Feb 21 20:56:49 2024 +0100 fix in formatter
2024-03-13 22:16:40 +03:00
// загрузка всех парсеров и других составляющих языков EVA
New languages engine (#3120) * Implement first version of languages interfaces and classes ParsersController заменен на LanguageProvider. * Update ParserTools.csproj * Update RemoteCompiler.cs * Update TestRunner * Rename LanguageIntegrator project to Languages * Update TestRunner * Rename Parsers folder * Rename PascalABCParser.dll to PascalABCLanguage.dll * Reorganise LanguageIntegrator and rename DocTagsParser * Update Release Generators * Update language loading messages * Update linux version * Move BaseParser fields to ILanguage interface * Revert "Update Release Generators" This reverts commit 26a991c71b81e643d9fbd9a815ddca222768dda9. * Revert "Rename PascalABCParser.dll to PascalABCLanguage.dll" * Clean the mess in parser folders * Organize namespaces properly * Revert "Rename LanguageIntegrator project to Languages" * Add new enclosing folders for standard languages * Organize namespaces of LanguageIntegrator properly * Rename StandardLanguages to Languages * Comment the rest of Visual basic source code * Update OutputPath in pascal parser project * Move BaseParser methods to IParser * Restore Pascal parser project initial structure * Add PascalLanguage project * Move SyntaxTreeConverters project to Languages\Pascal folder * Rename SemanticRules in parser project * Rename Errors1 to Errors in parser project * Delete LambdaConverter dll from installer * Update language integrator to load *Language.dll files * Move lambda converter project to pascal lanuage dir * Revert "Delete LambdaConverter dll from installer" This reverts commit dd56f559ebe4f8c4c5c33752d44e6953001b96a5. * Switch off VBNETParser building * Delete syntax tree converters controller * Delete lambda converter dll from repository * Reorganize syntax tree to semantic tree conversion stage * Add BaseLanguage class to make language initialization more neat * Delete syntax tree post processors entity from ILanguage and refactor ABCStatistics calls * Add new IDocParser interface for documentation comments parser * Clean up folders * Add helper data structures to reduce parameters amount in CompileInterface and CompileImplementation * Add documentation to language classes * Move Union struct in global namespace and project (ParserTools) * Add more comments and a safe select language method * Rename SemanticRules class * Fix directives format null bug * Add System.Linq ref to LanguageIntegrator * Delete SyntaxToSemanticTreeConverter interface * Add BaseSyntaxTreeConverter * Call safe select language method in intellisence * Delete source files providers from parsers * Rename GetSyntaxTree method * Change Prebuild tree to be virtual - not abstract * Refresh documentation a bit * Add temporary language check for ABCHealth button * Add parser reference to parser tools * Move current compilation unit assigning higher to avoid bug with unit check * Delete null DirectiveInfo's and refactor directives' code * Add a few more comments
2024-05-25 12:26:32 +03:00
Languages.Integration.LanguageIntegrator.LoadAllLanguages();
Implement programming languages integration functionality (#3001) * Make standardModules Dictionary instead of LanguageId usage * Create new common string constants for pascal language * Add LanguagesData class template * Move some compiler directive string constants to Compiler project * Extract LanguagesData class to separate file Also extracted RuntimeServiceModule (IO-modules) management to new functions. * Fix pabcnetc crashing (KeyNotFoundException) * Make similar change in pabcnetc_clear * Return PABCExtensions in DomConverter.cs * Return compiler string constants to Tree Converter * Rename MoveSystemUnitForward method * Rename system unit variable * Add new parser load error (localized versions) * Fix pascal language name constant * Add system units property to parsers * Add LanguageKits directory with a test file * Implement language integrator Был реализован загрузчик комплектов дополнительных языков (всех кроме Pascal). Был пересмотрен подход к реализации ParsersController и этот класс сделан синглтоном. Добавлена загрузка стандартных модулей языков в CompilerOptions. * Squashed commit of the following: commit 8f9dc7e5a0dbe2516a2af44d8ef843b7c30e2292 Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Mon Mar 11 20:33:13 2024 +0300 fix #3050 commit 90363ced454216ef44c4919bb694b1a2c786b4b5 Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sun Mar 3 21:37:25 2024 +0300 Недобитки при сортировке строк commit c9d7ba7758d1cb4f41348f5cc9095b0350e0c005 Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Sat Mar 2 13:32:14 2024 +0300 Order и OrderDescending для строк с Ordinal commit 6fbc0200bf4b413940a459f8b5d96c4597f561f4 Author: AlexanderZemlyak <92867056+AlexanderZemlyak@users.noreply.github.com> Date: Tue Feb 27 23:21:26 2024 +0300 Fix interface loop dependency check (#3047) Tests for problematic case were added commit e4d63bfef9ef22c3a21375b542d5540a593916e5 Author: bormant <bormant@mail.ru> Date: Tue Feb 27 23:18:25 2024 +0300 Fix typo: C (ru) -> C (en) (#3042) commit 0d37232d21ce81d3443ad680b21b865a2b2fe017 Author: Mikhalkovich Stanislav <miks@math.sfedu.ru> Date: Tue Feb 27 19:15:08 2024 +0300 School - исправление пустого диапазона простых и IP-адресов commit 9fd4c7f3388b7e9b5cd6dbae1d619fa11827e30d Merge: 3cca2a89 6027083b Author: Ivan Bondarev <ibond84@googlemail.com> Date: Wed Feb 21 20:57:10 2024 +0100 Merge branch 'master' of https://github.com/pascalabcnet/pascalabcnet commit 3cca2a894940cf585772464d55ac5f4bcf8e01ae Author: Ivan Bondarev <ibond84@googlemail.com> Date: Wed Feb 21 20:56:49 2024 +0100 fix in formatter
2024-03-13 22:16:40 +03:00
2021-03-01 22:33:02 +03:00
Compiler = new PascalABCCompiler.Compiler(null, null);
Compiler.InternalDebug.SkipPCUErrors = false;
CultureInfo ci = CultureInfo.InstalledUICulture;
if (StringResourcesLanguage.CurrentTwoLetterISO == "ru" && ci.TwoLetterISOLanguageName != "ru")
StringResourcesLanguage.CurrentLanguageName = StringResourcesLanguage.AccessibleLanguages[StringResourcesLanguage.TwoLetterISOLanguages.IndexOf("en")];
else
StringResourcesLanguage.CurrentLanguageName = StringResourcesLanguage.AccessibleLanguages[StringResourcesLanguage.TwoLetterISOLanguages.IndexOf(StringResourcesLanguage.CurrentTwoLetterISO)];
//Console.WriteLine("OK {0}ms", (DateTime.Now - ldt).TotalMilliseconds);
ldt = DateTime.Now;
//ShowConnectedParsers();
var n = args.Length;
if (n == 0)
{
//Console.WriteLine(StringResourcesGet("COMMANDLINEISABSENT"));
OutputHelp();
return 2;
}
// /W/a.pas расценивается как директива. Нужен более сложный паттерн: начинается с \буквы:
//var n1 = args.TakeWhile(a => a[0] == '/').Count(); // количество директив
// Поменяем: SSM 14/12/21
var n1 = args.TakeWhile(a => System.Text.RegularExpressions.Regex.IsMatch(a, @"^/\w+:")).Count(); // количество директив
2021-03-01 22:33:02 +03:00
if (n1<n-2)
{
Console.WriteLine("Error in argument {0}", args[n1+2]);
Console.WriteLine("Command line cannot contain any arguments after filename '{0}' and outdirname '{1}'", args[n1], args[n1 + 1]);
return 4;
}
if (n1 == n) // только директивы
{
string name, value;
var b = CheckAndSplitDirective(args[0], out name, out value);
if (!b) // Сообщение уже будет выдано
return 4;
switch (name)
{
case "help":
case "h":
case "?":
OutputHelp();
return 0;
case "version":
Console.WriteLine(PascalABCCompiler.Compiler.Version);
return 0;
2021-03-01 22:33:02 +03:00
default:
Console.WriteLine("Filename is absent. Nothing to compile");
return 4;
}
}
FileName = args[n1]; // следующий аргумент за директивами - имя файла
if (!File.Exists(FileName))
{
Console.WriteLine(StringResourcesGet("FILEISABSENT{0}"), "'" + FileName + "'");
return 3;
}
outputType = CompilerOptions.OutputType.ConsoleApplicaton;
CompilerOptions co = new CompilerOptions(FileName, outputType);
if (FileName.ToLower().EndsWith(StringConstants.platformProjectExtension))
2021-03-01 22:33:02 +03:00
co.ProjectCompiled = true;
if (n1 == n - 1)
//co.OutputDirectory = ""
;
else co.OutputDirectory = args[n - 1];
co.Rebuild = false;
co.Debug = false;
co.UseDllForSystemUnits = false;
for (var i = 0; i < n1; i++)
{
var b = CheckAndApplyDirective(args[i], co);
if (!b)
return 4;
}
bool success = true;
if (Compiler.Compile(co) != null)
Console.WriteLine("OK");
else
{
Console.WriteLine(StringResourcesGet("COMPILEERRORS"));
success = false;
}
// Console.WriteLine("OK {0}ms", (DateTime.Now - ldt).TotalMilliseconds); /////
for (int i = 0; i < Compiler.ErrorsList.Count; i++)
{
if (Compiler.ErrorsList[i] is LocatedError)
{
SourceLocation sl;
if ((sl = (Compiler.ErrorsList[i] as LocatedError).SourceLocation) != null)
Console.WriteLine(string.Format("[{0},{1}] {2}: {3}", sl.BeginPosition.Line, sl.BeginPosition.Column, Path.GetFileName(sl.FileName), Compiler.ErrorsList[i].Message));
else
Console.WriteLine(Compiler.ErrorsList[i]);
}
else
{
Console.WriteLine(Compiler.ErrorsList[i].Message);
Console.WriteLine(Compiler.ErrorsList[i].StackTrace);
}
break; // выйти после первой же ошибки
}
if (success)
return 0;
else return 1;
}
}
}