XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Общение> Трактир
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Ответ
 
J64_

offline
Опыт: 4,724
Активность:
Унарные операторы
Делая свой компилятор, я упоролся в отличии унарных от бинарных операторов: например, как отличить оператор ++a от ++a?
У меня в качестве базы данных есть map[тип1][строка][тип2]. Загвоздка в том, что я не знаю идущий за именем оператора тип (тип2).
То есть, допустим, у нас есть входное выражение: <a + b>.
  1. Читаем a, находим его тип, храним в стеке.
  2. Читаем +, и тут мы не знаем что делать, ведь если просто хранить в стеке, а потом загрузить, порядок при помощи приоритетов операторов нарушиться.
Конечно же можно извратиться путем просмотра следующего слова: идентификатор ли, вызов функции ли, константа ли или же открывающая скобка, но так синтаксис будет немного неудобен. Например нельзя будет вводит выражения типа <a + *(&b)>, а будет <a + (*(&(b)))>.
Наверное, ADOLF знаком с этим. Попрошу его ответить.
Пытался читать в википедии\книжке, искал в гугле, не понял - там не разжевано.

Отредактировано ScorpioT1000, 22.07.2012 в 04:55.
Старый 21.07.2012, 22:19
alexprey
познающий Unity
offline
Опыт: 68,501
Активность:
Judycaster64, делай не стек, а бинарное дерево для вычисления и т.д. По крайней мере я так делал у себя в интерпретаторе.
Старый 22.07.2012, 01:40
ScorpioT1000
Работаем
online
Опыт: отключен
Вы конченные, какой язык, ну да мб это было бы флудом при разработке межгалактического аннигилятора, но написат ьсвой язык намного сложнее, так вот мой вопрос, какого хрена свой язык, в понимаете, что творите ?
ScorpioT1000 добавил:
ну в целом идет a + b * c
читаем токены
\n
a
+
b
*
c
\n
читаем экспрешоны
a
b
c
операторы
op0 exp0 + exp1
op1 exp1 * exp2
приоритет 2
выполняем op1
выполняем op2 над временным результатом op1
?
здесь проще говна, даже школьник решит, это я к тому, что забейте писать свой язык
Старый 22.07.2012, 05:00
J64_

offline
Опыт: 4,724
Активность:
alexprey:
Возможно ты меня не понял или я тебя.
Если ты имеешь в виду это:
Вход: "2 + 2 + 2 * 5"
...
a = 2;
b = 5;
op = *;
node = new node (a, b, op);
a = node;
b = 2;
op = "+";
node = new node(a, b, op);
a = node;
b = 2;
op = "+";
node = new node(a, b, op);
...
То да, я это делал. Суть не в этом.
Короче, я не знаю сам приоритет оператора. Как я уже писал, он(сама целевая ссылка на экземпляр класса Type, который содержит приоритет, и прочую другую информацию) храниться в трехмерном map'е(map<Type*, map<string, map<Type*, Operator*>>> operatorMap, а это для того чтобы можно было добавлять свои операторы на ходу) нулевой индекс у нас известен - выталкиваем\берём из стека, первый это имя оператора, а вот что подать в качестве второго индекса?
ScorpioT1000
Почему ты всем говоришь что не надо делать то или иное? Что тогда нам делать? Карты создавать?
Я тебя понял так: сначала читаем всё, и только потом сравниваем приоритеты.
И да, я делаю язык максимально похожий на С++. И вообще, у меня Напалеоновские планы. А всё для того чтобы сделать мапу для вк3. лол :3
Старый 22.07.2012, 07:36
alexprey
познающий Unity
offline
Опыт: 68,501
Активность:
Judycaster64:
Я тебя понял так: сначала читаем всё, и только потом сравниваем приоритеты.
А по другому и не сделаешь. Хотя у меня просто дерево строиться по приоритетам. То есть если приоритет такой же или ниже текущего нода, то вставляется в левое или в правое поддерево. Если приоритет выше текущего, то создается новый нод и к нему в левое поддерево вставляется текущий нод.
Judycaster64:
я не знаю сам приоритет оператора
Когда ты вручную строишь, ты же знаешь по каким приоритетам надо строить. Так вот и научи свой "компилятор" это сделать
Judycaster64:
И да, я делаю язык максимально похожий на С++. И вообще, у меня Напалеоновские планы. А всё для того чтобы сделать мапу для вк3. лол :3
лол. Есть cJass, для мап вк3
Старый 22.07.2012, 11:21
J64_

offline
Опыт: 4,724
Активность:
alexprey:
Не знаю... короче, совсем запутался.
То есть если приоритет такой же...
Ты говоришь что нашёл приоритет, но не говоришь как.
Ведь как ты говоришь у тебя там одноименных операторов нету, то есть у тебя приоритеты хранятся в чем-то вроде мэпа, в которой, строка(имя), выступает как индекс. Или как?
лол. Есть cJass, для мап вк3
спасибо за уведомление.
Старый 22.07.2012, 12:10
alexprey
познающий Unity
offline
Опыт: 68,501
Активность:
Judycaster64, приоритеты записаны для каждого типа оператора
Старый 22.07.2012, 14:51
J64_

offline
Опыт: 4,724
Активность:
alexprey:
Да, записаны. Но как узнать?
Старый 22.07.2012, 15:19
alexprey
познающий Unity
offline
Опыт: 68,501
Активность:
Judycaster64, ну так достать, где записаны. Ах да, у тебя унарные операторы. Ну вот смотри.
допустим построили дерево
       R
     / 
    +
 /      \
1         -
       /      \
<empty>   2
Для выражения
1 + -2
Фактически унарные операторы имеют более высокий приоритет, чем бинарные. Как узнать что оператор именно унарный. Так просто. Во время построения дерева по токенам, у унарного оператора отсутствует левый операнд (левая часть поддерева). Ну вообще я руководствовался вроде такому принципу:
  1. Новый токен вставляется в левое поддерево текущего родителя, если его еще нет, иначе в правое
  2. Если токен является оператором, то помещаем, его на верх (текущее дерево записывается в левое поддерево)
  3. Если токен оператор и текущий токен является оператором, то у нас получается унарный оператор, отмечаем что для этого токена, как бы есть левый операнд, и следующий токен уже будет писаться в правый операнд.
Ну как то так
Старый 22.07.2012, 16:12
Romeno

offline
Опыт: 3,167
Активность:
Я как то ковырялся с lex-ом и yacc-ом... для питона: PLY. Насколько я помню там проблема "двоякости" восприятия была решена. В документации, в главе 5. Parsing basics приведён пример того как ведёт себя парсер. Для такого обхода дерева даже есть какое то название, только не помню какое...
По-мойму в таких случаях лучше сконцентрироваться на написании правил к языку, поэтому, возможно, хотя бы для того чтобы быстрее получить первоначальный результат имеет смысл обратить внимание на сторонние лексические/семантические анализаторы типа лекса, яка и др...
Ещё есть хорошая книжка, сам я её только немножко прочитал, но рекомендуется как must-have. Книга дракона
Может это поможет...
Старый 23.07.2012, 03:22
ScorpioT1000
Работаем
online
Опыт: отключен
Когда я писал свой парсер, он сначала бил на лексемы (т.е. разбивка на такие куски по пробельным символам, которые могут быть int,float,string итд итп). Потом лексемы превращались в экспрешшоны, например три лексемы
"
123\"abc
"
превращались в экспрешшон-константу строку
string|123"abc
или вот пример
1
.
8
+
e
24
F
понимала, что это
float|1.8+E24F
запись числа с плав. точкой, а не 1.8 плюс e20f, и таких мелочей овер 9000
дальше уже парсилось на блоки по { и }, ходило назад-вперед, составляло базу данных потихоньку, ну и в итоге был десериализованный код =)
ScorpioT1000 добавил:
офк у всех операторов должны быть приоритеты, причем операторы могут быть перегружены и тогда он от контекста (обычно типов) должен смотреть, что делать
ScorpioT1000 добавил:
т.е. что я хотел сказать что разные вещи решаются на разном уровне, сначала должен быть подход к кодировке и служебным символам, распознание чисел, бинарных строк ака "\24\28\r\n", систем счисления и неопределённостей на уровне лексера, только потом перейти к экспрешшенам

Отредактировано ScorpioT1000, 23.07.2012 в 14:20.
Старый 23.07.2012, 09:25
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 02:30.