Skip to content

Commit cf2fa48

Browse files
authored
Add a pile of documentation for expression predicates (#471)
1 parent 3dbcd32 commit cf2fa48

File tree

2 files changed

+137
-13
lines changed

2 files changed

+137
-13
lines changed

docs/src/api.md

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,62 @@ JuliaSyntax.SourceFile
6363
JuliaSyntax.source_line_range
6464
```
6565

66-
## Expression heads/kinds
66+
## Expression predicates, kinds and flags
67+
68+
Expressions are tagged with a kind - like a type, but represented as an integer
69+
tag rather than a full Julia type for efficiency. (Very like the tag of a "sum
70+
type".) `Kind`s are constructed with the `@K_str` macro.
6771

6872
```@docs
69-
JuliaSyntax.Kind
70-
JuliaSyntax.SyntaxHead
7173
JuliaSyntax.@K_str
74+
JuliaSyntax.Kind
75+
```
76+
77+
The kind of an expression `ex` in a tree should be accessed with `kind(ex)`
78+
79+
```@docs
7280
JuliaSyntax.kind
73-
JuliaSyntax.head
81+
```
82+
83+
In addition to the `kind`, a small integer set of "flags" is included to
84+
further distinguish details of each expresssion, accessed with the `flags`
85+
function. The kind and flags can be wrapped into a `SyntaxHead` which is
86+
accessed with the `head` function.
87+
88+
```@docs
7489
JuliaSyntax.flags
90+
JuliaSyntax.SyntaxHead
91+
JuliaSyntax.head
7592
```
7693

77-
see also predicates related to `flags`.
94+
Details about the flags may be extracted using various predicates:
95+
96+
```@docs
97+
JuliaSyntax.is_trivia
98+
JuliaSyntax.is_prefix_call
99+
JuliaSyntax.is_infix_op_call
100+
JuliaSyntax.is_prefix_op_call
101+
JuliaSyntax.is_postfix_op_call
102+
JuliaSyntax.is_dotted
103+
JuliaSyntax.is_suffixed
104+
JuliaSyntax.is_decorated
105+
JuliaSyntax.numeric_flags
106+
```
107+
108+
Some of the more unusual predicates are accessed merely with `has_flags(x,
109+
flag_bits)`, where any of the following uppercase constants may be used for
110+
`flag_bits` after checking that the `kind` is correct.
111+
112+
```@docs
113+
JuliaSyntax.has_flags
114+
JuliaSyntax.TRIPLE_STRING_FLAG
115+
JuliaSyntax.RAW_STRING_FLAG
116+
JuliaSyntax.PARENS_FLAG
117+
JuliaSyntax.COLON_QUOTE
118+
JuliaSyntax.TOPLEVEL_SEMICOLONS_FLAG
119+
JuliaSyntax.MUTABLE_FLAG
120+
JuliaSyntax.BARE_MODULE_FLAG
121+
```
78122

79123
## Syntax trees
80124

src/parse_stream.jl

Lines changed: 88 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,43 @@ const POSTFIX_OP_FLAG = RawFlags(3<<3)
2424

2525
# The following flags are quite head-specific and may overlap
2626

27-
# Set when K"string" or K"cmdstring" was triple-delimited as with """ or ```
27+
"""
28+
Set when K"string" or K"cmdstring" was triple-delimited as with \"\"\" or ```
29+
"""
2830
const TRIPLE_STRING_FLAG = RawFlags(1<<5)
29-
# Set when a K"string", K"cmdstring" or K"Identifier" needs raw string unescaping
31+
32+
"""
33+
Set when a K"string", K"cmdstring" or K"Identifier" needs raw string unescaping
34+
"""
3035
const RAW_STRING_FLAG = RawFlags(1<<6)
3136

32-
# Set for K"tuple", K"block" or K"macrocall" which are delimited by parentheses
37+
"""
38+
Set for K"tuple", K"block" or K"macrocall" which are delimited by parentheses
39+
"""
3340
const PARENS_FLAG = RawFlags(1<<5)
34-
# Set for K"quote" for the short form `:x` as oppsed to long form `quote x end`
41+
42+
"""
43+
Set for K"quote" for the short form `:x` as oppsed to long form `quote x end`
44+
"""
3545
const COLON_QUOTE = RawFlags(1<<5)
36-
# Set for K"toplevel" which is delimited by parentheses
46+
47+
"""
48+
Set for K"toplevel" which is delimited by parentheses
49+
"""
3750
const TOPLEVEL_SEMICOLONS_FLAG = RawFlags(1<<5)
3851

39-
# Set for K"struct" when mutable
52+
"""
53+
Set for K"struct" when mutable
54+
"""
4055
const MUTABLE_FLAG = RawFlags(1<<5)
4156

42-
# Set for K"module" when it's not bare (`module`, not `baremodule`)
57+
"""
58+
Set for K"module" when it's not bare (`module`, not `baremodule`)
59+
"""
4360
const BARE_MODULE_FLAG = RawFlags(1<<5)
4461

4562
# Flags holding the dimension of an nrow or other UInt8 not held in the source
63+
# TODO: Given this is only used for nrow/ncat, we could actually use all the flags?
4664
const NUMERIC_FLAGS = RawFlags(RawFlags(0xff)<<8)
4765

4866
function set_numeric_flags(n::Integer)
@@ -65,7 +83,11 @@ function remove_flags(n::RawFlags, fs...)
6583
RawFlags(n & ~(RawFlags((|)(fs...))))
6684
end
6785

68-
# Return true if any of `test_flags` are set
86+
"""
87+
has_flags(x, test_flags)
88+
89+
Return true if any of `test_flags` are set.
90+
"""
6991
has_flags(flags::RawFlags, test_flags) = (flags & test_flags) != 0
7092

7193
#-------------------------------------------------------------------------------
@@ -145,14 +167,72 @@ flags(x) = flags(head(x))
145167
has_flags(x, test_flags) = has_flags(flags(x), test_flags)
146168
call_type_flags(x) = call_type_flags(flags(x))
147169

170+
"""
171+
is_trivia(x)
172+
173+
Return true for "syntax trivia": tokens in the tree which are either largely
174+
invisible to the parser (eg, whitespace) or implied by the structure of the AST
175+
(eg, reserved words).
176+
"""
148177
is_trivia(x) = has_flags(x, TRIVIA_FLAG)
178+
179+
"""
180+
is_prefix_call(x)
181+
182+
Return true for normal prefix function call syntax such as the `f` call node
183+
parsed from `f(x)`.
184+
"""
149185
is_prefix_call(x) = call_type_flags(x) == PREFIX_CALL_FLAG
186+
187+
"""
188+
is_infix_op_call(x)
189+
190+
Return true for infix operator calls such as the `+` call node parsed from
191+
`x + y`.
192+
"""
150193
is_infix_op_call(x) = call_type_flags(x) == INFIX_FLAG
194+
195+
"""
196+
is_prefix_op_call(x)
197+
198+
Return true for prefix operator calls such as the `+` call node parsed from `+x`.
199+
"""
151200
is_prefix_op_call(x) = call_type_flags(x) == PREFIX_OP_FLAG
201+
202+
"""
203+
is_postfix_op_call(x)
204+
205+
Return true for postfix operator calls such as the `'ᵀ` call node parsed from `x'ᵀ`.
206+
"""
152207
is_postfix_op_call(x) = call_type_flags(x) == POSTFIX_OP_FLAG
208+
209+
"""
210+
is_dotted(x)
211+
212+
Return true for dotted syntax tokens
213+
"""
153214
is_dotted(x) = has_flags(x, DOTOP_FLAG)
215+
216+
"""
217+
is_suffixed(x)
218+
219+
Return true for operators which have sufficies, such as `+₁`
220+
"""
154221
is_suffixed(x) = has_flags(x, SUFFIXED_FLAG)
222+
223+
"""
224+
is_decorated(x)
225+
226+
Return true for operators which are decorated with a dot or suffix.
227+
"""
155228
is_decorated(x) = is_dotted(x) || is_suffixed(x)
229+
230+
"""
231+
numeric_flags(x)
232+
233+
Return the number attached to a `SyntaxHead`. This is only for kinds `K"nrow"`
234+
and `K"ncat"`, for now.
235+
"""
156236
numeric_flags(x) = numeric_flags(flags(x))
157237

158238
#-------------------------------------------------------------------------------

0 commit comments

Comments
 (0)