diff --git a/LanguageIntegrator/BaseLanguage.cs b/LanguageIntegrator/BaseLanguage.cs index 7e5864ffb..af9d7ba99 100644 --- a/LanguageIntegrator/BaseLanguage.cs +++ b/LanguageIntegrator/BaseLanguage.cs @@ -5,7 +5,6 @@ using PascalABCCompiler.Parsers; using System.Collections.Generic; using PascalABCCompiler.SyntaxTreeConverters; using PascalABCCompiler.TreeConverter; -using PascalABCCompiler.SyntaxTree; namespace Languages.Facade { @@ -18,29 +17,27 @@ namespace Languages.Facade /// /// Все параметры должны быть не null (и не пустым массивом), кроме IDocParser в случае, если он не требуется /// - public BaseLanguage(string name, string version, string copyright, ILanguageInformation languageInformation, - IParser parser, IDocParser docParser, List syntaxTreeConverters, bool applySyntaxTreeConvertersForIntellisense, - string[] filesExtensions, bool caseSensitive, string[] systemUnitNames) + public BaseLanguage(ILanguageInformation languageInformation, + IParser parser, IDocParser docParser, List syntaxTreeConverters) { - this.Name = name; - this.Version = version; - this.Copyright = copyright; this.LanguageInformation = languageInformation; this.Parser = parser; this.Parser.LanguageInformation = languageInformation; this.DocParser = docParser; this.SyntaxTreeConverters = syntaxTreeConverters; - this.ApplySyntaxTreeConvertersForIntellisense = applySyntaxTreeConvertersForIntellisense; - this.FilesExtensions = filesExtensions; - this.CaseSensitive = caseSensitive; - this.SystemUnitNames = systemUnitNames; } - public virtual string Name { get; protected set; } + public string Name => LanguageInformation.Name; - public virtual string Version { get; protected set; } + public string Version => LanguageInformation.Version; - public virtual string Copyright { get; protected set; } + public string Copyright => LanguageInformation.Copyright; + + public string[] FilesExtensions => LanguageInformation.FilesExtensions; + + public bool CaseSensitive => LanguageInformation.CaseSensitive; + + public string[] SystemUnitNames => LanguageInformation.SystemUnitNames; public virtual ILanguageInformation LanguageInformation { get; } @@ -50,16 +47,10 @@ namespace Languages.Facade public virtual List SyntaxTreeConverters { get; protected set; } - public virtual bool ApplySyntaxTreeConvertersForIntellisense { get; protected set; } + public bool ApplySyntaxTreeConvertersForIntellisense => LanguageInformation.ApplySyntaxTreeConvertersForIntellisense; public virtual syntax_tree_visitor SyntaxTreeToSemanticTreeConverter { get; protected set; } - public virtual string[] FilesExtensions { get; protected set; } - - public virtual bool CaseSensitive { get; protected set; } - - public virtual string[] SystemUnitNames { get; protected set; } - public abstract void SetSemanticConstants(); public abstract void SetSyntaxTreeToSemanticTreeConverter(); diff --git a/LanguageIntegrator/ILanguage.cs b/LanguageIntegrator/ILanguage.cs index 640cf2a20..9012ee723 100644 --- a/LanguageIntegrator/ILanguage.cs +++ b/LanguageIntegrator/ILanguage.cs @@ -45,6 +45,9 @@ namespace Languages.Facade /// List SyntaxTreeConverters { get; } + /// + /// Вызывать ли преобразователей синтаксического дерева в работе Intellisense + /// bool ApplySyntaxTreeConvertersForIntellisense { get; } /// diff --git a/LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguage.cs b/LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguage.cs index 239113ea5..16c29412b 100644 --- a/LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguage.cs +++ b/LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguage.cs @@ -9,20 +9,12 @@ namespace Languages.SPython public class SPythonLanguage : BaseLanguage { public SPythonLanguage() : base( - name: "SPython", - version: "0.0.1", - copyright: "Copyright © 2023-2025 by Vladislav Krylov, Egor Movchan", - + languageInformation: new Frontend.Data.SPythonLanguageInformation(), parser: new SPythonParser.SPythonLanguageParser(), docParser: null, - syntaxTreeConverters: new List() { new Frontend.Converters.StandardSyntaxTreeConverter(), new SyntaxSemanticVisitors.LambdaAnyConverter() }, - applySyntaxTreeConvertersForIntellisense: true, - - filesExtensions: new string[] { ".pys" }, - caseSensitive: true, - systemUnitNames: new string[] { "SPythonSystem", "SPythonHidden", "SPythonSystemPys" } + syntaxTreeConverters: new List() { new Frontend.Converters.StandardSyntaxTreeConverter(), new SyntaxSemanticVisitors.LambdaAnyConverter() } ) { ((SPythonParser.SPythonLanguageParser)Parser).SyntaxTreeConvertersForIntellisense = SyntaxTreeConverters; diff --git a/LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguageInformation.cs b/LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguageInformation.cs index 906237748..2c8c429b3 100644 --- a/LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguageInformation.cs +++ b/LanguagePlugins/SPython/SPythonLanguageInfo/SPythonLanguageInformation.cs @@ -1,4 +1,5 @@ -using PascalABCCompiler.Parsers; +using PascalABCCompiler; +using PascalABCCompiler.Parsers; using PascalABCCompiler.ParserTools.Directives; using PascalABCCompiler.SyntaxTree; using System; @@ -11,6 +12,18 @@ namespace Languages.SPython.Frontend.Data { internal class SPythonLanguageInformation : BaseLanguageInformation { + public override string Name => "SPython"; + + public override string Version => "0.0.1"; + + public override string Copyright => "Copyright © 2023-2025 by Vladislav Krylov, Egor Movchan"; + + public override string[] FilesExtensions => new string[] { ".pys" }; + + public override string[] SystemUnitNames => new string[] { "SPythonSystem", "SPythonHidden", "SPythonSystemPys" }; + + public override bool ApplySyntaxTreeConvertersForIntellisense => true; + public override BaseKeywords KeywordsStorage { get; } = new SPythonParser.SPythonKeywords(); public override Dictionary ValidDirectives { get; protected set; } diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParser.y b/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParser.y index 21d96bf30..119176230 100644 --- a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParser.y +++ b/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParser.y @@ -1116,7 +1116,6 @@ optional_semicolon public program_module NewProgramModule(program_name progName, Object optHeadCompDirs, uses_list mainUsesClose, syntax_tree_node progBlock, Object optPoint, LexLocation loc) { var progModule = new program_module(progName, mainUsesClose, progBlock as block, null, loc); - progModule.Language = "SPython"; if (optPoint == null && progBlock != null) { var fp = progBlock.source_context.end_position; diff --git a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParserYacc.cs b/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParserYacc.cs index 273a4127d..fff574ea7 100644 --- a/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParserYacc.cs +++ b/LanguagePlugins/SPython/SPythonParserKrylovMovchan/SPythonParserYacc.cs @@ -4,7 +4,7 @@ // GPPG version 1.3.6 // Machine: DESKTOP-V3E9T2U -// DateTime: 14.09.2025 15:38:38 +// DateTime: 07.11.2025 13:33:42 // UserName: alex // Input file @@ -1649,7 +1649,6 @@ public partial class SPythonGPPGParser: ShiftReduceParser ValidDirectives { get; protected set; } @@ -32,7 +44,7 @@ namespace PascalABCCompiler.Parsers public abstract string ProcedureName { get; } public abstract string FunctionName { get; } - public abstract bool CaseSensitive { get; } + public abstract bool ApplySyntaxTreeConvertersForIntellisense { get; } public abstract bool IncludeDotNetEntities { get; } diff --git a/ParserTools/ParserTools/BaseParser.cs b/ParserTools/ParserTools/BaseParser.cs index 30a2c2820..4ba75e2a6 100644 --- a/ParserTools/ParserTools/BaseParser.cs +++ b/ParserTools/ParserTools/BaseParser.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using PascalABCCompiler.Errors; using PascalABCCompiler.SyntaxTree; -using System; namespace PascalABCCompiler.Parsers { @@ -109,6 +108,7 @@ namespace PascalABCCompiler.Parsers if (root != null && root is compilation_unit compilationUnit) { + compilationUnit.Language = LanguageInformation.Name; compilationUnit.file_name = FileName; compilationUnit.compiler_directives = CompilerDirectives; diff --git a/ParserTools/ParserTools/ILanguageInformation.cs b/ParserTools/ParserTools/ILanguageInformation.cs index aab1422f5..16db69a16 100644 --- a/ParserTools/ParserTools/ILanguageInformation.cs +++ b/ParserTools/ParserTools/ILanguageInformation.cs @@ -11,6 +11,36 @@ namespace PascalABCCompiler.Parsers /// public interface ILanguageInformation { + /// + /// Название языка + /// + string Name { get; } + + /// + /// Версия языка + /// + string Version { get; } + + /// + /// Авторское право + /// + string Copyright { get; } + + /// + /// Чувствительность к регистру + /// + bool CaseSensitive { get; } + + /// + /// Расширения файлов, относящиеся к языку + /// + string[] FilesExtensions { get; } + + /// + /// Названия системных модулей (стандартной библиотеки и др.) + /// + string[] SystemUnitNames { get; } + /// /// Получить полное описание элемента (в желтой подсказке) /// @@ -140,6 +170,11 @@ namespace PascalABCCompiler.Parsers int FindParamDelimForIndexer(string descriptionAfterOpeningParenthesis, int number); + /// + /// Вызывать ли преобразователей синтаксического дерева в работе Intellisense + /// + bool ApplySyntaxTreeConvertersForIntellisense { get; } + Dictionary SpecialModulesAliases { get; } BaseKeywords KeywordsStorage @@ -172,10 +207,6 @@ namespace PascalABCCompiler.Parsers { get; } - bool CaseSensitive - { - get; - } bool IncludeDotNetEntities { get; diff --git a/Parsers/PascalABCParserNewSaushkin/ABCPascal.y b/Parsers/PascalABCParserNewSaushkin/ABCPascal.y index 37e4696c9..dce4b25c5 100644 --- a/Parsers/PascalABCParserNewSaushkin/ABCPascal.y +++ b/Parsers/PascalABCParserNewSaushkin/ABCPascal.y @@ -427,16 +427,14 @@ unit_file unit_header interface_part implementation_part initialization_part tkPoint { $$ = new unit_module($1 as unit_name, $2 as interface_node, $3 as implementation_node, - ($4 as initfinal_part).initialization_sect, ($4 as initfinal_part).finalization_sect, /*$1 as attribute_list*/ null, @$); - ($$ as compilation_unit).Language = PascalABCCompiler.StringConstants.pascalLanguageName; + ($4 as initfinal_part).initialization_sect, ($4 as initfinal_part).finalization_sect, /*$1 as attribute_list*/ null, @$); } | //attribute_declarations unit_header abc_interface_part initialization_part tkPoint { $$ = new unit_module($1 as unit_name, $2 as interface_node, null, - ($3 as initfinal_part).initialization_sect, ($3 as initfinal_part).finalization_sect, /*$1 as attribute_list*/ null, @$); - ($$ as compilation_unit).Language = PascalABCCompiler.StringConstants.pascalLanguageName; + ($3 as initfinal_part).initialization_sect, ($3 as initfinal_part).finalization_sect, /*$1 as attribute_list*/ null, @$); } ; diff --git a/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs b/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs index 491c314bd..c9c3d7179 100644 --- a/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs +++ b/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs @@ -1,9 +1,9 @@ // (see accompanying GPPGcopyright.rtf) // GPPG version 1.3.6 -// Machine: DESKTOP-L2INHKG -// DateTime: 07.10.2025 10:49:02 -// UserName: user +// Machine: DESKTOP-V3E9T2U +// DateTime: 07.11.2025 13:32:32 +// UserName: alex // Input file // options: no-lines gplex @@ -3146,15 +3146,13 @@ public partial class GPPGParser: ShiftReduceParser unit_header, abc_interface_part, initialization_part, tkPoint { CurrentSemanticValue.stn = new unit_module(ValueStack[ValueStack.Depth-4].stn as unit_name, ValueStack[ValueStack.Depth-3].stn as interface_node, null, - (ValueStack[ValueStack.Depth-2].stn as initfinal_part).initialization_sect, (ValueStack[ValueStack.Depth-2].stn as initfinal_part).finalization_sect, /*$1 as attribute_list*/ null, CurrentLocationSpan); - (CurrentSemanticValue.stn as compilation_unit).Language = PascalABCCompiler.StringConstants.pascalLanguageName; + (ValueStack[ValueStack.Depth-2].stn as initfinal_part).initialization_sect, (ValueStack[ValueStack.Depth-2].stn as initfinal_part).finalization_sect, /*$1 as attribute_list*/ null, CurrentLocationSpan); } break; case 49: // unit_header -> unit_key_word, unit_name, tkSemiColon, diff --git a/Parsers/PascalABCParserNewSaushkin/SemanticRulesForYacc.cs b/Parsers/PascalABCParserNewSaushkin/SemanticRulesForYacc.cs index 454266307..86a41e551 100644 --- a/Parsers/PascalABCParserNewSaushkin/SemanticRulesForYacc.cs +++ b/Parsers/PascalABCParserNewSaushkin/SemanticRulesForYacc.cs @@ -46,7 +46,6 @@ namespace Languages.Pascal.Frontend.Core public program_module NewProgramModule(program_name progName, Object optHeadCompDirs, uses_list mainUsesClose, syntax_tree_node progBlock, Object optPoint, LexLocation loc) { var progModule = new program_module(progName, mainUsesClose, progBlock as block, null, loc); - progModule.Language = PascalABCCompiler.StringConstants.pascalLanguageName; if (optPoint == null && progBlock != null) { var fp = progBlock.source_context.end_position; diff --git a/PascalABCLanguageInfo/PascalABCLanguage.cs b/PascalABCLanguageInfo/PascalABCLanguage.cs index 389092a7d..ed66ce0bb 100644 --- a/PascalABCLanguageInfo/PascalABCLanguage.cs +++ b/PascalABCLanguageInfo/PascalABCLanguage.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using Languages.Facade; -using PascalABCCompiler; using PascalABCCompiler.SyntaxTreeConverters; using PascalABCCompiler.SystemLibrary; using PascalABCCompiler.TreeConverter; @@ -14,20 +13,12 @@ namespace Languages.Pascal { public PascalABCLanguage() : base( - name: StringConstants.pascalLanguageName, - version: "1.2", - copyright: "Copyright © 2005-2025 by Ivan Bondarev, Stanislav Mikhalkovich", languageInformation: new Frontend.Data.PascalABCLanguageInformation(), parser: new Frontend.Wrapping.PascalABCNewLanguageParser(), docParser: new Frontend.Documentation.PascalDocTagsLanguageParser(), - syntaxTreeConverters: new List() { new Frontend.Converters.StandardSyntaxTreeConverter(), new SyntaxSemanticVisitors.LambdaAnyConverter() }, - applySyntaxTreeConvertersForIntellisense: false, - - filesExtensions: new string[] { StringConstants.pascalSourceFileExtension }, - caseSensitive: false, - systemUnitNames: StringConstants.pascalDefaultStandardModules + syntaxTreeConverters: new List() { new Frontend.Converters.StandardSyntaxTreeConverter(), new SyntaxSemanticVisitors.LambdaAnyConverter() } ) { } diff --git a/PascalABCLanguageInfo/PascalABCLanguageInformation.cs b/PascalABCLanguageInfo/PascalABCLanguageInformation.cs index 97c05256d..19ce05306 100644 --- a/PascalABCLanguageInfo/PascalABCLanguageInformation.cs +++ b/PascalABCLanguageInfo/PascalABCLanguageInformation.cs @@ -16,6 +16,18 @@ namespace Languages.Pascal.Frontend.Data { public class PascalABCLanguageInformation : BaseLanguageInformation { + public override string Name => StringConstants.pascalLanguageName; + + public override string Version => "1.2"; + + public override string Copyright => "Copyright © 2005-2025 by Ivan Bondarev, Stanislav Mikhalkovich"; + + public override string[] FilesExtensions => new string[] { StringConstants.pascalSourceFileExtension }; + + public override string[] SystemUnitNames => StringConstants.pascalDefaultStandardModules; + + public override bool ApplySyntaxTreeConvertersForIntellisense => false; + protected IParser Parser { get diff --git a/documentation/DeveloperGuides/Integrating new language.md b/documentation/DeveloperGuides/Integrating new language.md index 90b7a8bdb..ee2ad55b8 100644 --- a/documentation/DeveloperGuides/Integrating new language.md +++ b/documentation/DeveloperGuides/Integrating new language.md @@ -1,5 +1,5 @@ - ### Шаг 1 -Необходимо создать папку, называющуюся так же, как Ваш язык в папке *LanguagePlugins*, расположенной в корне репозитория. Далее создать в ней два обязательных проекта. Это проект парсера Вашего языка, а также проект, содержащий класс Вашего языка (унаследованный от класса `BaseLanguage`, находящегося в стандартном проекте `LanguageIntegrator`). +### Шаг 1 +Необходимо создать папку, называющуюся так же, как Ваш язык в папке *LanguagePlugins*, расположенной в корне репозитория. Далее создать в ней два обязательных проекта. Это проект парсера Вашего языка, а также проект, содержащий класс Вашего языка (унаследованный от класса `BaseLanguage`, находящегося в стандартном проекте `LanguageIntegrator`) и класс "базы данных" языка (унаследованный от класса `BaseLanguageInformation` из проекта `ParserTools`). Для совместимости целевой платформой Ваших проектов должна быть *.NET Framework 4.0*. В свойствах проекта и для Release, и для Debug версии должен быть выбран выходной путь `..\..\..\bin\`. @@ -7,7 +7,7 @@ > Чтобы платформа PascalABC.NET смогла подключить библиотеку с Вашим языком нужно, чтобы имя Вашей основной сборки (содержащей наследника `BaseLanguage`) заканчивалось на "LanguageInfo" (то есть имело вид \*LanguageInfo.dll). Имя наследника `BaseLanguage` должно иметь постфикс "Language". ### Шаг 2 -В проекты Вы добавляете все необходимые для работы ссылки. Вам точно понадобятся ссылки на проекты `ParserTools`, `Errors`, `SyntaxTree` в проекте Вашего парсера и на проекты `LanguageIntegrator`, `SyntaxVisitors`, `TreeConverter` в проекте с наследником `BaseLanguage`. +В проекты Вы добавляете все необходимые для работы ссылки. Вам точно понадобятся ссылки на проекты `ParserTools`, `Errors`, `SyntaxTree` в проекте Вашего парсера и на проекты `LanguageIntegrator`, `ParserTools`, `SyntaxTree` в проекте с наследником `BaseLanguage`. ### Шаг 3 Вам нужно унаследовать Ваш парсер (который является оберткой над GPPG парсером) от класса `BaseParser`, либо напрямую реализовать интерфейс `IParser`, если Вы не хотите пользоваться функциональностью из `BaseParser`. @@ -16,21 +16,26 @@ Для реализации `BuildTreeInNormalMode` Вам потребуется вызвать в этом методе сгенерированный GPPG парсер Вашего языка. Возвращаемое значение должно быть корнем полученного в результате парсинга синтаксического дерева. Для реализации парсера Вы можете также использовать такие базовые абстрактные классы как `BaseKeywords` и `BaseParserTools`. + ### Шаг 4 -В сделанном Вами наследнике `BaseLanguage` Вы пишете конструктор, который передает в `base()` следующие параметры: +Для реализации методов в наследнике `BaseLanguageInformation` на первое время можно взять методы из `PascalABCLanguageInformation`, они используются в системе *Intellisense*. Но Вам также нужно задать следующие параметры языка: 1) имя языка, версия языка, строка с указанием авторских прав -2) класс "базы данных" языка, хранящий информацию в основном необходимую для Intellisense (наследник `BaseLanguageInformation`). На первое время можно использовать PascalABCLangaugeInformation. -3) парсер Вашего языка (наследник `BaseParser`) -4) парсер XML-комментариев (если его нет, то можно передавать `null`) -5) список преобразователей синтаксического дерева с одним обязательным элементом (для него можно взять стандартную базовую версию под названием `DefaultSyntaxTreeConverter`) -6) флаг дающий системе Intellisense информацию о том, нужно ли запускать преобразователи синтаксического дерева -7) расширения файлов Вашего языка -8) чувствительность к регистру -9) имена стандартных модулей языка +2) расширения файлов Вашего языка +3) имена стандартных модулей языка +4) чувствительность к регистру +и т. д. + +### Шаг 5 +В сделанном Вами наследнике `BaseLanguage` Вы пишете конструктор, который передает в `base()` следующие параметры: +1) класс "базы данных" языка, хранящий информацию в основном необходимую для Intellisense (наследник `BaseLanguageInformation`). +2) парсер Вашего языка (наследник `BaseParser`) +3) парсер XML-комментариев (если его нет, то можно передавать `null`) +4) список преобразователей синтаксического дерева с одним обязательным элементом (для него можно взять стандартную базовую версию под названием `DefaultSyntaxTreeConverter`) Также Вы реализуете метод `SetSemanticConstants`, в котором задаете необходимые параметры (значения переменных) из файла *SemanticRulesConstants.cs* (проект TreeConverter). -И наконец, реализуете метод `SetSyntaxTreeToSemanticTreeConverter`, в котором создаете новый экземпляр преобразователя синтаксического дерева в семантическое (присваиваете его свойству `SyntaxTreeToSemanticTreeConverter`). Для простых языков в качестве преобразователя Вам подойдет стандартный `syntax_tree_visitor`. +И наконец, реализуете метод `SetSyntaxTreeToSemanticTreeConverter`, в котором создаете новый экземпляр преобразователя синтаксического дерева в семантическое (присваиваете его свойству `SyntaxTreeToSemanticTreeConverter`). Для простых языков в качестве преобразователя можно присваивать +экземпляр класса `syntax_tree_visitor`, получив его следующим образом: `LanguageProvider.Instance.MainLanguage.SyntaxTreeToSemanticTreeConverter`. --- Если описанные выше шаги проделаны правильно, то при запуске оболочки в окне сообщений компилятора Вы увидите информацию о Вашем языке в списке подключенных. Если же в этом окне будет выводиться ошибка, связанная с подключением сборки Вашего языка, то обратитесь к файлу *log.txt* в папке `bin` (запись в лог ведется только в режиме Debug). \ No newline at end of file