Smalltalk中消息与对象名称的区分及编译器识别逻辑问询
Smalltalk消息解析的核心规则
Smalltalk编译器靠固定的消息优先级、词法分类、语法约束来区分对象名和各类消息,根本不会混淆,核心逻辑如下:
第一步:词法分类
编译器先把输入拆成token,按类型标记:- 一元消息名:无冒号、字母开头的标识符(比如
factorial) - 二元消息名:1-2个非字母数字的符号(不含冒号,比如
+、==) - 关键字消息段:以冒号结尾的标识符(比如
between:、and:) - 对象/变量名:字母开头的标识符(仅在接收者位置、参数位置会被识别为对象)
- 一元消息名:无冒号、字母开头的标识符(比如
第二步:按优先级解析
Smalltalk消息优先级从高到低是:一元消息 > 二元消息 > 关键字消息,编译器严格按这个顺序绑定:- 一元消息:左结合,优先解析紧跟在接收者后的无参数消息。比如
name1 word1 word2会被解析为(name1 word1) word2——先让name1接收word1消息,结果再接收word2消息。 - 二元消息:左结合,优先级低于一元,必须紧跟参数(对象或表达式)。比如
name1 + word1 word2会先解析word1 word2为一元消息结果,再让name1和这个结果执行+二元消息。 - 关键字消息:优先级最低,所有连续的关键字段会被组合成完整的消息选择器,每个关键字后必须跟参数。比如
name1 word1: word2 word3: word4会被解析为name1 word1: word2 word3: word4,是一个带两个参数的关键字消息。
- 一元消息:左结合,优先解析紧跟在接收者后的无参数消息。比如
语法约束避免混淆
Smalltalk语法不允许“裸对象名紧跟另一个裸对象名”,比如name1 word1如果word1是对象名,这是语法错误(除非用句号分隔成两个独立表达式)。因此编译器明确知道:紧跟在接收者后的标识符,要么是一元消息,要么是二元/关键字消息的开头,不会被当成对象名。
举个对应你原始例子的解析过程:3 factorial + 4 factorial between: 10 and: 100
- 先解析两个一元消息:
3 factorial和4 factorial,得到两个数值对象 - 再解析二元消息
+:把两个数值相加,得到新的对象 - 最后解析关键字消息
between:and::让相加结果接收该消息,参数是10和100
回到你的泛化例子name1 word1 word2 word3 word4,编译器会根据token类型自动匹配:
- 如果
word1是一元消息、word2是二元消息、word3是一元消息、word4是关键字参数 → 解析为((name1 word1) word2 (word3)) between: word4 - 如果
word1和word3是关键字段、word2和word4是参数 → 解析为name1 word1: word2 word3: word4 - 如果所有word都是一元消息 → 解析为
(((name1 word1) word2) word3) word4
内容的提问来源于stack exchange,提问作者Vadim Goncharov
相关产品推荐
相关产品推荐

