Проверка синтаксиса
По сути задача похожая на написание компилятора (дескрипторы должны бинарится и выполняться движком).
Поэтому у меня и подход к ней как к компилятору - я уже написал лексический анализатор - он навыходе
даёт двунаправленый список лексем.
А вот запар возник с parsing'ом - одно дело синтаксический анализ мат. выражений и совсем другое
анализ дескрипторов - вот например как должно выглядеть синтаксическое дерево от для такой конструкции?:
;коментарий - это дескриптор, а не код С++
class Bullet: Ammo
{
maxspeed = 800;
model ="model.ms3d";
tracecolor[] = {0.8, 0.1, 0.1};
};
Как видите здесь не кактит подход разбиения на выражения, факторы и термы...
--------------------------------------------------
Вообщем меня интересует что вообше из себя должно представлять синтаксическое дерево в даном случае.
Я также прикрепляю лесический анализатор - он выводит список лексем дескриптора (Script.txt):
--------------------------------------------------
Вообщем меня интересует что вообше из себя должно представлять синтаксическое дерево в даном случае.
Я даже не понял причем тут дерево...
В мат.парсерах дерево определяет порядок вложенных действий. А какие здесь ДЕЙСТВИЯ? И есть ли тут вложенность? А пока вижу просто список не связанных друг с другом функций с несколькими переменными.
Если распишешь какие элементарные действия должен выполнить этот скрипт, будет понятнее.
Скорее всего получится несколько деревьев (каждое - со своим самодостаточным результатом), следующих друг за другом. Дерево не позволило бы например представить цикл...
Да и просто последовательность
print 10
print 15
как изобразить деревом??? что тут корень, а что - дочерняя ветка??? нету такого понятия... Оба равноправны и не являются составной частью друг друга, имеет значение только порядок следования.
Нет единственного результата. А если считать это все таки ОДНИМ итоговым результатом, то это очень не простой результат. Соответственно пришлось бы придумывать бесконечное количество функций. Например функция ДВА_ПОСЛЕДОВАТЕЛЬНЫХ_PRINT'а
А еще и ДВА_ПРИНТА_И_ЗВУКОВОЙ_СИГНАЛ_МЕЖДУ_НИМИ.
Но какой смысл такие связи притягивать за уши?
А синтаксический анализатор - а накой
ему дерево...
-------------------------------------------
Иногда (как и в этом случае) сложно объяснить, что
собсно нужно - но всё же - Ты внимательно читал вопрос!?!
-------------------------------------------
Я выложил LEXER - на экран выводиться список лексем (токенов), по сути он мало что значит,
особо язвительные счас спросят, мол нафиг он нужен - ОН ФОРМИРУЕТ ИЗ ВХОДНОГО ПОТОКА
СВЯЗНЫЙ СПИСОК КАЖДЫЙ УЗЕЛ КОТОРЫЙ СОДЕРЖИТ
ЛЕКСЕМУ И ЕЁ ТИП (надеюсь ненадо пояснять что такое связный список - а то опять кто-то что-то не
поймёт), т. е. на екране вы видите только элементы
списка во внешнем формате (НАДЕЮСЬ все поняли что за внешний формат и не будите грузить меня всякими
вопросами) - так вот PARSER (который пока НЕ НАПИСАН пока) и получает на входе указатель на вершину этого списка - так вот он и должен из этого списка
(где лексемы могут идти как попало)
сформировать СПИСОК-ДЕРЕВО синтаксическое (проверить синтаксически правильно ли раположены лексемы) - но здесь НЕ мат. выражения анализируются - так что тут общепринятые подходы не катят....
-----------------------------------------
т. е. если пользователь в скрипте напишет -
не color[] = {0.5, 0.5, 0.5};, а вот что такое
color[ < {0.5; - то PARSER должен понять что это
бодяга. Если всё правильно лексемы он должен распихать по узлам СПИСКА-ДЕРЕВА синтакисческого,
чтоб сними byte code generator уже работал...
--------------------------------------------
Для особо адарённых - допустим есть выражение,
expression:
color[] = {0.5, 0.5, 0.5}; - как для
него синтакисческое дерево будет выглядеть?
------------------------------------------
Проблема то как раз со вложенными конструкциями:
{
;какой либо код
{ ;какой либо вложенный код
{;вложений может быть много... }
};
};
него синтакисческое дерево будет выглядеть?
имя_переменной[]={ дейст_константа, дейст_константа, дейст_константа }
Объект -> class имя : предок { Атрибуты } ;
Атрибуты -> Атрибут | Атрибуты;
Атрибут -> имя = целая_константа;
Атрибут -> имя = строковая_константа;
Атрибут -> имя[] = массив_констант;
массив_констант-> { дейст_константа, дейст_константа, дейст_константа }
Атрибут -> пустое_выражение
Вообще, есть несколько проектов, где это используется. Вот один из них (он размещен на сайте "Королевство Дельфи" - на Дельфи).
Хотел бы сам с ним разобраться...
Блин, то что я выложил - это НЕ PARSER!!!!!!!!!!! ... Ты внимательно читал вопрос!?!
P( я ниче такого и не говорил!
Я главным образом хотел узнать, что будет происходить с тем, что появится на выходе PARSER'а ( P( не LEXER'а! )??? Мне так задача была бы понятнее.
Просто проверить правильность синтаксиса - не так уж трудно, используя рекурсивную функцию, которая знает все возможные типы лексем и их осмысленных комбинаций.
Она будет сканировать список лексем, начиная с указанной позиции, принимая массив допустимых типов (например на верхнем уровне допустим только один тип - "оператор", например: color[] = {0.5, 0.5, 0.5}; ). Вернуть должна тип выражения и позицию следующей за ним лексемы.
Она по первой лексеме определит, какой из ожидаемых типов выражений присутствует, если вообще левый - вернет ОШИБКУ.
Если ОК, то она на основании обнаруженного типа (например, color) определит его параметры (их типы и количество) - например "[", "]", "=", "список чисел" (пример не самый удачный, но некогда).
Тогда она вызовет саму себя несколько раз (по количеству параметров) с указанием позиции следующей лексемы, а также с указанием допустимых типов параметров.
...
Я это сообщение уже второй час правлю и запутался. Примеров решил таки не приводить. Либо как есть, либо весь день просидеть - и сделать программу. Но некогда, да и надо знать описание синтаксиса. Если со всякими циклами и условиями, то может и не один день.