查看源码 erl_syntax_lib (语法工具 v3.2.1)
抽象 Erlang 语法树的支持库。
此模块包含用于处理模块 erl_syntax
中定义的抽象数据类型的实用工具函数。
概要
类型
抽象语法树。有关详细信息,请参阅 erl_syntax
模块。
函数
返回被调用函数的名称。
分析属性节点。
返回 export 属性声明的函数名称列表。
返回 file
属性的文件名和行号。
分析“源代码形式”节点。
分析一系列“程序形式”。
返回函数定义的名称和元数。
返回语法树表示的函数名称。
返回隐式 fun 表达式“fun F
”的名称。
返回模块名称和(如果存在)import 属性声明的函数名称列表。
返回模块名称和模块属性声明的可能参数。
返回记录声明属性的名称和字段列表。
返回记录表达式的记录名称和字段名称/名称。
返回记录字段说明符的标签、值表达式和类型。
返回使用的类型的名称。
返回语法树表示的类型名称。
返回“wild”属性的名称和值。
在语法树中的节点上添加或更新注解。
在语法树中的节点上添加或更新注解。
将函数折叠到语法树的所有节点上。
将函数折叠到语法树的直接子树上。
类似于 lists:foldl/3
,但适用于列表的列表。
创建从相应的短名称到完整函数名称的映射。
如果 Tree
表示一个永远不会正常终止的表达式,则返回 true
。
等效于使用文本 "..."
作为默认替换的 limit(Tree, Depth, Text)
。
将语法树限制为指定的深度。
将函数应用于语法树的每个节点。
将函数应用于语法树的每个直接子树。
在单个操作中组合 map 和 fold。
对语法树的直接子树执行 mapfold 操作。
类似于 lists:mapfoldl/3
,但适用于列表的列表。
返回一个不在集合 Used
中的原子。
返回一个不在集合 Used
中的用户命名原子。
类似于 new_variable_name/1
,但生成 N
个新名称的列表。
类似于 new_variable_name/2
,但生成 N
个新名称的列表。
从语法树的所有节点中删除所有注释。
等效于使用默认格式化函数 F
的 to_comment(Tree, Prefix, F)
。
将语法树转换为抽象注释。
返回语法树中出现的变量的名称。
类型
-type field() :: {atom(), {field_default(), field_type()}}.
-type field_default() :: none | syntaxTree().
-type field_type() :: none | syntaxTree().
-type fields() :: [field()].
-type key() :: attributes | errors | exports | functions | imports | module | records | warnings.
-type ordset(T) :: ordsets:ordset(T).
-type set(T) :: sets:set(T).
-type syntaxTree() :: erl_syntax:syntaxTree().
抽象语法树。有关详细信息,请参阅 erl_syntax
模块。
函数
-spec analyze_application(syntaxTree()) -> appFunName() | arity().
返回被调用函数的名称。
如果 Node
表示函数应用程序“F(X_1, ..., X_A)
”,则结果是被应用函数 F/A
的名称的表示形式。如果该函数未明确命名(即,F
由某些表达式给出),则仅返回元数 A
。
如果 Node
不表示格式正确的应用程序表达式,则求值将抛出 syntax_error
。
另请参见: analyze_function_name/1
。
-spec analyze_attribute(syntaxTree()) -> preprocessor | {atom(), term()}.
分析属性节点。
如果 Node
表示预处理器指令,则返回原子 preprocessor
。否则,如果 Node
表示模块属性“-Name...
”,则返回一个元组 {Name, Info}
,其中 Info
取决于 Name
,如下所示
{module, Info}
- 其中Info = analyze_module_attribute(Node)
。{export, Info}
- 其中Info = analyze_export_attribute(Node)
。{import, Info}
- 其中Info = analyze_import_attribute(Node)
。{file, Info}
- 其中Info = analyze_file_attribute(Node)
。{record, Info}
- 其中Info = analyze_record_attribute(Node)
。{Name, Info}
- 其中{Name, Info} = analyze_wild_attribute(Node)
。
如果 Node
不表示格式正确的模块属性,则求值将抛出 syntax_error
。
另请参见: analyze_export_attribute/1
、analyze_file_attribute/1
、analyze_import_attribute/1
、analyze_module_attribute/1
、analyze_record_attribute/1
、analyze_wild_attribute/1
。
-spec analyze_export_attribute(syntaxTree()) -> [functionName()].
返回 export 属性声明的函数名称列表。
我们不保证每个名称在列表中最多出现一次。列表的顺序未定义。
如果 Node
不表示格式正确的 export 属性,则求值将抛出 syntax_error
。
另请参见: analyze_attribute/1
。
-spec analyze_file_attribute(syntaxTree()) -> {string(), integer()}.
返回 file
属性的文件名和行号。
如果 Node
表示“-file(File, Line).
”,则结果是 {File, Line}
对。
如果 Node
不表示格式正确的 file
属性,则求值将抛出 syntax_error
。
另请参见: analyze_attribute/1
。
-spec analyze_form(syntaxTree()) -> {atom(), term()} | atom().
分析“源代码形式”节点。
如果 Node
是“form”类型(请参阅 erl_syntax:is_form/1
),则返回的值是一个元组 {Type, Info}
,其中 Type
是节点类型,而 Info
取决于 Type
,如下所示
{attribute, Info}
- 其中Info = analyze_attribute(Node)
。{error_marker, Info}
- 其中Info = erl_syntax:error_marker_info(Node)
。{function, Info}
- 其中Info = analyze_function(Node)
。{warning_marker, Info}
- 其中Info = erl_syntax:warning_marker_info(Node)
。
对于其他类型的形式,仅返回节点类型。
如果 Node
格式不正确,则评估会抛出 syntax_error
。
另请参阅:analyze_attribute/1
、analyze_function/1
、erl_syntax:error_marker_info/1
、erl_syntax:is_form/1
、erl_syntax:warning_marker_info/1
。
-spec analyze_forms(erl_syntax:forms()) -> [info_pair()].
分析一系列“程序形式”。
给定的 Forms
可以是 form_list
类型的单个语法树,也可以是“程序形式”语法树的列表。返回的值是一个 {Key, Info}
对的列表,其中 Key
的每个值在列表中最多出现一次;特定键的缺失表示该键没有定义明确的值。
结果列表中的每个条目都包含以下关于程序形式的相应信息
{attributes, Attributes}
Attributes = [{atom(), term()}]
Attributes
是一个对列表,表示Forms
中出现的所有所谓的“通配符”属性的名称和相应值(例如,“-compile(...)
”)(请参阅analyze_wild_attribute/1
)。我们不保证每个名称在列表中最多出现一次。列表的顺序未定义。{errors, Errors}
Errors = [term()]
Errors
是Forms
中出现的所有error_marker
节点的错误描述符列表。列表的顺序未定义。{exports, Exports}
Exports = [FunctionName]
FunctionName = atom() | {atom(), integer()} | {ModuleName, FunctionName}
ModuleName = atom()
Exports
是Forms
中导出声明属性列出的函数名称的表示形式列表(请参阅analyze_export_attribute/1
)。我们不保证每个名称在列表中最多出现一次。列表的顺序未定义。{functions, Functions}
Functions = [{atom(), integer()}]
Functions
是在Forms
中定义的函数名称列表(请参阅analyze_function/1
)。我们不保证每个名称在列表中最多出现一次。列表的顺序未定义。{imports, Imports}
Imports = [{Module, Names}]
Module = atom()
Names = [FunctionName]
FunctionName = atom() | {atom(), integer()} | {ModuleName, FunctionName}
ModuleName = atom()
Imports
是一个对列表,表示Forms
中导入声明属性列出的模块名称和相应的函数名称(请参阅analyze_import_attribute/1
),其中每个Module
在Imports
中最多出现一次。我们不保证每个名称在函数名称列表中最多出现一次。列表的顺序未定义。{module, ModuleName}
ModuleName = atom()
ModuleName
是Forms
中模块属性声明的名称。如果Forms
中未定义模块名称,则结果将不包含module
键的条目。如果出现多个模块名称声明,则将忽略除第一个之外的所有声明。{records, Records}
Records = [{atom(), Fields}]
Fields = [{atom(), {Default, Type}}]
Default = none | syntaxTree()
Type = none | syntaxTree()
Records
是一个对列表,表示Forms
中出现的所有记录声明属性的名称和相应的字段声明。对于声明时没有默认值的字段,Default
的对应值是原子none
。类似地,对于声明时没有类型的字段,Type
的对应值是原子none
(请参阅analyze_record_attribute/1
)。我们不保证每个记录名称在列表中最多出现一次。列表的顺序未定义。{warnings, Warnings}
Warnings = [term()]
Warnings
是Forms
中出现的所有warning_marker
节点的错误描述符列表。列表的顺序未定义。
如果遇到格式错误的 Erlang 构造,则评估会抛出 syntax_error
。
另请参阅:analyze_export_attribute/1
、analyze_function/1
、analyze_import_attribute/1
、analyze_record_attribute/1
、analyze_wild_attribute/1
、erl_syntax:error_marker_info/1
、erl_syntax:warning_marker_info/1
。
-spec analyze_function(syntaxTree()) -> {atom(), arity()}.
返回函数定义的名称和元数。
如果 Node
表示函数定义“Name(P_1, ..., P_A) -> ...
”,则结果为 {Name, A}
对。
如果 Node
不表示格式正确的函数定义,则评估会抛出 syntax_error
。
-spec analyze_function_name(syntaxTree()) -> functionName().
返回语法树表示的函数名称。
如果 Node
表示函数名称,例如“foo/1
”或“bloggs:fred/2
”,则会返回该名称的统一表示形式。语法树中元数和模块名称限定符的不同嵌套不会影响结果。
如果 Node
不表示格式正确的函数名称,则评估会抛出 syntax_error
。
-spec analyze_implicit_fun(syntaxTree()) -> functionName().
返回隐式 fun 表达式“fun F
”的名称。
结果是函数名称 F
的表示形式。(请参阅 analyze_function_name/1
。)
如果 Node
不表示格式正确的隐式 fun,则评估会抛出 syntax_error
。
另请参见: analyze_function_name/1
。
-spec analyze_import_attribute(syntaxTree()) -> {atom(), [functionName()]} | atom().
返回模块名称和(如果存在)import 属性声明的函数名称列表。
返回的值是一个原子 Module
或一个对 {Module, Names}
,其中 Names
是声明为从 Module
指定的模块导入的函数名称列表。我们不保证每个名称在 Names
中最多出现一次。列表的顺序未定义。
如果 Node
不表示格式正确的导入属性,则评估会抛出 syntax_error
。
另请参见: analyze_attribute/1
。
-spec analyze_module_attribute(syntaxTree()) -> atom() | {atom(), [atom()]}.
返回模块名称和模块属性声明的可能参数。
如果属性是一个简单的模块声明,例如 -module(name)
,则结果是模块名称。如果属性是参数化的模块声明,则结果是一个元组,其中包含模块名称和参数变量名称列表。
如果 Node
不表示格式正确的模块属性,则求值将抛出 syntax_error
。
另请参见: analyze_attribute/1
。
-spec analyze_record_attribute(syntaxTree()) -> {atom(), fields()}.
返回记录声明属性的名称和字段列表。
如果 Node
表示“-record(Name, {...}).
”,则结果为 {Name, Fields}
对,其中 Fields
是每个字段“Label
”、“Label = Default
”、“Label :: Type
”或“Label = Default :: Type
”的 {Label, {Default, Type}}
对列表,按从左到右的顺序列出。如果字段没有默认值声明,则 Default
的值将是原子 none
。如果字段没有类型声明,则 Type
的值将是原子 none
。我们不保证每个标签在列表中最多出现一次。
如果 Node
不表示格式正确的记录声明属性,则评估会抛出 syntax_error
。
-spec analyze_record_expr(syntaxTree()) -> {atom(), info()} | atom().
返回记录表达式的记录名称和字段名称/名称。
如果 Node
的类型为 record_expr
、record_index_expr
或 record_access
,则返回一个对 {Type, Info}
,否则返回一个原子 Type
。Type
是 Node
的节点类型,而 Info
取决于 Type
,如下所示
record_expr
:-{atom(), [{atom(), Value}]}
record_access
:-{atom(), atom()}
record_index_expr
:-{atom(), atom()}
对于 record_expr
节点,Info
表示记录名称和所涉及字段的描述符列表,按它们出现的顺序列出。如果 Node
表示“Label = Value
”,则字段描述符是一个对 {Label, Value}
。对于 record_access
节点,Info
表示记录名称和字段名称。对于 record_index_expr
节点,Info
表示记录名称和字段名称。
如果 Node
表示格式不正确的记录表达式,则评估会抛出 syntax_error
。
-spec analyze_record_field(syntaxTree()) -> field().
返回记录字段说明符的标签、值表达式和类型。
如果 Node
表示“Label
”、“Label = Default
”、“Label :: Type
”或“Label = Default :: Type
”,则结果为 {Label, {Default, Type}}
对。如果字段没有值表达式,则 Default
的值将是原子 none
。如果字段没有类型,则 Type
的值将是原子 none
。
如果 Node
不表示格式正确的记录字段说明符,则评估会抛出 syntax_error
。
-spec analyze_type_application(syntaxTree()) -> typeName().
返回使用的类型的名称。
如果 Node
表示本地(用户)类型应用程序“N(T_1, ..., T_A)
”,则结果是使用的预定义或本地类型 N/A
的名称的表示形式;如果 Node
表示远程用户类型应用程序“M:N(T_1, ..., T_A)
”,则结果是使用的远程类型 M:N/A
的名称的表示形式。
如果 Node
不表示格式正确的(用户)类型应用程序表达式,则评估会抛出 syntax_error
。
另请参阅:analyze_type_name/1
。
-spec analyze_type_name(syntaxTree()) -> typeName().
返回语法树表示的类型名称。
如果 Node
表示类型名称,例如“foo/1
”或“bloggs:fred/2
”,则会返回该名称的统一表示形式。
如果 Node
不表示格式正确的类型名称,则评估会抛出 syntax_error
。
-spec analyze_wild_attribute(syntaxTree()) -> {atom(), term()}.
返回“wild”属性的名称和值。
如果 Node
表示“-Name(Value)
”,则结果为 {Name, Value}
对。
请注意,不会检查 Name
是否是保留的属性名称,例如 module
或 export
:假定该属性是“通配符”。
如果 Node
不表示格式正确的通配符属性,则评估会抛出 syntax_error
。
另请参见: analyze_attribute/1
。
-spec annotate_bindings(syntaxTree()) -> syntaxTree().
在语法树中的节点上添加或更新注解。
等效于 annotate_bindings(Tree, Bindings)
,其中顶级环境 Bindings
取自 Tree
的根节点上的注释 {env, Bindings}
。如果不存在这样的注释,则会引发异常。
另请参阅:annotate_bindings/2
。
-spec annotate_bindings(syntaxTree(), ordset(atom())) -> syntaxTree().
在语法树中的节点上添加或更新注解。
Bindings
指定顶级节点环境中的绑定变量集。以下注释会受到影响
{env, Vars}
,表示子树的输入环境。{bound, Vars}
,表示在子树中绑定的变量。{free, Vars}
,表示子树中的自由变量。
Bindings
和 Vars
是表示变量名称的原子有序集列表(请参阅模块 ordsets
)。
-spec fold(fun((syntaxTree(), term()) -> term()), term(), syntaxTree()) -> term().
将函数折叠到语法树的所有节点上。
结果是 Function(X1, Function(X2, ... Function(Xn, Start) ... ))
的值,其中 [X1, X2, ..., Xn]
是 Tree
树的后序遍历节点。
另请参阅:fold_subtrees/3
, foldl_listlist/3
。
-spec fold_subtrees(fun((syntaxTree(), term()) -> term()), term(), syntaxTree()) -> term().
将函数折叠到语法树的直接子树上。
这类似于 fold/3
,但只作用于 Tree
的直接子树,按从左到右的顺序;不包括 Tree
的根节点。
另请参阅:fold/3
。
类似于 lists:foldl/3
,但适用于列表的列表。
另请参阅://stdlib/lists:foldl/3, fold/3
。
创建从相应的短名称到完整函数名称的映射。
名称由原子和整数的嵌套元组表示(请参阅 analyze_function_name/1
)。结果是一个列表,其中包含给定列表中每个元素 Name
的一个键值对 {ShortName, Name}
,其中对应的 ShortName
是 Name
最右侧最内层部分。因此,该列表表示从非限定名称到对应的限定名称的有限映射。
请注意,对于同一个 ShortName
,结果列表可能包含多个元组 {ShortName, Name}
,可能对应不同的 Name
值,具体取决于给定的列表。
另请参见: analyze_function_name/1
。
-spec is_fail_expr(syntaxTree()) -> boolean().
如果 Tree
表示一个永远不会正常终止的表达式,则返回 true
。
请注意,反之则不成立。目前,检测到的情况是对 exit/1
、throw/1
、erlang:error/1
和 erlang:error/2
的调用。
另请参阅://erts/erlang:error/1、//erts/erlang:error/2、//erts/erlang:exit/1、//erts/erlang:throw/1。
-spec limit(syntaxTree(), integer()) -> syntaxTree().
等效于使用文本 "..."
作为默认替换的 limit(Tree, Depth, Text)
。
另请参阅:limit/3
, erl_syntax:text/1
。
-spec limit(syntaxTree(), integer(), syntaxTree()) -> syntaxTree().
将语法树限制为指定的深度。
在给定的 Depth
深度,将 Tree
中的所有非叶子子树替换为 Node
。如果 Depth
为负数,则结果始终为 Node
,即使 Tree
没有子树。
当一组子树(例如,application
节点的参数列表)处于指定的深度,并且该组中有两个或多个子树时,即使它们是叶子节点,也会被统一替换为 Node
。位于指定深度之上的子树组的大小会受到限制,就好像组中的每个后续树都比前一个树深一层一样。例如,如果 Tree
表示一个整数列表 "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
",则 limit(Tree, 5)
的结果将表示 [1, 2, 3, 4, ...]
。
生成的语法树通常仅用于美化打印或类似的视觉格式化。
另请参阅:limit/2
。
-spec map(fun((syntaxTree()) -> syntaxTree()), syntaxTree()) -> syntaxTree().
将函数应用于语法树的每个节点。
每次应用的结果会替换对应的原始节点。遍历顺序是从下往上。
另请参阅:map_subtrees/2
。
-spec map_subtrees(fun((syntaxTree()) -> syntaxTree()), syntaxTree()) -> syntaxTree().
将函数应用于语法树的每个直接子树。
每次应用的结果都会替换对应的原始节点。
另请参阅:map/2
。
-spec mapfold(fun((syntaxTree(), term()) -> {syntaxTree(), term()}), term(), syntaxTree()) -> {syntaxTree(), term()}.
在单个操作中组合 map 和 fold。
这类似于 map/2
,但在对树进行类似于 fold/3
的后序遍历的同时,还会将每次 Function
应用的额外值传递到下一次应用。值 Start
将传递给第一个函数应用,最终结果是最后一个函数应用的结果。
-spec mapfold_subtrees(fun((syntaxTree(), term()) -> {syntaxTree(), term()}), term(), syntaxTree()) -> {syntaxTree(), term()}.
对语法树的直接子树执行 mapfold 操作。
这类似于 mapfold/3
,但只作用于 Tree
的直接子树,按从左到右的顺序;不包括 Tree
的根节点。
另请参阅:mapfold/3
。
-spec mapfoldl_listlist(fun((term(), term()) -> {term(), term()}), term(), [[term()]]) -> {[[term()]], term()}.
类似于 lists:mapfoldl/3
,但适用于列表的列表。
结果中的列表的列表与给定的列表的列表具有相同的结构。
返回一个不在集合 Used
中的原子。
这等效于 new_variable_name(Function, Used)
,其中 Function
将给定的整数 N
映射到名称由 "V
" 后跟 N
的数字构成的原子。
另请参阅:new_variable_name/2
。
返回一个不在集合 Used
中的用户命名原子。
原子通过将给定的 Function
应用于生成的整数而生成。整数使用一种算法生成,该算法尝试使名称在相对于集合中元素数量的合理小范围内随机分布。
此函数使用模块 rand
来生成新键。它使用的种子可以通过在首次调用此函数之前调用 rand:seed/1
或 rand:seed/2
来初始化。
类似于 new_variable_name/1
,但生成 N
个新名称的列表。
另请参阅:new_variable_name/1
。
类似于 new_variable_name/2
,但生成 N
个新名称的列表。
另请参阅:new_variable_name/2
。
-spec strip_comments(syntaxTree()) -> syntaxTree().
从语法树的所有节点中删除所有注释。
所有其他属性(例如位置信息)保持不变。列表形式的独立注释将被删除;任何其他独立注释都会更改为空注释(无文本,无缩进)。
-spec to_comment(syntaxTree()) -> syntaxTree().
-spec to_comment(syntaxTree(), string()) -> syntaxTree().
等效于使用默认格式化函数 F
的 to_comment(Tree, Prefix, F)
。
默认的 F
只是调用 erl_prettypr:format/1
。
-spec to_comment(syntaxTree(), string(), fun((syntaxTree()) -> string())) -> syntaxTree().
将语法树转换为抽象注释。
注释的行包含 Node
的文本,由给定的 Printer
函数生成。注释的每一行都以字符串 Prefix
作为前缀(这不包括注释行的初始 "%
" 字符)。
例如,to_comment(erl_syntax:abstract([a,b,c]))
的结果表示
%% [a,b,c]
(请参阅 to_comment/1
)。
注意
格式化函数返回的文本将在每个换行符处自动拆分为单独的注释行。无需额外工作。
另请参阅:to_comment/1
, to_comment/2
。
-spec variables(syntaxTree()) -> set(atom()).
返回语法树中出现的变量的名称。
结果是由原子表示的变量名称集合。不包括宏名称。
另请参阅://stdlib/sets。