我正在阅读F#规范-我可以找到的最新规范here-旨在以一种很难的方式来学习该语言。在“3.6符号关键字”部分中,规范指出:
以下符号或部分符号字符序列被视为关键字:
token symbolic-keyword =
let! use! do! yield! return!
| -> <- . : ( ) [ ] [< >] [| |] { }
' # :?> :? :> .. :: := ;; ; =
_ ? ?? (*) <@ @> <@@ @@>
在下一节“3.7符号运算符”中,它指出:
用户定义的和库定义的符号运算符是如下所示的字符序列,除非字符序列是符号关键字(第3.6节)。
regexp first-op-char = !%&*+-./<=>@^|~
regexp op-char = first-op-char | ?
token quote-op-left =
| <@ <@@
token quote-op-right =
| @> @@>
token symbolic-op =
| ?
| ?<-
| first-op-char op-char*
| quote-op-left
| quote-op-right
我可能会遗漏一些显而易见的东西,但是在我看来,该规范表明该运算符/关键字
?
,@>
,@@>
,<@
和<@@
都是符号关键字和符号运算符。所以...他们是哪一个?我如何知道使用符号关键字 token 或符号运算符 token 的天气?提前致谢,
布兰登
编辑要清楚,我想知道为什么规范在声明不能将符号运算符声明为这些符号后立即声明它们。
最佳答案
回答这个问题的概念是keyword。关键字是reserved word。还要检查你的龙书。
保留字基本上是程序员不能将其用作标识符的字,在这种情况下,诸如(如果为)之类的单词,或诸如-> 的运算符。换句话说,如果您尝试使用“let(,如果是)=”或“let(-> )=”,则将出现错误,因为您使用的是保留字。
对于此问题,将第3.6节解释为,这些是保留供F#使用的关键字。在第3.7节中,您可以创建自己的运算符,只要它们遵循这些规则并且与3.6节中的保留关键字之一不同即可。
因此,如果要创建运算符-> ,可以,但不能创建运算符->
回答您的问题“那么……他们是哪一个?”它们是关键字,它们是系统定义的运算符,不能用作用户定义的运算符。
编辑
让我们从另一个方向来解决这个问题。所有词法分析器规则都由解析器规则调用。可以很容易地找到符号操作规则(即操作名)的用法,但是寻找符号关键字,您会发现“例如34 ..被后过滤为两个标记:一个int和一个符号关键字,― ..”。”有用,但是它不能回答您的问题,现在您想知道为什么没有语法分析器规则调用的词法分析器规则。我不知道,这是规范,不是正式的语法定义。如果您查看F# source,您可能会发现规范和语法不符合您的要求。换句话说,该规范旨在帮助您理解该语言,我不会将其用作构建编译器的权威规则。
用规格或汽车来表示,这些规格告诉您对汽车的期望,汽车的功能或参数的限制,但并不能告诉您如何制造汽车。
如果我正在编写编译器,我将解释34 ..的情况,即不要在第一遍创建符号关键字的标记,而应使用后期处理将其过滤为适当的标记。换句话说,在第二遍重写 token 流。如果是我,我将在使用该规范构建编译器之前验证其规格是否完整。但是,如果您想按一下,那么我可能会在第一遍跳过查找符号关键字,而在第一遍创建 token 流之后使用流重写。
如果您想了解有关F#中的 token 过滤的更多信息,请参见规范的第15节“词法过滤”。它简要说明了如何通过重写 token 流将轻量语法转换为常规语法。