/lib/syntax_tools/src/erl_syntax.erl
Erlang | 6765 lines | 2507 code | 852 blank | 3406 comment | 47 complexity | 84f69af772a3237def0c3ccbbad9bdce MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, AGPL-1.0
Large files files are truncated, but you can click here to view the full file
- %% =====================================================================
- %% Abstract Erlang syntax trees (`erl_parse'-compatible).
- %%
- %% Copyright (C) 1997-2004 Richard Carlsson
- %%
- %% This library is free software; you can redistribute it and/or modify
- %% it under the terms of the GNU Lesser General Public License as
- %% published by the Free Software Foundation; either version 2 of the
- %% License, or (at your option) any later version.
- %%
- %% This library is distributed in the hope that it will be useful, but
- %% WITHOUT ANY WARRANTY; without even the implied warranty of
- %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- %% Lesser General Public License for more details.
- %%
- %% You should have received a copy of the GNU Lesser General Public
- %% License along with this library; if not, write to the Free Software
- %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- %% USA
- %%
- %% Author contact: richardc@csd.uu.se
- %%
- %% $Id$
- %%
- %% =====================================================================
- %%
- %% @doc Abstract Erlang syntax trees.
- %%
- %% <p> This module defines an abstract data type for representing Erlang
- %% source code as syntax trees, in a way that is backwards compatible
- %% with the data structures created by the Erlang standard library
- %% parser module <code>erl_parse</code> (often referred to as "parse
- %% trees", which is a bit of a misnomer). This means that all
- %% <code>erl_parse</code> trees are valid abstract syntax trees, but the
- %% reverse is not true: abstract syntax trees can in general not be used
- %% as input to functions expecting an <code>erl_parse</code> tree.
- %% However, as long as an abstract syntax tree represents a correct
- %% Erlang program, the function <a
- %% href="#revert-1"><code>revert/1</code></a> should be able to
- %% transform it to the corresponding <code>erl_parse</code>
- %% representation.</p>
- %%
- %% <p>A recommended starting point for the first-time user is the
- %% documentation of the <a
- %% href="#type-syntaxTree"><code>syntaxTree()</code></a> data type, and
- %% the function <a href="#type-1"><code>type/1</code></a>.</p>
- %%
- %% <h3><b>NOTES:</b></h3>
- %%
- %% <p>This module deals with the composition and decomposition of
- %% <em>syntactic</em> entities (as opposed to semantic ones); its
- %% purpose is to hide all direct references to the data structures used
- %% to represent these entities. With few exceptions, the functions in
- %% this module perform no semantic interpretation of their inputs, and
- %% in general, the user is assumed to pass type-correct arguments - if
- %% this is not done, the effects are not defined.</p>
- %%
- %% <p>With the exception of the <code>erl_parse</code> data structures,
- %% the internal representations of abstract syntax trees are subject to
- %% change without notice, and should not be documented outside this
- %% module. Furthermore, we do not give any guarantees on how an abstract
- %% syntax tree may or may not be represented, <em>with the following
- %% exceptions</em>: no syntax tree is represented by a single atom, such
- %% as <code>none</code>, by a list constructor <code>[X | Y]</code>, or
- %% by the empty list <code>[]</code>. This can be relied on when writing
- %% functions that operate on syntax trees.</p>
- %%
- %% @type syntaxTree(). An abstract syntax tree. The
- %% <code>erl_parse</code> "parse tree" representation is a subset of the
- %% <code>syntaxTree()</code> representation.
- %%
- %% <p>Every abstract syntax tree node has a <em>type</em>, given by the
- %% function <a href="#type-1"><code>type/1</code></a>. Each node also
- %% has associated <em>attributes</em>; see <a
- %% href="#get_attrs-1"><code>get_attrs/1</code></a> for details. The
- %% functions <a href="#make_tree-2"><code>make_tree/2</code></a> and <a
- %% href="#subtrees-1"><code>subtrees/1</code></a> are generic
- %% constructor/decomposition functions for abstract syntax trees. The
- %% functions <a href="#abstract-1"><code>abstract/1</code></a> and <a
- %% href="#concrete-1"><code>concrete/1</code></a> convert between
- %% constant Erlang terms and their syntactic representations. The set of
- %% syntax tree nodes is extensible through the <a
- %% href="#tree-2"><code>tree/2</code></a> function.</p>
- %%
- %% <p>A syntax tree can be transformed to the <code>erl_parse</code>
- %% representation with the <a href="#revert-1"><code>revert/1</code></a>
- %% function.</p>
- %%
- %% @end
- %% =====================================================================
- -module(erl_syntax).
- -export([type/1,
- is_leaf/1,
- is_form/1,
- is_literal/1,
- abstract/1,
- concrete/1,
- revert/1,
- revert_forms/1,
- subtrees/1,
- make_tree/2,
- update_tree/2,
- meta/1,
- get_pos/1,
- set_pos/2,
- copy_pos/2,
- get_precomments/1,
- set_precomments/2,
- add_precomments/2,
- get_postcomments/1,
- set_postcomments/2,
- add_postcomments/2,
- has_comments/1,
- remove_comments/1,
- copy_comments/2,
- join_comments/2,
- get_ann/1,
- set_ann/2,
- add_ann/2,
- copy_ann/2,
- get_attrs/1,
- set_attrs/2,
- copy_attrs/2,
- flatten_form_list/1,
- cons/2,
- list_head/1,
- list_tail/1,
- is_list_skeleton/1,
- is_proper_list/1,
- list_elements/1,
- list_length/1,
- normalize_list/1,
- compact_list/1,
- application/2,
- application/3,
- application_arguments/1,
- application_operator/1,
- arity_qualifier/2,
- arity_qualifier_argument/1,
- arity_qualifier_body/1,
- atom/1,
- is_atom/2,
- atom_value/1,
- atom_literal/1,
- atom_name/1,
- attribute/1,
- attribute/2,
- attribute_arguments/1,
- attribute_name/1,
- binary/1,
- binary_field/1,
- binary_field/2,
- binary_field/3,
- binary_field_body/1,
- binary_field_types/1,
- binary_field_size/1,
- binary_fields/1,
- block_expr/1,
- block_expr_body/1,
- case_expr/2,
- case_expr_argument/1,
- case_expr_clauses/1,
- catch_expr/1,
- catch_expr_body/1,
- char/1,
- is_char/2,
- char_value/1,
- char_literal/1,
- clause/2,
- clause/3,
- clause_body/1,
- clause_guard/1,
- clause_patterns/1,
- comment/1,
- comment/2,
- comment_padding/1,
- comment_text/1,
- cond_expr/1,
- cond_expr_clauses/1,
- conjunction/1,
- conjunction_body/1,
- disjunction/1,
- disjunction_body/1,
- eof_marker/0,
- error_marker/1,
- error_marker_info/1,
- float/1,
- float_value/1,
- float_literal/1,
- form_list/1,
- form_list_elements/1,
- fun_expr/1,
- fun_expr_arity/1,
- fun_expr_clauses/1,
- function/2,
- function_arity/1,
- function_clauses/1,
- function_name/1,
- generator/2,
- generator_body/1,
- generator_pattern/1,
- if_expr/1,
- if_expr_clauses/1,
- implicit_fun/1,
- implicit_fun/2,
- implicit_fun_name/1,
- infix_expr/3,
- infix_expr_left/1,
- infix_expr_operator/1,
- infix_expr_right/1,
- integer/1,
- is_integer/2,
- integer_value/1,
- integer_literal/1,
- list/1,
- list/2,
- list_comp/2,
- list_comp_body/1,
- list_comp_template/1,
- list_prefix/1,
- list_suffix/1,
- macro/1,
- macro/2,
- macro_arguments/1,
- macro_name/1,
- match_expr/2,
- match_expr_body/1,
- match_expr_pattern/1,
- module_qualifier/2,
- module_qualifier_argument/1,
- module_qualifier_body/1,
- nil/0,
- operator/1,
- operator_literal/1,
- operator_name/1,
- parentheses/1,
- parentheses_body/1,
- prefix_expr/2,
- prefix_expr_argument/1,
- prefix_expr_operator/1,
- qualified_name/1,
- qualified_name_segments/1,
- query_expr/1,
- query_expr_body/1,
- receive_expr/1,
- receive_expr/3,
- receive_expr_action/1,
- receive_expr_clauses/1,
- receive_expr_timeout/1,
- record_access/2,
- record_access/3,
- record_access_argument/1,
- record_access_field/1,
- record_access_type/1,
- record_expr/2,
- record_expr/3,
- record_expr_argument/1,
- record_expr_fields/1,
- record_expr_type/1,
- record_field/1,
- record_field/2,
- record_field_name/1,
- record_field_value/1,
- record_index_expr/2,
- record_index_expr_field/1,
- record_index_expr_type/1,
- rule/2,
- rule_arity/1,
- rule_clauses/1,
- rule_name/1,
- size_qualifier/2,
- size_qualifier_argument/1,
- size_qualifier_body/1,
- string/1,
- is_string/2,
- string_value/1,
- string_literal/1,
- text/1,
- text_string/1,
- try_expr/2,
- try_expr/3,
- try_expr/4,
- try_after_expr/2,
- try_expr_body/1,
- try_expr_clauses/1,
- try_expr_handlers/1,
- try_expr_after/1,
- class_qualifier/2,
- class_qualifier_argument/1,
- class_qualifier_body/1,
- tuple/1,
- tuple_elements/1,
- tuple_size/1,
- underscore/0,
- variable/1,
- variable_name/1,
- variable_literal/1,
- warning_marker/1,
- warning_marker_info/1,
- tree/1,
- tree/2,
- data/1,
- is_tree/1]).
- %% =====================================================================
- %% IMPLEMENTATION NOTES:
- %%
- %% All nodes are represented by tuples of arity 2 or greater, whose
- %% first element is an atom which uniquely identifies the type of the
- %% node. (In the backwards-compatible representation, the interpretation
- %% is also often dependent on the context; the second element generally
- %% holds the position information - with a couple of exceptions; see
- %% `get_pos' and `set_pos' for details). In the documentation of this
- %% module, `Pos' is the source code position information associated with
- %% a node; usually, this is a positive integer indicating the original
- %% source code line, but no assumptions are made in this module
- %% regarding the format or interpretation of position information. When
- %% a syntax tree node is constructed, its associated position is by
- %% default set to the integer zero.
- %% =====================================================================
- -define(NO_UNUSED, true).
- %% =====================================================================
- %% Declarations of globally used internal data structures
- %% =====================================================================
- %% `com' records are used to hold comment information attached to a
- %% syntax tree node or a wrapper structure.
- %%
- %% #com{pre :: Pre, post :: Post}
- %%
- %% Pre = Post = [Com]
- %% Com = syntaxTree()
- %%
- %% type(Com) = comment
- -record(com, {pre = [],
- post = []}).
- %% `attr' records store node attributes as an aggregate.
- %%
- %% #attr{pos :: Pos, ann :: Ann, com :: Comments}
- %%
- %% Pos = term()
- %% Ann = [term()]
- %% Comments = none | #com{}
- %%
- %% where `Pos' `Ann' and `Comments' are the corresponding values of a
- %% `tree' or `wrapper' record.
- -record(attr, {pos = 0,
- ann = [],
- com = none}).
- %% `tree' records represent new-form syntax tree nodes.
- %%
- %% Tree = #tree{type :: Type, attr :: Attr, data :: Data}
- %%
- %% Type = atom()
- %% Attr = #attr{}
- %% Data = term()
- %%
- %% is_tree(Tree) = true
- -record(tree, {type,
- attr = #attr{},
- data}).
- %% `wrapper' records are used for attaching new-form node information to
- %% `erl_parse' trees.
- %%
- %% Wrapper = #wrapper{type :: Type, attr :: Attr, tree :: ParseTree}
- %%
- %% Type = atom()
- %% Attr = #attr{}
- %% ParseTree = term()
- %%
- %% is_tree(Wrapper) = false
- -record(wrapper, {type,
- attr = #attr{},
- tree}).
- %% =====================================================================
- %%
- %% Exported functions
- %%
- %% =====================================================================
- %% =====================================================================
- %% @spec type(Node::syntaxTree()) -> atom()
- %%
- %% @doc Returns the type tag of <code>Node</code>. If <code>Node</code>
- %% does not represent a syntax tree, evaluation fails with reason
- %% <code>badarg</code>. Node types currently defined by this module are:
- %% <p><center><table border="1">
- %% <tr>
- %% <td>application</td>
- %% <td>arity_qualifier</td>
- %% <td>atom</td>
- %% <td>attribute</td>
- %% </tr><tr>
- %% <td>binary</td>
- %% <td>binary_field</td>
- %% <td>block_expr</td>
- %% <td>case_expr</td>
- %% </tr><tr>
- %% <td>catch_expr</td>
- %% <td>char</td>
- %% <td>class_qualifier</td>
- %% <td>clause</td>
- %% </tr><tr>
- %% <td>comment</td>
- %% <td>cond_expr</td>
- %% <td>conjunction</td>
- %% <td>disjunction</td>
- %% </tr><tr>
- %% <td>eof_marker</td>
- %% <td>error_marker</td>
- %% <td>float</td>
- %% <td>form_list</td>
- %% </tr><tr>
- %% <td>fun_expr</td>
- %% <td>function</td>
- %% <td>generator</td>
- %% <td>if_expr</td>
- %% </tr><tr>
- %% <td>implicit_fun</td>
- %% <td>infix_expr</td>
- %% <td>integer</td>
- %% <td>list</td>
- %% </tr><tr>
- %% <td>list_comp</td>
- %% <td>macro</td>
- %% <td>match_expr</td>
- %% <td>module_qualifier</td>
- %% </tr><tr>
- %% <td>nil</td>
- %% <td>operator</td>
- %% <td>parentheses</td>
- %% <td>prefix_expr</td>
- %% </tr><tr>
- %% <td>qualified_name</td>
- %% <td>query_expr</td>
- %% <td>receive_expr</td>
- %% <td>record_access</td>
- %% </tr><tr>
- %% <td>record_expr</td>
- %% <td>record_field</td>
- %% <td>record_index_expr</td>
- %% <td>rule</td>
- %% </tr><tr>
- %% <td>size_qualifier</td>
- %% <td>string</td>
- %% <td>text</td>
- %% <td>try_expr</td>
- %% </tr><tr>
- %% <td>tuple</td>
- %% <td>underscore</td>
- %% <td>variable</td>
- %% <td>warning_marker</td>
- %% </tr>
- %% </table></center></p>
- %% <p>The user may (for special purposes) create additional nodes
- %% with other type tags, using the <code>tree/2</code> function.</p>
- %%
- %% <p>Note: The primary constructor functions for a node type should
- %% always have the same name as the node type itself.</p>
- %%
- %% @see tree/2
- %% @see application/3
- %% @see arity_qualifier/2
- %% @see atom/1
- %% @see attribute/2
- %% @see binary/1
- %% @see binary_field/2
- %% @see block_expr/1
- %% @see case_expr/2
- %% @see catch_expr/1
- %% @see char/1
- %% @see class_qualifier/2
- %% @see clause/3
- %% @see comment/2
- %% @see cond_expr/1
- %% @see conjunction/1
- %% @see disjunction/1
- %% @see eof_marker/0
- %% @see error_marker/1
- %% @see float/1
- %% @see form_list/1
- %% @see fun_expr/1
- %% @see function/2
- %% @see generator/2
- %% @see if_expr/1
- %% @see implicit_fun/2
- %% @see infix_expr/3
- %% @see integer/1
- %% @see list/2
- %% @see list_comp/2
- %% @see macro/2
- %% @see match_expr/2
- %% @see module_qualifier/2
- %% @see nil/0
- %% @see operator/1
- %% @see parentheses/1
- %% @see prefix_expr/2
- %% @see qualified_name/1
- %% @see query_expr/1
- %% @see receive_expr/3
- %% @see record_access/3
- %% @see record_expr/2
- %% @see record_field/2
- %% @see record_index_expr/2
- %% @see rule/2
- %% @see size_qualifier/2
- %% @see string/1
- %% @see text/1
- %% @see try_expr/3
- %% @see tuple/1
- %% @see underscore/0
- %% @see variable/1
- %% @see warning_marker/1
- type(#tree{type = T}) ->
- T;
- type(#wrapper{type = T}) ->
- T;
- type(Node) ->
- %% Check for `erl_parse'-compatible nodes, and otherwise fail.
- case Node of
- %% Leaf types
- {atom, _, _} -> atom;
- {char, _, _} -> char;
- {float, _, _} -> float;
- {integer, _, _} -> integer;
- {nil, _} -> nil;
- {string, _, _} -> string;
- {var, _, Name} ->
- if Name == '_' -> underscore;
- true -> variable
- end;
- {error, _} -> error_marker;
- {warning, _} -> warning_marker;
- {eof, _} -> eof_marker;
- %% Composite types
- {'case', _, _, _} -> case_expr;
- {'catch', _, _} -> catch_expr;
- {'cond', _, _} -> cond_expr;
- {'fun', _, {clauses, _}} -> fun_expr;
- {'fun', _, {function, _, _}} -> implicit_fun;
- {'if', _, _} -> if_expr;
- {'receive', _, _, _, _} -> receive_expr;
- {'receive', _, _} -> receive_expr;
- {attribute, _, _, _} -> attribute;
- {bin, _, _} -> binary;
- {bin_element, _, _, _, _} -> binary_field;
- {block, _, _} -> block_expr;
- {call, _, _, _} -> application;
- {clause, _, _, _, _} -> clause;
- {cons, _, _, _} -> list;
- {function, _, _, _, _} -> function;
- {generate, _, _, _} -> generator;
- {lc, _, _, _} -> list_comp;
- {match, _, _, _} -> match_expr;
- {op, _, _, _, _} -> infix_expr;
- {op, _, _, _} -> prefix_expr;
- {'query', _, _} -> query_expr;
- {record, _, _, _, _} -> record_expr;
- {record, _, _, _} -> record_expr;
- {record_field, _, _, _, _} -> record_access;
- {record_field, _, _, _} ->
- case is_qualified_name(Node) of
- true -> qualified_name;
- false -> record_access
- end;
- {record_index, _, _, _} -> record_index_expr;
- {remote, _, _, _} -> module_qualifier;
- {rule, _, _, _, _} -> rule;
- {'try', _, _, _, _, _} -> try_expr;
- {tuple, _, _} -> tuple;
- _ ->
- erlang:fault({badarg, Node})
- end.
- %% =====================================================================
- %% @spec is_leaf(Node::syntaxTree()) -> bool()
- %%
- %% @doc Returns <code>true</code> if <code>Node</code> is a leaf node,
- %% otherwise <code>false</code>. The currently recognised leaf node
- %% types are:
- %% <p><center><table border="1">
- %% <tr>
- %% <td><code>atom</code></td>
- %% <td><code>char</code></td>
- %% <td><code>comment</code></td>
- %% <td><code>eof_marker</code></td>
- %% <td><code>error_marker</code></td>
- %% </tr><tr>
- %% <td><code>float</code></td>
- %% <td><code>integer</code></td>
- %% <td><code>nil</code></td>
- %% <td><code>operator</code></td>
- %% <td><code>string</code></td>
- %% </tr><tr>
- %% <td><code>text</code></td>
- %% <td><code>underscore</code></td>
- %% <td><code>variable</code></td>
- %% <td><code>warning_marker</code></td>
- %% </tr>
- %% </table></center></p>
- %% <p>A node of type <code>tuple</code> is a leaf node if and only if
- %% its arity is zero.</p>
- %%
- %% <p>Note: not all literals are leaf nodes, and vice versa. E.g.,
- %% tuples with nonzero arity and nonempty lists may be literals, but are
- %% not leaf nodes. Variables, on the other hand, are leaf nodes but not
- %% literals.</p>
- %%
- %% @see type/1
- %% @see is_literal/1
- is_leaf(Node) ->
- case type(Node) of
- atom -> true;
- char -> true;
- comment -> true; % nonstandard type
- eof_marker -> true;
- error_marker -> true;
- float -> true;
- integer -> true;
- nil -> true;
- operator -> true; % nonstandard type
- string -> true;
- text -> true; % nonstandard type
- tuple ->
- case tuple_elements(Node) of
- [] -> true;
- _ -> false
- end;
- underscore -> true;
- variable -> true;
- warning_marker -> true;
- _ -> false
- end.
- %% =====================================================================
- %% @spec is_form(Node::syntaxTree()) -> bool()
- %%
- %% @doc Returns <code>true</code> if <code>Node</code> is a syntax tree
- %% representing a so-called "source code form", otherwise
- %% <code>false</code>. Forms are the Erlang source code units which,
- %% placed in sequence, constitute an Erlang program. Current form types
- %% are:
- %% <p><center><table border="1">
- %% <tr>
- %% <td><code>attribute</code></td>
- %% <td><code>comment</code></td>
- %% <td><code>error_marker</code></td>
- %% <td><code>eof_marker</code></td>
- %% </tr><tr>
- %% <td><code>form_list</code></td>
- %% <td><code>function</code></td>
- %% <td><code>rule</code></td>
- %% <td><code>warning_marker</code></td>
- %% </tr>
- %% </table></center></p>
- %% @see type/1
- %% @see attribute/2
- %% @see comment/2
- %% @see eof_marker/1
- %% @see error_marker/1
- %% @see form_list/1
- %% @see function/2
- %% @see rule/2
- %% @see warning_marker/1
- is_form(Node) ->
- case type(Node) of
- attribute -> true;
- comment -> true;
- function -> true;
- eof_marker -> true;
- error_marker -> true;
- form_list -> true;
- rule -> true;
- warning_marker -> true;
- _ -> false
- end.
- %% =====================================================================
- %% @spec get_pos(Node::syntaxTree()) -> term()
- %%
- %% @doc Returns the position information associated with
- %% <code>Node</code>. This is usually a nonnegative integer (indicating
- %% the source code line number), but may be any term. By default, all
- %% new tree nodes have their associated position information set to the
- %% integer zero.
- %%
- %% @see set_pos/2
- %% @see get_attrs/1
- %% All `erl_parse' tree nodes are represented by tuples whose second
- %% field is the position information (usually an integer), *with the
- %% exceptions of* `{error, ...}' (type `error_marker') and `{warning,
- %% ...}' (type `warning_marker'), which only contain the associated line
- %% number *of the error descriptor*; this is all handled transparently
- %% by `get_pos' and `set_pos'.
- get_pos(#tree{attr = Attr}) ->
- Attr#attr.pos;
- get_pos(#wrapper{attr = Attr}) ->
- Attr#attr.pos;
- get_pos({error, {Pos, _, _}}) ->
- Pos;
- get_pos({warning, {Pos, _, _}}) ->
- Pos;
- get_pos(Node) ->
- %% Here, we assume that we have an `erl_parse' node with position
- %% information in element 2.
- element(2, Node).
- %% =====================================================================
- %% @spec set_pos(Node::syntaxTree(), Pos::term()) -> syntaxTree()
- %%
- %% @doc Sets the position information of <code>Node</code> to
- %% <code>Pos</code>.
- %%
- %% @see get_pos/1
- %% @see copy_pos/2
- set_pos(Node, Pos) ->
- case Node of
- #tree{attr = Attr} ->
- Node#tree{attr = Attr#attr{pos = Pos}};
- #wrapper{attr = Attr} ->
- Node#wrapper{attr = Attr#attr{pos = Pos}};
- _ ->
- %% We then assume we have an `erl_parse' node, and create a
- %% wrapper around it to make things more uniform.
- set_pos(wrap(Node), Pos)
- end.
- %% =====================================================================
- %% @spec copy_pos(Source::syntaxTree(), Target::syntaxTree()) ->
- %% syntaxTree()
- %%
- %% @doc Copies the position information from <code>Source</code> to
- %% <code>Target</code>.
- %%
- %% <p>This is equivalent to <code>set_pos(Target,
- %% get_pos(Source))</code>, but potentially more efficient.</p>
- %%
- %% @see get_pos/1
- %% @see set_pos/2
- copy_pos(Source, Target) ->
- set_pos(Target, get_pos(Source)).
- %% =====================================================================
- %% `get_com' and `set_com' are for internal use only.
- get_com(#tree{attr = Attr}) -> Attr#attr.com;
- get_com(#wrapper{attr = Attr}) -> Attr#attr.com;
- get_com(_) -> none.
- set_com(Node, Com) ->
- case Node of
- #tree{attr = Attr} ->
- Node#tree{attr = Attr#attr{com = Com}};
- #wrapper{attr = Attr} ->
- Node#wrapper{attr = Attr#attr{com = Com}};
- _ ->
- set_com(wrap(Node), Com)
- end.
- %% =====================================================================
- %% @spec get_precomments(syntaxTree()) -> [syntaxTree()]
- %%
- %% @doc Returns the associated pre-comments of a node. This is a
- %% possibly empty list of abstract comments, in top-down textual order.
- %% When the code is formatted, pre-comments are typically displayed
- %% directly above the node. For example:
- %% <pre>
- %% % Pre-comment of function
- %% foo(X) -> {bar, X}.</pre>
- %%
- %% <p>If possible, the comment should be moved before any preceding
- %% separator characters on the same line. E.g.:
- %% <pre>
- %% foo([X | Xs]) ->
- %% % Pre-comment of 'bar(X)' node
- %% [bar(X) | foo(Xs)];
- %% ...</pre>
- %% (where the comment is moved before the "<code>[</code>").</p>
- %%
- %% @see comment/2
- %% @see set_precomments/2
- %% @see get_postcomments/1
- %% @see get_attrs/1
- get_precomments(#tree{attr = Attr}) -> get_precomments_1(Attr);
- get_precomments(#wrapper{attr = Attr}) -> get_precomments_1(Attr);
- get_precomments(_) -> [].
- get_precomments_1(#attr{com = none}) -> [];
- get_precomments_1(#attr{com = #com{pre = Cs}}) -> Cs.
- %% =====================================================================
- %% @spec set_precomments(Node::syntaxTree(),
- %% Comments::[syntaxTree()]) -> syntaxTree()
- %%
- %% @doc Sets the pre-comments of <code>Node</code> to
- %% <code>Comments</code>. <code>Comments</code> should be a possibly
- %% empty list of abstract comments, in top-down textual order.
- %%
- %% @see comment/2
- %% @see get_precomments/1
- %% @see add_precomments/2
- %% @see set_postcomments/2
- %% @see copy_comments/2
- %% @see remove_comments/1
- %% @see join_comments/2
- set_precomments(Node, Cs) ->
- case Node of
- #tree{attr = Attr} ->
- Node#tree{attr = set_precomments_1(Attr, Cs)};
- #wrapper{attr = Attr} ->
- Node#wrapper{attr = set_precomments_1(Attr, Cs)};
- _ ->
- set_precomments(wrap(Node), Cs)
- end.
- set_precomments_1(#attr{com = none} = Attr, Cs) ->
- Attr#attr{com = #com{pre = Cs}};
- set_precomments_1(#attr{com = Com} = Attr, Cs) ->
- Attr#attr{com = Com#com{pre = Cs}}.
- %% =====================================================================
- %% @spec add_precomments(Comments::[syntaxTree()],
- %% Node::syntaxTree()) -> syntaxTree()
- %%
- %% @doc Appends <code>Comments</code> to the pre-comments of
- %% <code>Node</code>.
- %%
- %% <p>Note: This is equivalent to <code>set_precomments(Node,
- %% get_precomments(Node) ++ Comments)</code>, but potentially more
- %% efficient.</p>
- %%
- %% @see comment/2
- %% @see get_precomments/1
- %% @see set_precomments/2
- %% @see add_postcomments/2
- %% @see join_comments/2
- add_precomments(Cs, Node) ->
- case Node of
- #tree{attr = Attr} ->
- Node#tree{attr = add_precomments_1(Cs, Attr)};
- #wrapper{attr = Attr} ->
- Node#wrapper{attr = add_precomments_1(Cs, Attr)};
- _ ->
- add_precomments(Cs, wrap(Node))
- end.
- add_precomments_1(Cs, #attr{com = none} = Attr) ->
- Attr#attr{com = #com{pre = Cs}};
- add_precomments_1(Cs, #attr{com = Com} = Attr) ->
- Attr#attr{com = Com#com{pre = Com#com.pre ++ Cs}}.
- %% =====================================================================
- %% @spec get_postcomments(syntaxTree()) -> [syntaxTree()]
- %%
- %% @doc Returns the associated post-comments of a node. This is a
- %% possibly empty list of abstract comments, in top-down textual order.
- %% When the code is formatted, post-comments are typically displayed to
- %% the right of and/or below the node. For example:
- %% <pre>
- %% {foo, X, Y} % Post-comment of tuple</pre>
- %%
- %% <p>If possible, the comment should be moved past any following
- %% separator characters on the same line, rather than placing the
- %% separators on the following line. E.g.:
- %% <pre>
- %% foo([X | Xs], Y) ->
- %% foo(Xs, bar(X)); % Post-comment of 'bar(X)' node
- %% ...</pre>
- %% (where the comment is moved past the rightmost "<code>)</code>" and
- %% the "<code>;</code>").</p>
- %%
- %% @see comment/2
- %% @see set_postcomments/2
- %% @see get_precomments/1
- %% @see get_attrs/1
- get_postcomments(#tree{attr = Attr}) -> get_postcomments_1(Attr);
- get_postcomments(#wrapper{attr = Attr}) -> get_postcomments_1(Attr);
- get_postcomments(_) -> [].
- get_postcomments_1(#attr{com = none}) -> [];
- get_postcomments_1(#attr{com = #com{post = Cs}}) -> Cs.
- %% =====================================================================
- %% @spec set_postcomments(Node::syntaxTree(),
- %% Comments::[syntaxTree()]) -> syntaxTree()
- %%
- %% @doc Sets the post-comments of <code>Node</code> to
- %% <code>Comments</code>. <code>Comments</code> should be a possibly
- %% empty list of abstract comments, in top-down textual order
- %%
- %% @see comment/2
- %% @see get_postcomments/1
- %% @see add_postcomments/2
- %% @see set_precomments/2
- %% @see copy_comments/2
- %% @see remove_comments/1
- %% @see join_comments/2
- set_postcomments(Node, Cs) ->
- case Node of
- #tree{attr = Attr} ->
- Node#tree{attr = set_postcomments_1(Attr, Cs)};
- #wrapper{attr = Attr} ->
- Node#wrapper{attr = set_postcomments_1(Attr, Cs)};
- _ ->
- set_postcomments(wrap(Node), Cs)
- end.
- set_postcomments_1(#attr{com = none} = Attr, Cs) ->
- Attr#attr{com = #com{post = Cs}};
- set_postcomments_1(#attr{com = Com} = Attr, Cs) ->
- Attr#attr{com = Com#com{post = Cs}}.
- %% =====================================================================
- %% @spec add_postcomments(Comments::[syntaxTree()],
- %% Node::syntaxTree()) -> syntaxTree()
- %%
- %% @doc Appends <code>Comments</code> to the post-comments of
- %% <code>Node</code>.
- %%
- %% <p>Note: This is equivalent to <code>set_postcomments(Node,
- %% get_postcomments(Node) ++ Comments)</code>, but potentially more
- %% efficient.</p>
- %%
- %% @see comment/2
- %% @see get_postcomments/1
- %% @see set_postcomments/2
- %% @see add_precomments/2
- %% @see join_comments/2
- add_postcomments(Cs, Node) ->
- case Node of
- #tree{attr = Attr} ->
- Node#tree{attr = add_postcomments_1(Cs, Attr)};
- #wrapper{attr = Attr} ->
- Node#wrapper{attr = add_postcomments_1(Cs, Attr)};
- _ ->
- add_postcomments(Cs, wrap(Node))
- end.
- add_postcomments_1(Cs, #attr{com = none} = Attr) ->
- Attr#attr{com = #com{post = Cs}};
- add_postcomments_1(Cs, #attr{com = Com} = Attr) ->
- Attr#attr{com = Com#com{post = Com#com.post ++ Cs}}.
- %% =====================================================================
- %% @spec has_comments(Node::syntaxTree()) -> bool()
- %%
- %% @doc Yields <code>false</code> if the node has no associated
- %% comments, and <code>true</code> otherwise.
- %%
- %% <p>Note: This is equivalent to <code>(get_precomments(Node) == [])
- %% and (get_postcomments(Node) == [])</code>, but potentially more
- %% efficient.</p>
- %%
- %% @see get_precomments/1
- %% @see get_postcomments/1
- %% @see remove_comments/1
- has_comments(#tree{attr = Attr}) ->
- case Attr#attr.com of
- none -> false;
- #com{pre = [], post = []} -> false;
- _ -> true
- end;
- has_comments(#wrapper{attr = Attr}) ->
- case Attr#attr.com of
- none -> false;
- #com{pre = [], post = []} -> false;
- _ -> true
- end;
- has_comments(_) -> false.
- %% =====================================================================
- %% @spec remove_comments(Node::syntaxTree()) -> syntaxTree()
- %%
- %% @doc Clears the associated comments of <code>Node</code>.
- %%
- %% <p>Note: This is equivalent to
- %% <code>set_precomments(set_postcomments(Node, []), [])</code>, but
- %% potentially more efficient.</p>
- %%
- %% @see set_precomments/2
- %% @see set_postcomments/2
- remove_comments(Node) ->
- case Node of
- #tree{attr = Attr} ->
- Node#tree{attr = Attr#attr{com = none}};
- #wrapper{attr = Attr} ->
- Node#wrapper{attr = Attr#attr{com = none}};
- _ ->
- Node
- end.
- %% =====================================================================
- %% @spec copy_comments(Source::syntaxTree(), Target::syntaxTree()) ->
- %% syntaxTree()
- %%
- %% @doc Copies the pre- and postcomments from <code>Source</code> to
- %% <code>Target</code>.
- %%
- %% <p>Note: This is equivalent to
- %% <code>set_postcomments(set_precomments(Target,
- %% get_precomments(Source)), get_postcomments(Source))</code>, but
- %% potentially more efficient.</p>
- %%
- %% @see comment/2
- %% @see get_precomments/1
- %% @see get_postcomments/1
- %% @see set_precomments/2
- %% @see set_postcomments/2
- copy_comments(Source, Target) ->
- set_com(Target, get_com(Source)).
- %% =====================================================================
- %% @spec join_comments(Source::syntaxTree(), Target::syntaxTree()) ->
- %% syntaxTree()
- %%
- %% @doc Appends the comments of <code>Source</code> to the current
- %% comments of <code>Target</code>.
- %%
- %% <p>Note: This is equivalent to
- %% <code>add_postcomments(get_postcomments(Source),
- %% add_precomments(get_precomments(Source), Target))</code>, but
- %% potentially more efficient.</p>
- %%
- %% @see comment/2
- %% @see get_precomments/1
- %% @see get_postcomments/1
- %% @see add_precomments/2
- %% @see add_postcomments/2
- join_comments(Source, Target) ->
- add_postcomments(
- get_postcomments(Source),
- add_precomments(get_precomments(Source), Target)).
- %% =====================================================================
- %% @spec get_ann(syntaxTree()) -> [term()]
- %%
- %% @doc Returns the list of user annotations associated with a syntax
- %% tree node. For a newly created node, this is the empty list. The
- %% annotations may be any terms.
- %%
- %% @see set_ann/2
- %% @see get_attrs/1
- get_ann(#tree{attr = Attr}) -> Attr#attr.ann;
- get_ann(#wrapper{attr = Attr}) -> Attr#attr.ann;
- get_ann(_) -> [].
- %% =====================================================================
- %% @spec set_ann(Node::syntaxTree(), Annotations::[term()]) ->
- %% syntaxTree()
- %%
- %% @doc Sets the list of user annotations of <code>Node</code> to
- %% <code>Annotations</code>.
- %%
- %% @see get_ann/1
- %% @see add_ann/2
- %% @see copy_ann/2
- set_ann(Node, As) ->
- case Node of
- #tree{attr = Attr} ->
- Node#tree{attr = Attr#attr{ann = As}};
- #wrapper{attr = Attr} ->
- Node#wrapper{attr = Attr#attr{ann = As}};
- _ ->
- %% Assume we have an `erl_parse' node and create a wrapper
- %% structure to carry the annotation.
- set_ann(wrap(Node), As)
- end.
- %% =====================================================================
- %% @spec add_ann(Annotation::term(), Node::syntaxTree()) -> syntaxTree()
- %%
- %% @doc Appends the term <code>Annotation</code> to the list of user
- %% annotations of <code>Node</code>.
- %%
- %% <p>Note: this is equivalent to <code>set_ann(Node, [Annotation |
- %% get_ann(Node)])</code>, but potentially more efficient.</p>
- %%
- %% @see get_ann/1
- %% @see set_ann/2
- add_ann(A, Node) ->
- case Node of
- #tree{attr = Attr} ->
- Node#tree{attr = Attr#attr{ann = [A | Attr#attr.ann]}};
- #wrapper{attr = Attr} ->
- Node#wrapper{attr = Attr#attr{ann = [A | Attr#attr.ann]}};
- _ ->
- %% Assume we have an `erl_parse' node and create a wrapper
- %% structure to carry the annotation.
- add_ann(A, wrap(Node))
- end.
- %% =====================================================================
- %% @spec copy_ann(Source::syntaxTree(), Target::syntaxTree()) ->
- %% syntaxTree()
- %%
- %% @doc Copies the list of user annotations from <code>Source</code> to
- %% <code>Target</code>.
- %%
- %% <p>Note: this is equivalent to <code>set_ann(Target,
- %% get_ann(Source))</code>, but potentially more efficient.</p>
- %%
- %% @see get_ann/1
- %% @see set_ann/2
- copy_ann(Source, Target) ->
- set_ann(Target, get_ann(Source)).
- %% =====================================================================
- %% @spec get_attrs(syntaxTree()) -> syntaxTreeAttributes()
- %%
- %% @doc Returns a representation of the attributes associated with a
- %% syntax tree node. The attributes are all the extra information that
- %% can be attached to a node. Currently, this includes position
- %% information, source code comments, and user annotations. The result
- %% of this function cannot be inspected directly; only attached to
- %% another node (cf. <code>set_attrs/2</code>).
- %%
- %% <p>For accessing individual attributes, see <code>get_pos/1</code>,
- %% <code>get_ann/1</code>, <code>get_precomments/1</code> and
- %% <code>get_postcomments/1</code>.</p>
- %%
- %% @type syntaxTreeAttributes(). This is an abstract representation of
- %% syntax tree node attributes; see the function <a
- %% href="#get_attrs-1"><code>get_attrs/1</code></a>.
- %%
- %% @see set_attrs/2
- %% @see get_pos/1
- %% @see get_ann/1
- %% @see get_precomments/1
- %% @see get_postcomments/1
- get_attrs(#tree{attr = Attr}) -> Attr;
- get_attrs(#wrapper{attr = Attr}) -> Attr;
- get_attrs(Node) -> #attr{pos = get_pos(Node),
- ann = get_ann(Node),
- com = get_com(Node)}.
- %% =====================================================================
- %% @spec set_attrs(Node::syntaxTree(),
- %% Attributes::syntaxTreeAttributes()) -> syntaxTree()
- %%
- %% @doc Sets the attributes of <code>Node</code> to
- %% <code>Attributes</code>.
- %%
- %% @see get_attrs/1
- %% @see copy_attrs/2
- set_attrs(Node, Attr) ->
- case Node of
- #tree{} ->
- Node#tree{attr = Attr};
- #wrapper{} ->
- Node#wrapper{attr = Attr};
- _ ->
- set_attrs(wrap(Node), Attr)
- end.
- %% =====================================================================
- %% @spec copy_attrs(Source::syntaxTree(), Target::syntaxTree()) ->
- %% syntaxTree()
- %%
- %% @doc Copies the attributes from <code>Source</code> to
- %% <code>Target</code>.
- %%
- %% <p>Note: this is equivalent to <code>set_attrs(Target,
- %% get_attrs(Source))</code>, but potentially more efficient.</p>
- %%
- %% @see get_attrs/1
- %% @see set_attrs/2
- copy_attrs(S, T) ->
- set_attrs(T, get_attrs(S)).
- %% =====================================================================
- %% @spec comment(Strings) -> syntaxTree()
- %% @equiv comment(none, Strings)
- comment(Strings) ->
- comment(none, Strings).
- %% =====================================================================
- %% @spec comment(Padding, Strings::[string()]) -> syntaxTree()
- %% Padding = none | integer()
- %%
- %% @doc Creates an abstract comment with the given padding and text. If
- %% <code>Strings</code> is a (possibly empty) list
- %% <code>["<em>Txt1</em>", ..., "<em>TxtN</em>"]</code>, the result
- %% represents the source code text
- %% <pre>
- %% %<em>Txt1</em>
- %% ...
- %% %<em>TxtN</em></pre>
- %% <code>Padding</code> states the number of empty character positions
- %% to the left of the comment separating it horizontally from
- %% source code on the same line (if any). If <code>Padding</code> is
- %% <code>none</code>, a default positive number is used. If
- %% <code>Padding</code> is an integer less than 1, there should be no
- %% separating space. Comments are in themselves regarded as source
- %% program forms.
- %%
- %% @see comment/1
- %% @see is_form/1
- -record(comment, {pad, text}).
- %% type(Node) = comment
- %% data(Node) = #comment{pad :: Padding, text :: Strings}
- %%
- %% Padding = none | integer()
- %% Strings = [string()]
- comment(Pad, Strings) ->
- tree(comment, #comment{pad = Pad, text = Strings}).
- %% =====================================================================
- %% @spec comment_text(Node::syntaxTree()) -> [string()]
- %%
- %% @doc Returns the lines of text of the abstract comment.
- %%
- %% @see comment/2
- comment_text(Node) ->
- (data(Node))#comment.text.
- %% =====================================================================
- %% @spec comment_padding(Node::syntaxTree()) -> none | integer()
- %%
- %% @doc Returns the amount of padding before the comment, or
- %% <code>none</code>. The latter means that a default padding may be
- %% used.
- %%
- %% @see comment/2
- comment_padding(Node) ->
- (data(Node))#comment.pad.
- %% =====================================================================
- %% @spec form_list(Forms::[syntaxTree()]) -> syntaxTree()
- %%
- %% @doc Creates an abstract sequence of "source code forms". If
- %% <code>Forms</code> is <code>[F1, ..., Fn]</code>, where each
- %% <code>Fi</code> is a form (cf. <code>is_form/1</code>, the result
- %% represents
- %% <pre>
- %% <em>F1</em>
- %% ...
- %% <em>Fn</em></pre>
- %% where the <code>Fi</code> are separated by one or more line breaks. A
- %% node of type <code>form_list</code> is itself regarded as a source
- %% code form; cf. <code>flatten_form_list/1</code>.
- %%
- %% <p>Note: this is simply a way of grouping source code forms as a
- %% single syntax tree, usually in order to form an Erlang module
- %% definition.</p>
- %%
- %% @see form_list_elements/1
- %% @see is_form/1
- %% @see flatten_form_list/1
- %% type(Node) = form_list
- %% data(Node) = [Form]
- %%
- %% Form = syntaxTree()
- %% is_form(Form) = true
- form_list(Forms) ->
- tree(form_list, Forms).
- %% =====================================================================
- %% @spec form_list_elements(syntaxTree()) -> [syntaxTree()]
- %%
- %% @doc Returns the list of subnodes of a <code>form_list</code> node.
- %%
- %% @see form_list/1
- form_list_elements(Node) ->
- data(Node).
- %% =====================================================================
- %% @spec flatten_form_list(Node::syntaxTree()) -> syntaxTree()
- %%
- %% @doc Flattens sublists of a <code>form_list</code> node. Returns
- %% <code>Node</code> with all subtrees of type <code>form_list</code>
- %% recursively expanded, yielding a single "flat" abstract form
- %% sequence.
- %%
- %% @see form_list/1
- flatten_form_list(Node) ->
- Fs = form_list_elements(Node),
- Fs1 = lists:reverse(flatten_form_list_1(Fs, [])),
- copy_attrs(Node, form_list(Fs1)).
- flatten_form_list_1([F | Fs], As) ->
- case type(F) of
- form_list ->
- As1 = flatten_form_list_1(form_list_elements(F), As),
- flatten_form_list_1(Fs, As1);
- _ ->
- flatten_form_list_1(Fs, [F | As])
- end;
- flatten_form_list_1([], As) ->
- As.
- %% =====================================================================
- %% @spec text(String::string()) -> syntaxTree()
- %%
- %% @doc Creates an abstract piece of source code text. The result
- %% represents exactly the sequence of characters in <code>String</code>.
- %% This is useful in cases when one wants full control of the resulting
- %% output, e.g., for the appearance of floating-point numbers or macro
- %% definitions.
- %%
- %% @see text_string/1
- %% type(Node) = text
- %% data(Node) = string()
- text(String) ->
- tree(text, String).
- %% =====================================================================
- %% @spec text_string(syntaxTree()) -> string()
- %%
- %% @doc Returns the character sequence represented by a
- %% <code>text</code> node.
- %%
- %% @see text/1
- text_string(Node) ->
- data(Node).
- %% =====================================================================
- %% @spec variable(Name) -> syntaxTree()
- %% Name = atom() | string()
- %%
- %% @doc Creates an abstract variable with the given name.
- %% <code>Name</code> may be any atom or string that represents a
- %% lexically valid variable name, but <em>not</em> a single underscore
- %% character; cf. <code>underscore/0</code>.
- %%
- %% <p>Note: no checking is done whether the character sequence
- %% represents a proper variable name, i.e., whether or not its first
- %% character is an uppercase Erlang character, or whether it does not
- %% contain control characters, whitespace, etc.</p>
- %%
- %% @see variable_name/1
- %% @see variable_literal/1
- %% @see underscore/0
- %% type(Node) = variable
- %% data(Node) = atom()
- %%
- %% `erl_parse' representation:
- %%
- %% {var, Pos, Name}
- %%
- %% Name = atom() \ '_'
- variable(Name) when atom(Name) ->
- tree(variable, Name);
- variable(Name) ->
- tree(variable, list_to_atom(Name)).
- revert_variable(Node) ->
- Pos = get_pos(Node),
- Name = variable_name(Node),
- {var, Pos, Name}.
- %% =====================================================================
- %% @spec variable_name(syntaxTree()) -> atom()
- %%
- %% @doc Returns the name of a <code>variable</code> node as an atom.
- %%
- %% @see variable/1
- variable_name(Node) ->
- case unwrap(Node) of
- {var, _, Name} ->
- Name;
- Node1 ->
- data(Node1)
- end.
- %% =====================================================================
- %% @spec variable_literal(syntaxTree()) -> string()
- %%
- %% @doc Returns the name of a <code>variable</code> node as a string.
- %%
- %% @see variable/1
- variable_literal(Node) ->
- case unwrap(Node) of
- {var, _, Name} ->
- atom_to_list(Name);
- Node1 ->
- atom_to_list(data(Node1))
- end.
- %% =====================================================================
- %% @spec underscore() -> syntaxTree()
- %%
- %% @doc Creates an abstract universal pattern ("<code>_</code>"). The
- %% lexical representation is a single underscore character. Note that
- %% this is <em>not</em> a variable, lexically speaking.
- %%
- %% @see variable/1
- %% type(Node) = underscore
- %% data(Node) = []
- %%
- %% `erl_parse' representation:
- %%
- %% {var, Pos, '_'}
- underscore() ->
- tree(underscore, []).
- revert_underscore(Node) ->
- Pos = get_pos(Node),
- {var, Pos, '_'}.
- %% =====================================================================
- %% @spec integer(Value::integer()) -> syntaxTree()
- %%
- %% @doc Creates an abstract integer literal. The lexical representation
- %% is the canonical decimal numeral of <code>Value</code>.
- %%
- %% @see integer_value/1
- %% @see integer_literal/1
- %% @see is_integer/2
- %% type(Node) = integer
- %% data(Node) = integer()
- %%
- %% `erl_parse' representation:
- %%
- %% {integer, Pos, Value}
- %%
- %% Value = integer()
- integer(Value) ->
- tree(integer, Value).
- revert_integer(Node) ->
- Pos = get_pos(Node),
- {integer, Pos, integer_value(Node)}.
- %% =====================================================================
- %% @spec is_integer(Node::syntaxTree(), Value::integer()) -> bool()
- %%
- %% @doc Returns <code>true</code> if <code>Node</code> has type
- %% <code>integer</code> and represents <code>Value</code>, otherwise
- %% <code>false</code>.
- %%
- %% @see integer/1
- is_integer(Node, Value) ->
- case unwrap(Node) of
- {integer, _, Value} ->
- true;
- #tree{type = integer, data = Value} ->
- true;
- _ ->
- false
- end.
- %% =====================================================================
- %% @spec integer_value(syntaxTree()) -> integer()
- %%
- %% @doc Returns the value represented by an <code>integer</code> node.
- %%
- %% @see integer/1
- integer_value(Node) ->
- case unwrap(Node) of
- {integer, _, Value} ->
- Value;
- Node1 ->
- data(Node1)
- end.
- %% =====================================================================
- %% @spec integer_literal(syntaxTree()) -> string()
- %%
- %% @doc Returns the numeral string represented by an
- %% <code>integer</code> node.
- %%
- %% @see integer/1
- integer_literal(Node) ->
- integer_to_list(integer_value(Node)).
- %% =====================================================================
- %% @spec float(Value::float()) -> syntaxTree()
- %%
- %% @doc Creates an abstract floating-point literal. The lexical
- %% representation is the decimal floating-point numeral of
- %% <code>Value</code>.
- %%
- %% @see float_value/1
- %% @see float_literal/1
- %% type(Node) = float
- %% data(Node) = Value
- %%
- %% Value = float()
- %%
- %% `erl_parse' representation:
- %%
- %% {float, Pos, Value}
- %%
- %% Value = float()
- %% Note that under current versions of Erlang, the name `float/1' cannot
- %% be used for local calls (i.e., within the module) - it will be
- %% overridden by the type conversion BIF of the same name, so always use
- %% `make_float/1' for local calls.
- float(Value) ->
- make_float(Value).
- make_float(Value) ->
- tree(float, Value).
- revert_float(Node) ->
- Pos = get_pos(Node),
- {float, Pos, float_value(Node)}.
- %% =====================================================================
- %% @spec float_value(syntaxTree()) -> float()
- %%
- %% @doc Returns the value represented by a <code>float</code> node. Note
- %% that floating-point values should usually not be compared for
- %% equality.
- %%
- %% @see float/1
- float_value(Node) ->
- case unwrap(Node) of
- {float, _, Value} ->
- Value;
- Node1 ->
- data(Node1)
- end.
- %% =====================================================================
- %% @spec float_literal(syntaxTree()) -> string()
- %%
- %% @doc Returns the numeral string represented by a <code>float</code>
- %% node.
- %%
- %% @see float/1
- float_literal(Node) ->
- float_to_list(float_value(Node)).
- %% =====================================================================
- %% @spec char(Value::char()) -> syntaxTree()
- %%
- %% @doc Creates an abstract character literal. The result represents
- %% "<code>$<em>Name</em></code>", where <code>Name</code> corresponds to
- %% <code>Value</code>.
- %%
- %% <p>Note: the literal corresponding to a particular character value is
- %% not uniquely defined. E.g., the character "<code>a</code>" can be
- %% written both as "<code>$a</code>" and "<code>$\141</code>", and a Tab
- %% character can be written as "<code>$\11</code>", "<code>$\011</code>"
- %% or "<code>$\t</code>".</p>
- %%
- %% @see char_value/1
- %% @see char_literal/1
- %% @see is_char/2
- %% type(Node) = char
- %% data(Node) = char()
- %%
- %% `erl_parse' representation:
- %%
- %% {char, Pos, Code}
- %%
- %% Code = integer()
- char(Char) ->
- tree(char, Char).
- revert_char(Node) ->
- Pos = get_pos(Node),
- {char, Pos, char_value(Node)}.
- %% =====================================================================
- %% @spec is_char(Node::syntaxTree(), Value::char()) -> bool()
- %%
- %% @doc Returns <code>true</code> if <code>Node</code> has type
- %% <code>char</code> and represents <code>Value</code>, otherwise
- %% <code>false</code>.
- %%
- %% @see char/1
- is_char(Node, Value) ->
- case unwrap(Node) of
- {char, _, Value} ->
- true;
- #tree{type = char, data = Value} ->
- true;
- _ ->
- false
- end.
- %% =====================================================================
- %% @spec char_value(syntaxTree()) -> char()
- %%
- %% @doc Returns the value represented by a <code>char</code> node.
- %%
- %% @see char/1
- char_value(Node) ->
- case unwrap(Node) of
- {char, _, Char} ->
- Char;
- Node1 ->
- data(Node1)
- end.
- %% =====================================================================
- %% @spec char_literal(syntaxTree()) -> string()
- %%
- %% @doc Returns the literal string represented by a <code>char</code>
- %% node. This includes the leading "<code>$</code>" character.
- %%
- %% @see char/1
- char_literal(Node) ->
- io_lib:write_char(char_value(Node)).
- %% =====================================================================
- %% @spec string(Value::string()) -> syntaxTree()
- %%
- %% @doc Creates an abstract string literal. The result represents
- %% <code>"<em>Text</em>"</code> (including the surrounding
- %% double-quotes), where <code>Text</code> corresponds to the sequence
- %% of characters in <code>Value</code>, but not representing a
- %% <em>specific</em> string literal. E.g., the result of
- %% <code>string("x\ny")</code> represents any and all of
- %% <code>"x\ny"</code>, <code>"x\12y"</code>, <code>"x\012y"</code> and
- %% <code>"x\^Jy"</code>; cf. <code>char/1</code>.
- %%
- %% @see string_value/1
- %% @see string_literal/1
- %% @see is_string/2
- %% @see char/1
- %% type(Node) = string
- %% data(Node) = string()
- %%
- %% `erl_parse' representation:
- %%
- %% {string, Pos, Chars}
- %%
- %% Chars = string()
- string(String) ->
- tree(string, String).
- revert_string(Node) ->
- Pos = get_pos(Node),
- {string, Pos, string_value(Node)}.
- %% =====================================================================
- %% @spec is_string(Node::syntaxTree(), Value::string()) -> bool()
- %%
- %% @doc Returns <code>true</code> if <code>Node</code> has type
- %% <code>string</code> and represents <code>Value</code>, otherwise
- %% <code>false</code>.
- %%
- %% @see string/1
- is_string(Node, Value) ->
- case unwrap(Node) of
- {string, _, Value} ->
- true;
- #tree{type = string, data = Value} ->
- true;
- _ ->
- false
- end.
- %% =====================================================================
- %% @spec string_value(syntaxTree()) -> string()
- %%
- %% @doc Returns the value represented by a <code>string</code> node.
- %%
- %% @see string/1
- string_value(Node) ->
- case unwrap(Node) of
- {string, _, List} ->
- List;
- Node1 ->
- data(Node1)
- end.
- %% =====================================================================
- %% @spec string_literal(syntaxTree()) -> string()
- %%
- %% @doc Returns the literal string represented by a <code>string</code>
- %% node. This includes surrounding double-quote characters.
- %%
- %% @see string/1
- string_literal(Node) ->
- io_lib:write_string(string_value(Node)).
- %% =====================================================================
- %% @spec atom(Name) -> syntaxTre…
Large files files are truncated, but you can click here to view the full file