
Sway 关键字完全指南保留字语义详解与编译器词法/语法层实现【免费下载链接】sway Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway本篇技术指南以 Sway 官方参考文档《Keywords》为骨架系统梳理 Sway 语言中全部保留字Reserved Keywords——包括当前已使用的关键字与为未来预留的关键字逐一说明其语法用途并结合本仓库sway 编译器源码深入剖析这些关键字从词法分析、语法解析到错误报告的实现机制帮助读者理解“为什么这些单词不能作为标识符”以及如何规避相关编译错误。一、什么是 Sway 关键字保留字Sway 语言保留了一批关键字供当前或未来使用。被保留意味着它们不能被用作标识符identifier。所谓标识符指的是函数、变量、参数、模块、常量、属性attribute、类型、trait 等一切需要命名的实体。例如下面的代码试图把let用作变量名、把fn用作函数名都会触发编译错误// 非法let / fn 是保留关键字不能作为标识符 let let 5; // 错误 fn fn() {} // 错误从编译器源码可以直观印证这一点Sway 的词法单元token定义集中在 sway-ast/src/keywords.rs其中通过define_keyword!宏为每个关键字生成独立的 token 类型例如define_keyword!(LetToken, let); define_keyword!(FnToken, fn); define_keyword!(AbiToken, abi); define_keyword!(ConfigurableToken, configurable);完整定义见 sway-ast/src/keywords.rs共包含script、contract、predicate、library、mod、pub、use、as、struct、enum、self、fn、trait、impl、for、abi、const、storage、str、asm、return、if、else、match、mut、let、while、where、ref、true、false、break、continue、configurable、type等关键字 token。二、当前正在使用的关键字以下按字母序列出 Sway 当前已投入使用的关键字及其功能说明。每个关键字附带语法用途简介部分关键字在本书其他章节有深入讲解可点击链接查阅。关键字功能说明深入阅读as在use语句中重命名导入项例如use type::type_name as alias_name;—abi以与 trait 语法相似的方式声明智能合约 ABI智能合约与 ABI 声明asm定义一个内联汇编块内联汇编break立即退出循环break 与 continueconfigurable定义可配置常量configurable constants—const定义常量常量continue跳到下一次循环迭代break 与 continuecontract声明 contract 程序类型智能合约else与if条件配合使用构成控制流分支—enum定义枚举枚举false布尔字面量false—for基于迭代器的循环for 循环fn定义函数函数if根据条件表达式的结果进行分支if 表达式impl实现固有方法或 trait 功能—let绑定一个变量—library声明 library 程序类型库match将值与模式进行穷尽式匹配match 表达式mod定义模块—mut表示可变性—pub表示公开可见性—predicate声明 predicate 程序类型谓词ref按引用绑定—return从函数中提前返回—script声明 script 程序类型脚本Self当前正在定义或实现的类型的类型别名—self方法调用目标—storage声明存储storage declaration存储str字符串切片类型—struct定义结构体结构体trait定义 trait声明 traittrue布尔字面量true—type定义类型别名或关联类型类型别名use将符号引入当前作用域—where为泛型类型参数指定 trait 约束—while根据条件表达式的求值结果循环while 循环分组详解程序类型关键字script/contract/predicate/librarySway 的每个源文件都以一个程序类型声明开头程序类型关键字决定该文件的角色contract; // 智能合约 script; // 脚本 predicate; // 谓词 library; // 库这四个关键字分别对应 Sway 的四种程序类型其详细说明见 docs/book/src/sway-program-types/ 目录下的 智能合约、脚本、谓词 与 库。在源码中它们被定义为独立的 token 类型sway-ast/src/keywords.rs由解析器在模块开头强制识别。abi与implabi用于以类似 trait 的语法声明智能合约的接口impl则用于实现固有方法或 trait以及 ABI。典型组合用法// 声明 ABI接口 abi Wallet { fn receive_funds(); fn send_funds(amount: u64, address: Address); } // 实现 ABI impl Wallet for Contract { fn receive_funds() { // ... } fn send_funds(amount: u64, address: Address) { // ... } }完整的 ABI 使用示例可参考仓库中的 examples/wallet_smart_contract/src/main.sw 与 examples/wallet_abi/src/main.swABI 声明的语法细节见智能合约文档。configurable与const常量体系const定义编译期常量configurable定义可配置常量configurable constants——一种在合约部署时可以通过参数覆盖的常量适用于部署方需要定制合约行为的场景。可配置常量块的真实示例见 examples/configurable_constants/src/main.swconfigurable { U8: u8 8u8, BOOL: bool true, ARRAY: [u32; 3] [253u32, 254u32, 255u32], STR_4: str[4] __to_str_array(fuel), STRUCT: StructWithGenericu8 StructWithGeneric { field_1: 8u8, field_2: 16, }, ENUM: EnumWithGenericbool EnumWithGeneric::VariantOne(true), }可以看到configurable块支持基本类型、数组、字符串、结构体与枚举等多种默认值形态并在合约内部像普通常量一样直接引用见 examples/configurable_constants/src/main.sw。if/else/match/for/while/break/continue控制流if/else基于条件表达式分支match对值进行穷尽式模式匹配Sway 会检查所有分支是否覆盖全部可能for基于迭代器循环while基于条件循环break立即退出循环continue跳过本次迭代进入下一轮。这些关键字的完整语义与代码示例见 控制流文档。struct/enum/type/trait类型系统struct定义结构体文档enum定义枚举文档trait定义 trait 接口文档type定义类型别名或关联类型文档。let/mut/ref/pub/mod/use/as声明与作用域let绑定变量默认不可变mut标记可变绑定例如let mut counter 0;ref按引用绑定例如let ref x some_value;pub将项函数、结构体、模块等暴露为公开可见mod声明模块use引入外部符号as为其重命名例如use type::type_name as alias_name;。fn/return函数定义与返回fn定义函数文档return用于从函数提前返回函数体的最后一个表达式不带分号也作为返回值。self与Self方法上下文self是方法调用目标接收者例如impl Foo { fn bar(self) {} }Self是当前正在定义或实现的类型本身的类型别名常用于impl块或 trait 默认实现中返回Self类型的场景。true/false布尔字面量true与false是布尔类型仅有的两个字面量它们同样是保留字不能被用作标识符。storage与strstorage声明合约的持久化存储块文档str表示字符串切片类型固定长度字符串类型为str[N]。三、为未来使用保留的关键字除上述已启用关键字外Sway 还预留了一批关键字供未来语法扩展使用。它们当前同样不可用作标识符即使某些关键字尚未实现任何实际语法功能abstract、async、await、become、box、do、dyn、extern、for、in、loop、macro、move、override、priv、static、super、try、typeof、unsafe、unsized、virtual、yield注意其中for同时出现在“当前使用”与“未来预留”两份列表中——原文档即如此列出读者应以“当前使用”中的实际语义为准。值得注意的是尽管in出现在“未来使用”列表中它其实已作为for循环的组成部分for x in iterable被编译器识别而class并未出现在文档列表中但源码为它定义了ClassToken注释明确说明它“不属于语言仅用于错误恢复”sway-ast/src/keywords.rs。这从侧面说明文档列表只反映面向用户的语言保留字编译器内部还维护着一份更宽泛的 token 集合。四、从源码看关键字如何被识别与强制理解关键字机制最直接的方式是阅读编译器的词法与语法实现它由三部分组成1. 词法层token 的生成与原始标识符在 sway-parse/src/token.rs 中词法分析器lexer将标识符字符序列XID_Start或_开头切分为标识符 token。特别地它支持**原始标识符raw identifier**语法r#foo// Raw identifier, e.g., r#foo? Then mark as such, stripping the prefix r#. let is_raw_ident character r matches!(l.stream.peek(), Some((_, #)));原始标识符允许开发者以r#前缀使用本应被保留的单词例如let r#type 1;。这一能力与 Rust 的r#原始标识符设计一致可用于对接外部系统如 JSON 字段名时避开关键字冲突。2. 语法层关键字集合与 peek/parsesway-parse/src/keywords.rs 维护了一份权威的保留关键字集合RESERVED_KEYWORDS使用phf::phf_set!构建的完美哈希集合并声明“必须与sway-ast/keywords.rs中define_keyword!定义的列表保持同步”。它同时为每个关键字 token 实现了Peek与Parsetraitfn peek_keywordT: Keyword(peeker: Peeker_) - OptionT { let ident peeker.peek_ident().ok()?; (!ident.is_raw_ident() ident.as_str() T::AS_STR).then(|| T::new(ident.span())) }注意这里的两个关键细节原始标识符豁免!ident.is_raw_ident()表明r#let、r#fn等原始标识符不会被当作关键字精确字符串匹配关键字判定基于 token 的字符串值与AS_STR常量逐一比对而不是字符集合判断。3. 错误报告层ReservedKeywordIdentifier在解析普通标识符Ident时sway-parse/src/parse.rs解析器会做双重检查if !ident.is_raw_ident() RESERVED_KEYWORDS.contains(ident_str) { return Err(parser.emit_error_with_span( ParseErrorKind::ReservedKeywordIdentifier, ident.span(), )); }一旦用户把保留字用作标识符编译器就会在对应 span 位置报告ReservedKeywordIdentifier错误错误类型定义于 sway-error/src/parser_error.rs。这也是文档中“它们不能用作标识符”这一规则在实现层面的落地不是约定而是编译期强制。五、实践中如何避免与利用关键字冲突1. 命名规范避开保留字定义变量、函数、类型、模块、常量、属性、trait 名称时应避免直接使用本文列出的任何保留字。Sway 采用snake_case命名函数与变量、PascalCase命名类型与 trait见风格指南正常遵循命名规范时很少会与全小写的关键字冲突。2. 必要时使用原始标识符当确实需要与关键字重名的符号例如处理外部数据结构的字段名时可使用原始标识符let r#type 42u64; // 合法r# 前缀使其不再是关键字词法与语法层的实现sway-parse/src/token.rs、sway-parse/src/keywords.rs都显式放行了r#形式。3. 区分大小写Self与selfSelf类型别名与self方法接收者大小写敏感且语义完全不同而true/false均为全小写——True或TRUE并不是关键字但这并不代表它们可以随意使用未定义的标识符会引发未找到符号的错误。同理Contract特殊类型与contract程序类型关键字是不同标识符。4. 编译器内部保留 token__ptr、__slice、panic除面向用户的关键字外编译器还保留了若干内部 token见 sway-ast/src/keywords.rs__ptr、__slice用于内建指针与切片类型panic用于不可恢复错误。此外check_double_underscore逻辑禁止使用无法识别为内建函数intrinsic的双下划线开头标识符sway-parse/src/parse.rs。普通用户代码应避免使用这些内部名称。六、总结Sway 的关键字体系可以归纳为三层认知用户视角34 个已启用的关键字覆盖程序类型script/contract/predicate/library、类型系统struct/enum/trait/type、控制流if/match/for/while等、声明体系let/mut/const/configurable/storage等全部核心语法维度另有 23 个为未来语法扩展预留的保留字编译器视角关键字由 sway-ast/src/keywords.rs 中的define_keyword!宏定义成独立 token 类型由 sway-parse/src/keywords.rs 的RESERVED_KEYWORDS集合统一裁决机制视角任何非原始标识符一旦命中保留字集合解析器即抛出ReservedKeywordIdentifier错误只有r#前缀能绕过该限制。掌握这份关键字清单与背后的实现机制既能避免最常见的“标识符冲突”编译错误也能加深对 Sway 语法设计ABI、可配置常量、程序类型等的理解为编写可靠的智能合约打下基础。需要进一步查阅各关键字的详细语法时可依次阅读控制流、智能合约、存储与高级类型等章节。【免费下载链接】sway Empowering everyone to build reliable and efficient smart contracts.项目地址: https://gitcode.com/GitHub_Trending/sw/sway创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考