Java是否有需要更多标识符信息的不明确语法?

Java是否有需要更多标识符信息的不明确语法?,java,parsing,semantics,symbol-table,Java,Parsing,Semantics,Symbol Table,注意:这个问题不是关于“Java没有指针” 在C语言中,代码identifier1*identifier2具有两种可能的含义: 如果identifier1是一个类型,那么这可能是一个指针声明 如果identifier1是一个变量,那么这可能是一个乘法语句 问题是,在构建语法树时,我无法选择正确的产品。我检查了Clang的代码,似乎Clang必须将类型检查(通过使用符号表)放到解析阶段(如果我错了,请纠正我) 然后我检查了javac(OpenJDK)的代码,似乎在解析阶段,没有涉及语义分析。解析器

注意:这个问题不是关于“Java没有指针”

在C语言中,代码
identifier1*identifier2
具有两种可能的含义:

  • 如果identifier1是一个类型,那么这可能是一个指针声明
  • 如果identifier1是一个变量,那么这可能是一个乘法语句
  • 问题是,在构建语法树时,我无法选择正确的产品。我检查了Clang的代码,似乎Clang必须将类型检查(通过使用符号表)放到解析阶段(如果我错了,请纠正我)

    然后我检查了javac(OpenJDK)的代码,似乎在解析阶段,没有涉及语义分析。解析器可以使用标记构建AST

    所以我很好奇Java是否也有同样的歧义语法问题?问题是,如果解析器不知道标识符的类型,它就不能选择正确的产品


    或者更一般地说,Java的语法是否不明确,以至于解析器在没有令牌流以外的其他信息的情况下无法选择产品?

    我认为Java没有这个问题,因为Java是强类型的。 而且,Java不支持指针,因此不可能出现上述问题。
    我希望这能回答你的问题。

    我认为Java没有这个问题,因为Java是强类型的。 而且,Java不支持指针,因此不可能出现上述问题。
    我希望这能回答您的问题。

    对于语言而言,标记化始终是上下文敏感的。但是,Java没有这样敏感的运算符。但是,您可以以这样的方式链接标记,使其产生歧义,但不仅仅是作为更大语法语句的一部分:

    A
    可以是
    公共类A{…}
    的一部分,如果(A
    。 第一个是泛型类定义,第二个是比较

    这只是我的第一个例子,但我想还有更多。 然而,操作符的定义通常非常狭窄,并且不能重载(就像在C/C++语言中一样)。此外,除了C/C++之外,只有一个访问器操作符(点:
    ),只有一个例外(自Java8以来,双冒号
    )。 在C++中有一堆,所以它就不那么混乱了。 关于Java是否总是语法上可判定的特定问题:
    对一个实现良好的编译器总是可以根据令牌流来决定存在什么令牌。

    对于语言来说,令牌化始终是上下文敏感的。但是,Java没有这样敏感的运算符。但是,您可以以这样的方式链接标记,使其产生歧义,但不仅仅是作为更大语法语句的一部分:

    A
    可以是
    公共类A{…}
    的一部分,如果(A
    。 第一个是泛型类定义,第二个是比较

    这只是我的第一个例子,但我想还有更多。 然而,操作符的定义通常非常狭窄,并且不能重载(就像在C/C++语言中一样)。此外,除了C/C++之外,只有一个访问器操作符(点:
    ),只有一个例外(自Java8以来,双冒号
    )。 在C++中有一堆,所以它就不那么混乱了。 关于Java是否总是语法上可判定的特定问题:
    对一个实现良好的编译器总是可以根据令牌流决定存在什么令牌。

    您的问题不容易回答;这取决于您拥有的生产规则。你说:

    there's two production:
    <pointer> ::= * {<type-qualifier>}* {<pointer>}?
    or
    <multiplicative-expression> ::= <multiplicative-expression> * <cast-expression>
    
    它可以是一个名为
    bar
    的指针,用于键入
    foo
    ,或者
    foo
    bar
    的乘法可以解析为令牌流:

    identifier_or_type ASTERISK identifier_or_type SEMICOLON
    

    其余部分由解析器“业务逻辑”决定。因此,在解析器级别根本没有歧义,规则背后的逻辑决定了这两种情况的不同。

    您的问题不容易回答;这取决于您拥有的生产规则。你说:

    there's two production:
    <pointer> ::= * {<type-qualifier>}* {<pointer>}?
    or
    <multiplicative-expression> ::= <multiplicative-expression> * <cast-expression>
    
    它可以是一个名为
    bar
    的指针,用于键入
    foo
    ,或者
    foo
    bar
    的乘法可以解析为令牌流:

    identifier_or_type ASTERISK identifier_or_type SEMICOLON
    

    其余部分由解析器“业务逻辑”决定。因此,在解析器级别根本没有歧义,规则背后的逻辑决定了这两种情况的不同。

    foo.bar.bla.i
    这样的表达式不能单独使用语法进行有意义的解析。
    foo
    bar
    bla
    中的每一个都可以是包名称的一部分、静态变量(此变量不适用于
    foo
    )或内部类的名称

    例如:

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


    当静态变量
    bla
    被注释掉或没有注释掉时,这将打印
    21
    42

    foo.bar.bla.i
    这样的表达式不能单独使用语法进行有意义的解析。
    foo
    bar
    bla
    中的每一个都可以是包名称的一部分、静态变量(此变量不适用于
    foo
    )或内部类的名称

    例如:

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


    当静态变量
    bla
    被注释掉或没有注释掉时,这将打印
    21
    42

    我不太理解这个问题:java没有指针,所以这里不会有歧义,因为
    *
    总是乘法。我不认为so@SanderDeDycker我认为OP是泛泛而谈,而不仅仅是关于
    *
    。换句话说,在解析源代码时,是否有任何符号会导致歧义,而这些符号只能通过了解上下文中使用的类型来解决。有些运算符重载,可能会很简短