Что делает Java проще для анализа, чем C?



Я знаком с тем, что грамматики C и C++ являются контекстно-зависимая, и в частности вам нужен "lexer hack" в C. С другой стороны, у меня сложилось впечатление, что вы можете анализировать Java только с помощью 2 токенов look-ahead, несмотря на значительное сходство между двумя языками.



что вам нужно изменить в C, чтобы сделать его более сговорчивым для разбора?



Я спрашиваю, потому что все примеры, которые я видел Контекстная чувствительность C технически допустима, но ужасно странная. Например,



foo (a);


может вызывать функцию void foo С аргументом a. Или, это может быть объявление a быть объектом типа foo, но вы могли бы так же легко избавиться от парантезов. Отчасти эта странность возникает из-за производственного правила" прямого Декларатора " для C грамматика выполняет двойную цель объявлять обе функции и переменная.



С другой стороны,грамматика Java имеет отдельные производственные правила для объявления переменных и объявления функций. Если вы пишете



foo a;


тогда вы знаете, что это объявление переменной и foo можно однозначно разобрать как имя типа. Это может быть недопустимый код, если класс foo не был определен где-то в текущей области, но это задание для семантического анализа, которое может быть выполнено в более позднем компиляторе пройти.



Я видел, что C трудно разобрать из-за typedef, но вы также можете объявить свои собственные типы в Java. Какие правила грамматики C, кроме direct_declarator в этом не виноваты?

544   1  

1 ответ:

разбор C++ становится все труднее. Разбор Java становится таким же сложным.

посмотреть этот Итак, ответьте, почему C (и C++) "трудно" разобрать. Краткое резюме заключается в том, что C и C++ грамматик по своей сути неоднозначны; они дадут вам несколько парсов, и вы должны используйте контекст для устранения двусмысленностей. Затем люди делают ошибку, предполагая, что вам нужно разрешить двусмысленности при анализе; не так, см. ниже. Если вы настаиваете на разрешении двусмысленностей при анализе, ваш синтаксический анализатор становится более сложным, и это намного сложнее построить; но эта сложность-это нанесенная самому себе рана.

IIRC, "очевидная" грамматика Lalr(1) Java 1.4 не была двусмысленной, поэтому ее было "легко" разобрать. Я не уверен, что современная Java не имеет по крайней мере междугородних локальных двусмысленностей; всегда есть проблема принятия решения "...> > "закрывает два шаблона или является "оператором сдвига вправо". Я подозреваю современный Java больше не анализирует LALR(1).

но можно пройти мимо проблемы синтаксического анализа, используя сильные Парсеры (или слабые Парсеры и хаки контекстной коллекции, как это обычно делают интерфейсы C и C++) для обоих языков. C и C++ имеют дополнительную сложность наличия препроцессора; они более сложны на практике, чем они выглядят. Одно из утверждений заключается в том, что синтаксические анализаторы C и C++ настолько сложны, что их нужно писать вручную. это не так; вы можете построить Java и C++ анализаторы очень хорошо с генераторами синтаксических анализаторов ГЛР.

но разбор на самом деле не там, где проблема.

Как только вы проанализируете, вы захотите что-то сделать с деревом AST/parse. На практике для каждого идентификатора необходимо знать, каково его определение и где оно используется ("разрешение имени и типа", небрежно, построение таблиц символов). Это оказывается намного больше работы, чем получение правильного парсера, усугубленного наследованием, интерфейсы, перегрузки и шаблоны, а также смущает тот факт, что семантика для всего этого написана на неформальном естественном языке, разбросанном по десяткам-сотням страниц языкового стандарта. C++ - это действительно плохо. Java 7 и 8, становится ужасно с этой точки зрения. (И таблицы символов-это не все, что вам нужно; см. мою биографию для более длинного эссе "жизнь после разбора").

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

исправление синтаксиса C++ никуда не приведет.

Что касается изменения синтаксиса C++: вы обнаружите, что вам нужно исправить много мест, чтобы позаботиться о разнообразии локальных и реальных двусмысленностей в любой грамматике C++. Если вы настаиваете, то следующий список может быть хорошим местом для начала. Я утверждаю, что нет смысла делать это, если вы не являетесь комитетом по стандартам C++; если бы вы это сделали и построили компилятор, используя его, никто в здравом уме не использовал бы его. Слишком много вложено в существующие приложения на C++, чтобы переключаться для удобства парней, создающих Парсеры; кроме того, их боль закончилась, и существующие Парсеры работают нормально.

вы можете написать свой собственный парсер. Хорошо, это нормально; просто не ожидайте, что остальная часть сообщества позволит вам изменить язык, который они должны использовать, чтобы сделать его проще для вас. Они все хотят, чтобы им было легче, и это использовать язык, как документированный и реализованный.

Comments

    Ничего не найдено.