在ocamlmenhir中,如何为C++/Rust/Java风格的泛型 在C++中,一个著名的解析模糊现象发生在类似的代码中。 x<T> a; xa;
如果在ocamlmenhir中,如何为C++/Rust/Java风格的泛型 在C++中,一个著名的解析模糊现象发生在类似的代码中。 x<T> a; xa;,ocaml,menhir,Ocaml,Menhir,如果T是一个类型,它就是它的样子(类型x的变量a的声明,否则它就是(xa(是比较运算符,而不是尖括号) 事实上,我们可以做一个改变,使其变得明确:我们可以使 AFAIK C++的模板语法是真实世界非LR语法的一个著名例子。严格来说,它不是任何有限k的LR(k)。所以C++分析器通常是用HACK(如CLAN)手写的,或者由GLR语法(LR分支)生成。理论上,在Menhir中实现一个完整的C++解析器是不可能的,即LALR. 但是泛型的语法也可以是不同的。如果泛型类型和包含比较运算符的表达式在同一上
T
是一个类型,它就是它的样子(类型x
的变量a
的声明,否则它就是(xa
(
是比较运算符,而不是尖括号)
事实上,我们可以做一个改变,使其变得明确:我们可以使非关联。因此
,没有括号,即使x
a ,x
和T
都是变量名,也不会是一个有效的句子a
如何在Menhir中解决这一冲突?乍一看,我们似乎无法解决。即使进行了上述修改,在看到另一个结束之前,我们需要先查看不确定数量的标记,然后才能得出结论,这是一个模板实例化,或者以其他方式得出结论,这是一个表达式。是否存在在Menhir中,实现这种任意的前瞻性是什么? < P> AFAIK C++的模板语法是真实世界非LR语法的一个著名例子。严格来说,它不是任何有限k的LR(k)。所以C++分析器通常是用HACK(如CLAN)手写的,或者由GLR语法(LR分支)生成。理论上,在Menhir中实现一个完整的C++解析器是不可能的,即LALR.但是泛型的语法也可以是不同的。如果泛型类型和包含比较运算符的表达式在同一上下文中不会出现,则语法可能仍然是LR兼容的。例如,考虑变量声明的Rice语法(仅针对这一部分):
让x:Vec=。。。
标记表示后面是类型,而不是表达式,因此在本例中,语法可以是LR,甚至是LL(未验证):
<> P> >最后,我们的答案是,这取决于。但是对于C++的情况,在MHIHIR中不可能实现语法。<> P> AFAIK C++的模板语法是真实世界非LR语法的一个著名例子。严格来说,对于任何有限的K,它不是LR(k)。所以C++分析器通常是用HACK(如CLAN)手写的。或者由GLR文法生成(分支),所以在Menhir中不可能实现完整的C++分析器,即LALR.但是泛型的语法也可以是不同的。如果泛型类型和包含比较运算符的表达式在同一上下文中不会出现,则语法可能仍然是LR兼容的。例如,考虑变量声明的Rice语法(仅针对这一部分):
让x:Vec=。。。
标记表示后面是类型,而不是表达式,因此在本例中,语法可以是LR,甚至是LL(未验证) <> P> >最后的答案是,这取决于。但是对于C++的情况,在MHIHIR中不可能实现语法。< P>不同的语言(包括在你的标题中列出的)实际上有不同的模板/泛型规则。(比如可以有什么类型的参数,模板/泛型可以出现在哪里,何时允许它们有一个显式的参数列表,以及泛型方法上模板/类型参数的语法是什么),这会强烈影响解析选项。在我所知的任何语言中,:
的含义都取决于xa;
是否为类型 <> P>让我们通过C++语言、java语言、Rust语言和C语言: 在这四种语言中,类型和函数/方法都可以是模板/泛型的。因此,我们不仅要担心变量声明的模糊性,还要担心函数/方法调用:isT
带有显式模板/类型参数的函数/方法调用,还是带有最后一个操作数括号的两个关系运算符?在所有四种语言中,如果可以推断模板/泛型函数/方法,则可以在没有模板/类型的情况下调用这些函数/方法,但这种推断并不总是可能的,所以只需禁止显式模板/类型a即可函数/方法调用的参数不是选项 即使一种语言不允许将关系运算符链接起来,我们也可能会在表达式中出现歧义:f(x)
。这是使用三个参数f(a(e))
调用ae
还是使用单个参数f
使用类型/模板参数调用名为a(e)
的函数/方法a
b、c、d
现在除了这个共同的基础,大多数其他语言在这些语言之间是不同的:
生锈 在Rust中,变量声明的语法是,因此let variableName:type=expr;
不可能是变量声明,因为它与语法完全不匹配。此外,它也不是有效的表达式语句(不再),因为比较运算符无法链接(不再) 因此这里没有歧义,甚至没有解析困难。但是函数调用呢?对于函数调用,Rust通过简单地选择不同的语法来提供类型参数来避免歧义:而不是x a;
语法是f(x)
。由于函数调用的类型参数在可以推断的情况下是可选的,所以谢天谢地,这种丑陋的情况并不经常出现 总之:f::(x)
是一个变量声明,让a:x=…;
用三个参数调用f(a(e));
,用三个类型参数调用f
调用f(a:(e));
。解析很容易,因为所有这些都非常不同,只需一个先行标记即可区分 JAVA 在Javaa
实际上是一个有效的变量声明,但它不是一个有效的表达式语句x中;