我正在阅读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
我可能会遗漏一些明显的东西,但在我看来,规范说明运营商/关键字?
,@>
,@@>
,<@
和<@@
是符号关键字和符号运算符。那么......他们是哪一个?我如何知道天气使用符号关键字标记或符号操作符令牌?
提前致谢, 布兰登
编辑为了清楚起见,我想知道为什么规范说明符号运算符在声明它们不能出现后立即成为这些符号。
答案 0 :(得分:3)
有助于回答这个问题的概念是keyword。关键字是reserved word。还要查看你的龙书。
保留字基本上是程序员不能用作标识符的单词,在这种情况下是 if 之类的单词,或 - &gt;等运算符。换句话说,如果您尝试使用“let( if )=”或“let( - &gt; )=”,您将因为使用保留而出错字。
对于这个问题,将第3.6节解释为,这些是保留供F#使用的关键字。在第3.7节中,您可以创建自己的运算符,只要它们遵循这些规则并且与第3.6节中的一个保留关键字不同。
因此,如果您想创建运营商 - &gt; ,您可以,但无法创建运营商 - &gt;
回答你的问题“那么......他们是哪一个?”它们是关键字,它们是由系统定义的运算符,不能用作用户定义的运算符。
修改
让我们从不同的方向来看待这个问题。所有词法分析器规则都由解析器规则调用。很容易找到符号操作规则的使用,即操作名称,但查找符号关键字,你会发现“如34 ..后过滤到两个标记:一个int和一个符号关键字, - ..‖“。有帮助,但它没有回答你的问题,现在你想知道为什么解析器规则没有调用lexer规则。我不知道,这是一个规范,而不是一个正式的语法定义。如果您查看F# source,您可能会发现规格和语法不符合您的要求。换句话说,规范旨在帮助您理解语言,我不会将其用作构建编译器的权威规则集。
根据条款或汽车的规格,规格告诉你汽车可以期待什么,汽车应该如何运作,或参数的限制,它不告诉你如何建造汽车。
如果我正在编写编译器,我会解释34 ..的情况,意思是,不要在第一次传递时为符号关键字创建标记,而是使用后期处理将它们过滤到适当的标记中。换句话说,在第二遍中重写令牌流。如果是我,我会在使用它构建编译器之前验证规范是完整的语法。如果你想要按下,那么我可能会在第一次传递时跳过寻找符号关键字,并在第一次传递时创建令牌流后使用流重写。
如果您想了解有关F#中令牌过滤的更多信息,请参阅规范第15节“Lexical Filtering”;它通过重写令牌流给出了如何将轻型语法转换为常规语法的下降解释。