GithubHelp home page GithubHelp logo

lead-tools / bsparser Goto Github PK

View Code? Open in Web Editor NEW
24.0 6.0 13.0 1.76 MB

[RIP] Парсер встроенного языка

Home Page: https://lead-tools.github.io/bsparser/

License: MIT License

1C Enterprise 99.38% PowerShell 0.62%
1c-enterprise parser bsl linter educational ast compiler compiler-construction

bsparser's People

Contributors

agponomarev avatar gitter-badger avatar nixel2007 avatar tsukanov-as avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

bsparser's Issues

Разделить подписки плагинов на два вида: Начало/Окончание обхода узла

Сейчас подписки вызываются по окончании обхода узла обобщенным визитером. Это позволит предоставить полезную информацию (например, статистику по подчиненным узлам) обработчику подписки, но не всегда удобно, так как подписки плагина в этом случае вызываются в обратном порядке обхода дерева (снизу вверх).

Ошибка парсинга

Вот такая конструкция вызывает ошибку

#Если Клиент Тогда
ИначеЕсли КакоеТоУсловие Тогда

Добавить плагин проверяющий что все локальные переменные объявлены

  • проверять что все локальные переменные объявлены
  • проверять что объявленные используются
  • запретить прямое присваивание глобальным переменным:
    для присваивания глобальной переменной нужно выделять процедуру, которой передавать глобал параметром, и присваивать уже этому параметру внутри процедуры

Добавить разбор препроцессора

Парсить по аналогии с обычным If Then. Все возможности это не покроет, но при нормальном стиле кодинга 99.99% будет разбираться без ошибок. Оставшиеся ошибки разбора пусть будут сигналом переписать это дерьмо (любая интерпретация фразы верна)

Сделать парсер более строгим

  • Выдавать ошибку разбора если в числовом литерале более одной точки (сейчас исключение преобразования в число)
  • Выдавать ошибку разбора если в объявлении локальной переменной указан Export (сейчас тихий игнор)
  • Запретить обращение к переменной в правой части присваивания, если эта переменная создается в левой части (создавать переменную после разбора выражения)
  • Циклы For и For Each должны создавать авто-переменные после разбора выражений
  • Если до методов в модуле есть регион, то переменная сразу за ним будет ошибкой разбора
  • Обращение по индексу может содержать только одно выражение (сейчас список)
  • Для первого варианта New нужно выделить отдельную сущность под конструктор (сейчас берется переменная или функция из текущего скопа)
  • Выражения препроцессора должны разбираться в рамках отдельного фиктивного скопа
  • Выражения препроцессора могут быть только логическими (сейчас парсер пропускает любые)
  • Проверять что директивы и инструкции препроцессора являются правильными идентификаторами (сейчас исключение в Property())

Доработать транслятор BSL

  • Все узлы должны корректно транслироваться
  • Восстанавливать форматирование насколько это возможно
  • Тип узлов проверять только через перечисление Nodes

Вместо Goto-транслятора сделать While-транслятор

Надо таки наверно вернуться к этой заготовке и добить ее 😄
Уже в самом начале стало понятно, что идея с Goto была плохой. Проблема в возвратах из процедур - для них придется городить большой If, в котором будут все возможные места возврата. Вариант рабочий, но дюже некрасивый. Потому я на него забил.
Вызов процедур лучше организовать на состояниях в цикле по аналогии с машиной Тьюринга.

Стабилизация кода к версии 1.0-alpha

  • сделать общий конструктор узлов AST (для автодоков)
  • сделать разбор выражений однообразным (операции в массивах)
  • выделить субрегионы ParseExpr, ParseDecl, etc в регионе Parser
  • все узлы (кроме элементов скопа) должны иметь информацию о положении в исходном коде
  • информацию о положении в исходном коде хранить в узлах в одном поле-структуре "Place"
  • названия полей в узлах заменить по возможности на более лаконичные
  • состав полей узлов должен быть фиксированным
  • описание типов полей в комментариях должно быть формальным (для автодоков)
  • упразднить узел Object (просто лишняя сущность)
  • Вместо Variable сделать два вида объектов: VarMod и VarLoc
  • добавить ключевое слово Null
  • добавить тип узла ElsIf
  • для Parser, Scanner, etc сделать общий конструктор Class (для автодоков)
  • сделать обобщенный визитер для плагинов

Убрать разбор структуры инструкций препроцессора

В AST хранить просто как отдельные операторы/декларации. Это позволит покрыть 99.99% синтаксис и избавиться от проблем типа #55

Анализ областей действия инструкций препроцессора при необходимости можно будет выполнить в визитере

Баг AfterVisitVisitPrepExpr

В процедуре VisitPrepExpr добавлен цикл:

For Each Hook In Visitor.Hooks.AfterVisitVisitPrepExpr Do
	Hook.AfterVisitVisitPrepExpr(PrepExpr, Visitor.Stack, Visitor.Counters);
EndDo;

Похоже ошибка, наверное имелось ввиду AfterVisitPrepExpr.

Точка после скобки

Не переваривает такой код:
SubsystemIndex = ?(SubsystemDescription.Parent = Undefined, RolesTree.Rows, SubsystemDescription.Parent.Rows).IndexOf(SubsystemDescription);

Оптимизация

Попробовать переделать с использованием StrFind():

  • ScanStringLen
  • ScanComment

Добавить связанный список родителей узла в визитере

Передавать родителя (элемент связанного списка) параметром в хук, чтобы в плагинах была возможность подняться вверх по дереву при необходимости.
В сами узлы добавлять родителя нельзя, т.к. появятся циклические ссылки

Добавить в визитер счетчики видов родительских узлов

Например, есть счетчик Visitor.Info.WhileStmtCount. При обходе подчиненных узлов цикла While увеличиваем счетчик на 1. При завершении обхода соответственно уменьшаем счетчик на 1.
Предполагается, что такая информация будет полезна в плагинах. Например, если плагин подписан на узел NewExpr и распознает создание запроса, то простая проверка Info.WhileStmtCount > 0 позволит выявить создание запроса внутри цикла (пример отстойный, да).

Совместимость с OneScript

  • Избавиться от реквизитов обработки парсера
  • Убрать лишние запятые в конструкторах структур (а может и вообще эту кухню переиграть)
  • Разбор инструкции препроцессора #Использовать
  • Проверить все плагины

Оптимизация разбора выражений

Сейчас ERP разбирается за 17 минут на ноуте 2.4ГГц (8 параллельных фоновых заданий)
Показатель неплохой, но кажется можно ускориться еще примерно в 2 раза.
Примерно 80% времени парсер тратит на разбор выражений, которые сейчас разбираются классическим рекурсивным спуском. Рекурсивный спуск требует большого количества вызовов функций, а это не дешево. Дешевле было бы выполнять разбор выражения по возможности в рамках одной функции.
Придумал вчера алгоритм разбора бинарных выражений со сложностью примерно O(n^2) который выполняется быстрее рекурсивного спуска по крайней мере на типовом размере выражений (0-3 оператора). Но выигрыш в целом небольшой, т.к. львиная доля затрат разбора в текущей реализации падает на анализ указателей(DesigExpr) и селекторов(SelectExpr).
Нужно попробовать унифицировать структуру выражений так, чтобы большая часть выражений была бинарной и пригодной для общего алгоритма. Грубо говоря все сводится к избавлению от сущностей DesigExpr и SelectExpr

Еще можно попробовать алгоритм сортировочной станции. Возможно он даже эффективнее, т.к. O(n).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.