Имеет ли Java неоднозначный синтаксис, который нуждается в дополнительной информации об идентификаторе? - PullRequest
0 голосов
/ 08 апреля 2019

ВНИМАНИЕ: Этот вопрос не о том, что «у Java нет указателей»

На языке C код identifier1 * identifier2 неоднозначен для двух возможных значений:

  1. Если идентификатор1 является типом, то это может быть объявление указателя.
  2. Если идентификатор1 является переменной, то это может быть оператор умножения.

проблема в том, что я не могу выбрать правильную продукцию при построении дерева синтаксиса.Я проверил код Clang, и кажется, что Clang должен поставить проверку типа (с помощью таблицы символов) на этап синтаксического анализа (исправьте меня, если я ошибаюсь).

Затем я проверил код javac (OpenJDK), кажется, что на этапе синтаксического анализа нет семантического анализа.Синтаксический анализатор может построить AST, используя только токены.

Так что мне интересно, есть ли у Java такая же неоднозначная проблема синтаксиса?Проблема в том, что если синтаксический анализатор не знает тип идентификатора, он не может выбрать правильную продукцию?

Или, что более универсально, имеет ли Java неоднозначный синтаксис, что парсер не может выбрать продукцию без другой информации?больше, чем поток токенов?

Ответы [ 4 ]

2 голосов
/ 08 апреля 2019

Токенизация всегда зависит от контекста для языков. Однако в Java нет таких чувствительных операторов. Однако вы можете связать токены таким образом, чтобы они вызывали двусмысленность, но не только как часть более крупного синтаксического утверждения:

A < B может быть частью обоих public class A < B > { ... } или if (A < B) { ... }. Первое - это общее определение класса, второе - сравнение.

Это только первый пример с моей шляпы, но я предполагаю, что есть и другие. Однако операторы обычно очень узко определены и не могут (как в C / C ++ -подобных языках) быть перегруженными. Кроме того, кроме C / C ++ есть только один оператор доступа (точка: .), с одним исключением (начиная с Java 8, двойное двоеточие ::). В C ++ есть куча, так что это гораздо менее хаотично.

На конкретный вопрос о том, всегда ли Java синтаксически разрешима: Да. Хорошо реализованный компилятор всегда может решить, какой токен присутствует, в зависимости от потока токенов.

0 голосов
/ 08 апреля 2019

Выражение, подобное foo.bar.bla.i, не может быть проанализировано осмысленным образом, используя только синтаксис.Каждый из foo, bar и bla может быть либо частью имени пакета, либо статической переменной (эта не относится к foo), либо именем внутреннего класса.

Пример:

public class Main {
    public static void main(String[] args) {
        System.out.println(foo.bar.bla.i);
    }
}

package foo;
public class bar {

    public static class bla {
        public static int i = 42;
    }

//  public static NotBla bla = new NotBla();
    public static class NotBla {
        public static int i = 21;
    }
}

Будет напечатано 21 или 42, когда статическая переменная bla закомментирована или нет.

0 голосов
/ 08 апреля 2019

На ваш вопрос нелегко ответить;это зависит от правил производства, которые у вас есть.Вы говорите:

there's two production:
<pointer> ::= * {<type-qualifier>}* {<pointer>}?
or
<multiplicative-expression> ::= <multiplicative-expression> * <cast-expression>

Но это не единственный возможный синтаксический анализатор!

С C при взгляде на

foo * bar;

, который может быть указателем с именем bar для ввода foo или умножение foo на bar может быть проанализировано для потока токенов:

identifier_or_type ASTERISK identifier_or_type SEMICOLON

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

0 голосов
/ 08 апреля 2019

Я не думаю, что у Java есть эта проблема, поскольку Java строго типизирована.Кроме того, Java не поддерживает указатели, поэтому нет шансов на вышеуказанную проблему.Я надеюсь, что это ответит на ваш вопрос.

...