Java是否具有模糊的语法,需要有关标识符的更多信息?

问题描述 投票:0回答:4

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

在C语言中,代码identifier1 * identifier2对于两个可能的含义是不明确的:

  1. 如果identifier1是一个类型,那么这可能是一个指针声明。
  2. 如果identifier1是变量,那么这可能是乘法语句。

问题是我在构建语法树时无法选择正确的产品。我检查了Clang的代码,似乎Clang必须将类型检查(通过使用符号表)放到解析阶段(如果我错了,请纠正我)。

然后我检查了javac(OpenJDK)的代码,似乎在解析阶段,没有涉及语义分析。解析器几乎不能使用令牌构建AST。

所以我很好奇Java是否有相同的模糊语法问题?如果解析器不知道标识符的类型,它不能选择正确的生产?

或者更通用,Java是否具有语法模糊,以至于解析器无法选择没有其他信息而非令牌流的生产?

java parsing semantics symbol-table
4个回答
2
投票

对于语言,标记化总是对上下文敏感。但是,Java没有这种敏感的运算符。但是,您可以以这种方式链接令牌,它会产生歧义,但不仅仅是作为更大的语法陈述的一部分:

A < B可以是public class A < B > { ... }if (A < B) { ... }的一部分。第一个是泛型​​类定义,第二个是比较。

这只是我头顶的第一个例子,但我认为还有更多。但是,运算符的定义通常非常狭窄,而且不能(如在C / C ++中那样的语言)重载。此外,除了在C / C ++中,只有一个访问器 - 运算符(点:.),有一个例外(自Java 8以来,双冒号::)。在C ++中有一堆,所以它不那么混乱。

关于Java是否总是在语法上可判定的具体问题:是的。一个良好实现的编译器总是可以决定存在哪个令牌,具体取决于令牌流。


0
投票

我不认为Java有这个问题,因为Java是强类型的。此外,Java不支持指针,因此不存在上述问题。我希望这能回答你的问题。


0
投票

foo.bar.bla.i这样的表达式不能仅使用语法以有意义的方式解析。 foobarbla中的每一个都可以是包名称的一部分,一个静态变量(这个不适用于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被注释掉时,这将打印42bla


-1
投票

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

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

但这不是唯一可能的解析器!

用C看着

foo * bar;

这可能是一个名为bar的指针,用于输入foo,或者foobar的乘法可以解析为令牌流:

identifier_or_type ASTERISK identifier_or_type SEMICOLON

其余的由解析器“业务逻辑”决定。因此,解析器级别根本没有歧义,规则背后的逻辑使得两种情况之间存在差异。

© www.soinside.com 2019 - 2024. All rights reserved.