diff --git a/Compiler/Models/Interfaces/IParser.cs b/Compiler/Models/Interfaces/IParser.cs new file mode 100644 index 0000000..9446b70 --- /dev/null +++ b/Compiler/Models/Interfaces/IParser.cs @@ -0,0 +1,10 @@ + +namespace Compiler +{ + public interface IParser + { + List Errors { get; set; } + + List Parse(List tokensList); + } +} \ No newline at end of file diff --git a/Compiler/Models/Parser/DeclareParser.cs b/Compiler/Models/Parser/DeclareParser.cs new file mode 100644 index 0000000..c49d9be --- /dev/null +++ b/Compiler/Models/Parser/DeclareParser.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Compiler; + +public class DeclareParser : IParser +{ + private List tokens; + private Lexeme CurrToken; + private int CurrIndex; + private int MaxIndex; + + public List Errors { get; set; } + + public DeclareParser() + { + Errors = new List(); + } + + public List Parse(List tokensList) + { + Errors.Clear(); + if (tokensList.Count <= 0) + return Errors; + tokens = tokensList; + CurrIndex = 0; + MaxIndex = tokensList.Count - 1; + CurrToken = tokens[CurrIndex]; + + + + return Errors; + } +} diff --git a/Compiler/Models/Parser/ReqParser.cs b/Compiler/Models/Parser/ReqParser.cs index 2d15b76..efc12ac 100644 --- a/Compiler/Models/Parser/ReqParser.cs +++ b/Compiler/Models/Parser/ReqParser.cs @@ -7,7 +7,7 @@ namespace Compiler; -public class ReqParser +public class ReqParser : IParser { private List tokens; private Lexeme CurrToken; @@ -15,7 +15,7 @@ public class ReqParser private int MaxIndex; public List Errors { get; set; } - + public ReqParser() { Errors = new List(); @@ -45,7 +45,7 @@ public List Parse(List tokensList) private void log(string str) { - + } private void ChangeCurrentToken() @@ -85,11 +85,7 @@ private void Z(bool get, bool neutralize = false) else { Errors.Add(new ParserError($"Ожидалось ключевое слово DECLARE, а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex, tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression)); - - //if (GetNextType() == LexemeType.Identifier) - // E(false); - //else - E(true); + E(true); } } @@ -104,11 +100,7 @@ private void E(bool get, bool neutralize = false) else { Errors.Add(new ParserError($"Ожидался идентификатор, а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex, tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression)); - - //if (GetNextType() == LexemeType.CONSTANT) - // CONST(false); - //else - CONST(true); + CONST(true); } } @@ -123,11 +115,7 @@ private void CONST(bool get, bool neutralize = false) else { Errors.Add(new ParserError($"Ожидалось ключевое слово CONSTANT, а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex, tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression)); - - //if (GetNextType() == LexemeType.INTEGER) - // INT(false); - //else - INT(true); + INT(true); } } @@ -142,11 +130,7 @@ private void INT(bool get, bool neutralize = false) else { Errors.Add(new ParserError($"Ожидалось ключевое слово INTEGER, а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex, tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression)); - - //if (GetNextType() == LexemeType.AssignmentOperator) - // ASSIGN(false); - //else - ASSIGN(true); + ASSIGN(true); } } @@ -161,11 +145,7 @@ private void ASSIGN(bool get, bool neutralize = false) else { Errors.Add(new ParserError($"Ожидался оператор присваивания, а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex, tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression)); - - //if (GetNextType() == LexemeType.Sign || GetNextType() == LexemeType.Number) - // NUMBER(false); - //else - NUMBER(true); + NUMBER(true); } } @@ -180,11 +160,7 @@ private void NUMBER(bool get, bool neutralize = false) else { Errors.Add(new ParserError($"Ожидался знак или число, а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex, tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression)); - - //if (GetNextType() == LexemeType.UnsignedInteger) - // UNSIGNEDINT(false); - //else - UNSIGNEDINT(true); + UNSIGNEDINT(true); } } @@ -199,11 +175,7 @@ private void UNSIGNEDINT(bool get, bool neutralize = false) else { Errors.Add(new ParserError($"Ожидалось число, а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex, tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression)); - - //if (GetNextType() == LexemeType.Semicolon) - // END(false); - //else - END(true); + END(true); } } @@ -218,11 +190,7 @@ private void END(bool get, bool neutralize = false) else { Errors.Add(new ParserError($"Ожидался идентификатор, а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex, tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression)); - - //if (GetNextType() == LexemeType.DECLARE) - // Z(false); - //else - Z(true); + Z(true); } } } \ No newline at end of file diff --git a/Compiler/Resources/Help.html b/Compiler/Resources/Help.html index 9ade409..60e4a20 100644 --- a/Compiler/Resources/Help.html +++ b/Compiler/Resources/Help.html @@ -17,10 +17,8 @@

Оглавление:

  • Текст
  • Пуск
  • Справка
  • -
  • Исправить найденные ошибки
  • -
    • Создать
      Создает новый файл для редактирования.
    • @@ -61,9 +59,6 @@
    • Вызов справки
      Отображает окно справки с описанием функций редактора.
    • О программе
      Показывает информацию о текстовом редакторе и его версии.
    - - -

    При нахождении ошибок в левом нижнем углу отобразится их количество и появится кнопка, предлагающая исправить их автоматически в один клик.

    diff --git a/Compiler/Resources/MethodOfAnalysis.html b/Compiler/Resources/MethodOfAnalysis.html index 01187a7..ccc67e8 100644 --- a/Compiler/Resources/MethodOfAnalysis.html +++ b/Compiler/Resources/MethodOfAnalysis.html @@ -8,12 +8,144 @@

    Метод анализа

    -

    Методом анализа является алгоритм синтаксического анализа, основанный на графе автоматной грамматики.

    -

    Графы или диаграммы состояний представляют собой геометрическую интерпретацию синтаксического анализа слева направо. В отличие от синтаксических деревьев, графы или диаграммы состояний используются только для автоматных грамматик.

    -

    Определение: Графом Γ(G[Z]) или диаграммой состояний называется совокупность узлов и направленных дуг, соединяющих узлы. Узлы графа соответствуют нетерминальным символам. Дуги графа направлены из одного узла в другой (или в тот же узел) таким образом, что из узла N дуга направляется в M и маркируется терминалом t, если в грамматике имеется правило вида: N → t M.

    -

    Граф конечного автомата:

    -
    - Diagram -
    +

    Методом анализа является метод рекурсивного спуска, представленный кодом ниже:

    +
    
    +private void Z(bool get, bool neutralize = false)
    +{
    +    if (get) ChangeCurrentToken();
    +
    +    if (CurrToken.Type == LexemeType.DECLARE || neutralize)
    +    {
    +        E(true);
    +    }
    +    else
    +    {
    +        Errors.Add(new ParserError($"Ожидалось ключевое слово DECLARE,
    +            а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex,
    +            tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression));
    +        E(true);
    +    }
    +}
    +
    +private void E(bool get, bool neutralize = false)
    +{
    +    if (get) ChangeCurrentToken();
    +
    +    if (CurrToken.Type == LexemeType.Identifier || neutralize)
    +    {
    +        CONST(true);
    +    }
    +    else
    +    {
    +        Errors.Add(new ParserError($"Ожидался идентификатор,
    +            а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex,
    +            tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression));
    +        CONST(true);
    +    }
    +}
    +
    +private void CONST(bool get, bool neutralize = false)
    +{
    +    if (get) ChangeCurrentToken();
    +
    +    if (CurrToken.Type == LexemeType.CONSTANT || neutralize)
    +    {
    +        INT(true);
    +    }
    +    else
    +    {
    +        Errors.Add(new ParserError($"Ожидалось ключевое слово CONSTANT,
    +            а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex,
    +            tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression));
    +        INT(true);
    +    }
    +}
    +
    +private void INT(bool get, bool neutralize = false)
    +{
    +    if (get) ChangeCurrentToken();
    +
    +    if (CurrToken.Type == LexemeType.INTEGER || neutralize)
    +    {
    +        ASSIGN(true);
    +    }
    +    else
    +    {
    +        Errors.Add(new ParserError($"Ожидалось ключевое слово INTEGER,
    +            а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex,
    +            tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression));
    +        ASSIGN(true);
    +    }
    +}
    +
    +private void ASSIGN(bool get, bool neutralize = false)
    +{
    +    if (get) ChangeCurrentToken();
    +
    +    if (CurrToken.Type == LexemeType.AssignmentOperator || neutralize)
    +    {
    +        NUMBER(true);
    +    }
    +    else
    +    {
    +        Errors.Add(new ParserError($"Ожидался оператор присваивания,
    +            а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex,
    +            tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression));
    +        NUMBER(true);
    +    }
    +}
    +
    +private void NUMBER(bool get, bool neutralize = false)
    +{
    +    if (get) ChangeCurrentToken();
    +
    +    if (CurrToken.Type == LexemeType.Sign || CurrToken.Type == LexemeType.UnsignedInteger
    +            || neutralize)
    +    {
    +        UNSIGNEDINT(CurrToken.Type == LexemeType.Sign);
    +    }
    +    else
    +    {
    +        Errors.Add(new ParserError($"Ожидался знак или число,
    +            а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex,
    +            tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression));
    +        UNSIGNEDINT(true);
    +    }
    +}
    +
    +private void UNSIGNEDINT(bool get, bool neutralize = false)
    +{
    +    if (get) ChangeCurrentToken();
    +
    +    if (CurrToken.Type == LexemeType.UnsignedInteger || neutralize)
    +    {
    +        END(true);
    +    }
    +    else
    +    {
    +        Errors.Add(new ParserError($"Ожидалось число,
    +            а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex,
    +            tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression));
    +        END(true);
    +    }
    +}
    +
    +private void END(bool get, bool neutralize = false)
    +{
    +    if (get) ChangeCurrentToken();
    +
    +    if (CurrToken.Type == LexemeType.Semicolon || neutralize)
    +    {
    +        Z(true);
    +    }
    +    else
    +    {
    +        Errors.Add(new ParserError($"Ожидался идентификатор,
    +            а встречено \"{CurrToken.Value}\"", CurrToken.StartIndex,
    +            tokens[MaxIndex].EndIndex, ErrorType.UnfinishedExpression));
    +        Z(true);
    +    }
    +}
    +
    \ No newline at end of file diff --git a/Compiler/Resources/ProblemStatement.html b/Compiler/Resources/ProblemStatement.html index 1330300..9d63296 100644 --- a/Compiler/Resources/ProblemStatement.html +++ b/Compiler/Resources/ProblemStatement.html @@ -25,21 +25,21 @@

    Особенности языка

    Константы в языке SQL - это элементы данных, значения которых известны на этапе компиляции и не изменяются в процессе выполнения программы. Для описания констант используется оператор DECLARE с ключевым словом CONSTANT.

    Формат записи для объявления целочисленной константы в SQL следующий:

    -
    DECLARE имя_константы CONSTANT INTEGER := значение;
    +
    DECLARE имя_константы CONSTANT INTEGER = значение;

    Примеры верных строк из языка

    В соответствии с разработанной автоматной грамматикой синтаксический анализатор (парсер) целочисленных констант будет считать верными следующие записи:

    -
    DECLARE total_amount CONSTANT INTEGER := -150;
    +
    DECLARE total_amount CONSTANT INTEGER = -150;
    -
    DECLARE productPrice CONSTANT INTEGER := +150;
    +
    DECLARE productPrice CONSTANT INTEGER = +150;
    -
    DECLARE expense_1_amount CONSTANT INTEGER := -50;
    +
    DECLARE expense_1_amount CONSTANT INTEGER = -50;
    -
    DECLARE product_price CONSTANT INTEGER := -150; DECLARE total_2 CONSTANT INTEGER := 50;
    +
    DECLARE product_price CONSTANT INTEGER = -150; DECLARE total_2 CONSTANT INTEGER = 50;
    -
    DECLARE productPrice3 CONSTANT INTEGER := 150; DECLARE expense_amount_4 CONSTANT INTEGER := -50;
    +
    DECLARE productPrice3 CONSTANT INTEGER = 150; DECLARE expense_amount_4 CONSTANT INTEGER = -50;
    diff --git a/Compiler/Resources/correct_test_case.txt b/Compiler/Resources/correct_test_case.txt index ab94802..5a58a56 100644 --- a/Compiler/Resources/correct_test_case.txt +++ b/Compiler/Resources/correct_test_case.txt @@ -1,6 +1,6 @@ -DECLARE product_price CONSTANT INTEGER := +150; -DECLARE expense_1_amount CONSTANT INTEGER := +50; -DECLARE product_price CONSTANT INTEGER := -150; +DECLARE product_price CONSTANT INTEGER = +150; +DECLARE expense_1_amount CONSTANT INTEGER = +50; +DECLARE product_price CONSTANT INTEGER = -150; -DECLARE total_2 CONSTANT INTEGER:= 50; DECLARE productPrice3 CONSTANT INTEGER = +150; +DECLARE total_2 CONSTANT INTEGER = 50; DECLARE productPrice3 CONSTANT INTEGER = +150; diff --git a/Compiler/Resources/wrong_test_case.txt b/Compiler/Resources/wrong_test_case.txt index f6b6756..c228506 100644 --- a/Compiler/Resources/wrong_test_case.txt +++ b/Compiler/Resources/wrong_test_case.txt @@ -1,8 +1,2 @@ -!D!E!C!L!A!R!E! 123product_price 0C1O2N3S4T5A6N7T8 DECLARE INTEhihihiGER DECfffLARE := +150; -! -? -DECLARE expense_1_amount tyjjtjty GLUTCONSTANT CONSTANT AbC INTEGER := +-+-+-+-+-50; -DECLARE product_price CONSTANT INTEGER := -150; - -DECLARE total_2 CONSTANT +INTEGER+ := 50; DECLARE productPrice3 CONSTANT INTEGER = ++150; - +DECLAR "product_price CONSTANT INTEGER =@ +150; +DECLARE expense_1_amount INTEGER = +50; diff --git a/Compiler/ViewModels/MainWindowViewModel.cs b/Compiler/ViewModels/MainWindowViewModel.cs index dc51967..687e3eb 100644 --- a/Compiler/ViewModels/MainWindowViewModel.cs +++ b/Compiler/ViewModels/MainWindowViewModel.cs @@ -6,7 +6,7 @@ namespace Compiler; public class MainWindowViewModel : ViewModelBase { - private ReqParser _parser; + private IParser _parser; private FileManager _fileManager; private ILexicalAnalyzer _lexicalAnalyzer;