Здравствуйте, VladD2, Вы писали:
V>>LR-разбор в состоянии подсказать множество верных ожидаемых символов. В реальности там выбор из 1-2-х вариантов максимум, потому что в С++ неоднозначность происходит в выборе м/у идентификатором типа или переменой, вот и вся неоднозначность, которой "болеет" С++.
VD>ЛР падает на свертках. И эти почти наверняка не места реальных ошибок. В тоже время ЛЛ падет на входе в правило и это почти наверняка реальное место ошибки.
Свертки в LR происходят только по входному символу.
Например, пришел входной символ (предположим, у нас scannerless), предположим, символ 'a', подали этот терминал "наверх", наверху выяснили, что допустимого шифта нет (продвижения по последовательности нетерминалов/терминалов в правиле), есть только шифт по открывающей фигурной скобке или по точке с запятой. Так и говорим: "ожидалось '{' или ';'".
VD>Ты почитай какими извращениями занимаются те кто восстановление для GLR-ов пишут. Это жесть!
Пока что ваши извращения вокруг восстановления кажутся более серьёзными.
И да, это демагогия, бо "восстановление" — это редкая задача, вот как раз для интиллисенса.
А компилятор ЯП может тупо отрапортовать об ошибке в этом файле и отвалиться.
VD>Какие типы в ЛР-парсере?
Простые. Свертка идёт снизу, мы можем доопределить "просто идентификатор" до "идентификатора типа" или "идентификатора терма".
VD>Пипец ты жжешь! Вот в ЛЛ можно тупо таблицу имен протащить и действительно во время парсинга резолвнуть имя узнав является ли оно типом (если речь о С++). А как это сделать в ЛР, который обломался на свертке некого правила?
Облом происходит всегда на шифте, а не на свертке.
Просто да, ввиду того, что работа парсера событийная, облом на шифте сверху происходит по свертке снизу.
И вообще, сосредоточься, а то уже неинтересно. ))
Там ничего сложного, я не понимаю причин твоего психа.
Представь себе, что у тебя парснг происходит не по схеме pull, а по схеме push.
Помнишь, чем sax-парсинг XML отличается от DOM-парсинга?
Вот так же и в восходящем парсинге.
Представь, что это не ты вызываешь лексер, а лексер тебя вызывает, когда у него готова очередная лексема для её обработки (передает лексему наверх).
В этом смысле LR-разбор вызывает сам себя, когда у него готов очередной нетерминал.
V>>Если id3 — это значение (переменная/константа/перечисление), то id2 — это идентификатор переменной, а всё выражение означает объявление переменной типа id1 и вызов соотв. конструктора этого типа. А если id3 — это имя типа, то всё выражение означает объявление сигнатуры некоей ф-ии id2.
VD>Какая чушь?! Никто не типизирует выражения С++ во время парсинга. Только лукапят имена по таблице имен.
Лукап имён в С++ происходит по непростому алгоритму, описанному в стандарте.
VD>И тип выражения определяется по тому является ли id1 типом. Хотя здесь выражение и так объявление переменной.
Объявляется или переменная или ф-ия.
VD>Вот в случае id1* id2(id3) действительно было бы не ясно.
И тут точно так же надо знать, какой идентификатор является идентификатором типа, а какой нет.
V>>С другой стороны, подобную неоднозначность НЕ обязательно сваливать на парсер и её не сваливают — для такой конструкции заводится отдельный "недоопределённый" нетерминал и его ресолвят до однозначного через таблицу идентификаторов ручками. Т.е. на скорости работы именно парсера по алгоритму *LR это не сказывается (если убрать ресолвинг). Это конкретные заморочки конкретно С++, которые верны для ЛЮБОГО алгоритма парсинга.
VD>Причем тут скорость?
Речь изначально была про скорость парсинга.