#[repr(u16)]pub enum SyntaxKind {
Show 132 variants
Whitespace = 0,
LineComment = 1,
BlockComment = 2,
Ident = 3,
IntLit = 4,
FloatLit = 5,
TextLit = 6,
InterpOpen = 7,
InterpMiddle = 8,
InterpClose = 9,
CharLit = 10,
BacktickTemplate = 11,
UnterminatedBacktickTemplate = 12,
KW_VAR = 13,
KW_FN = 14,
KW_IF = 15,
KW_ELSE = 16,
KW_WHILE = 17,
KW_FOR = 18,
KW_IN = 19,
KW_LOOP = 20,
KW_MATCH = 21,
KW_RETURN = 22,
KW_BREAK = 23,
KW_CONTINUE = 24,
KW_READ = 25,
KW_STRUCT = 26,
KW_ENUM = 27,
KW_TRUE = 28,
KW_FALSE = 29,
L_PAREN = 30,
R_PAREN = 31,
L_BRACE = 32,
R_BRACE = 33,
L_BRACK = 34,
R_BRACK = 35,
COMMA = 36,
DOT = 37,
DOT2 = 38,
DOT2EQ = 39,
COLON = 40,
SEMICOLON = 41,
THIN_ARROW = 42,
FAT_ARROW = 43,
HASH = 44,
PIPE = 45,
PIPE2 = 46,
AMP = 47,
AMP2 = 48,
UNDERSCORE = 49,
PLUS = 50,
MINUS = 51,
STAR = 52,
SLASH = 53,
PERCENT = 54,
PLUS_EQ = 55,
MINUS_EQ = 56,
STAR_EQ = 57,
SLASH_EQ = 58,
PERCENT_EQ = 59,
EQ2 = 60,
NEQ = 61,
LT = 62,
GT = 63,
LTEQ = 64,
GTEQ = 65,
EQ = 66,
BANG = 67,
QUESTION = 68,
EOF = 69,
ERROR = 70,
SOURCE_FILE = 71,
VAR_STMT = 72,
EXPR_STMT = 73,
ASSIGN_STMT = 74,
PLACE_ASSIGN_STMT = 75,
UPDATE_OP = 76,
BREAKPOINT = 77,
FN_ITEM = 78,
STRUCT_ITEM = 79,
ENUM_ITEM = 80,
ENUM_VARIANT = 81,
FIELD_LIST = 82,
FIELD = 83,
RECORD_LIT_EXPR = 84,
TUPLE_INDEX_EXPR = 85,
TYPE_ARG_LIST = 86,
INDEX_EXPR = 87,
FIELD_EXPR = 88,
MATCH_EXPR = 89,
CLOSURE_EXPR = 90,
MATCH_ARM = 91,
PATTERN = 92,
PATTERN_FIELD = 93,
PARAM = 94,
PARAM_LIST = 95,
BLOCK_EXPR = 96,
IF_EXPR = 97,
ELSE_BRANCH = 98,
WHILE_EXPR = 99,
FOR_EXPR = 100,
LOOP_EXPR = 101,
BREAK_EXPR = 102,
CONTINUE_EXPR = 103,
RETURN_EXPR = 104,
CALL_EXPR = 105,
METHOD_CALL_EXPR = 106,
ARG_LIST = 107,
PATH_EXPR = 108,
LITERAL = 109,
INTERP_EXPR = 110,
NAME_REF = 111,
BIN_EXPR = 112,
RANGE_EXPR = 113,
UNARY_EXPR = 114,
PAREN_EXPR = 115,
TUPLE_EXPR = 116,
LIST_EXPR = 117,
TYPE_REF = 118,
TUPLE_TYPE = 119,
FN_TYPE = 120,
PARSE_ERROR = 121,
READ_EXPR = 122,
PARSE_EXPR = 123,
PARSER_EXPR = 124,
PARSER_ATOM = 125,
PARSER_TEMPLATE = 126,
PARSER_CAPTURE = 127,
PARSER_CALL = 128,
PARSER_ARG_LIST = 129,
PARSER_NAMED_ARG = 130,
PARSER_KEYWORD_VALUE = 131,
}Expand description
Every lexical token, piece of trivia, and tree node in Praxis.
The ordering inside the enum is grouping-only (comments delimit the
sections) and carries no semantic meaning. The discriminants are stable
u16 values because rowan stores them as raw integers in the green tree.
Naming convention: keywords carry a KW_ prefix, punctuation a prefix
matching its role (L_/R_ for matching pairs), and tree nodes an _EXPR/
_STMT/_ITEM suffix. The screaming-snake names make lexical kinds visually
distinct from the CamelCase AST wrappers in praxis-ast, which is why we
relax the usual camel-case lint for this one enum.
Variants§
Whitespace = 0
A run of spaces, tabs, and newlines outside a comment.
LineComment = 1
A // line comment (not including the trailing newline).
BlockComment = 2
A nestable /* ... */ block comment, including delimiters.
Ident = 3
An identifier that is not a keyword.
IntLit = 4
An integer literal, e.g. 42.
FloatLit = 5
A floating-point literal, e.g. 3.14, 1e10, .5, 2. (§4.12).
A bare . is DOT; a float literal needs a digit on at least one side
of the dot, or an exponent. A . immediately followed by another . is
a range (.. / ..=), never part of a float.
TextLit = 6
A double-quoted text literal with no interpolation holes, e.g.
"hello" — the whole literal, quotes included.
A literal that holds a { is not this kind: it is an
InterpOpen / InterpMiddle /
InterpClose run with the holes’ ordinary tokens
between the fragments (§8.1, ADR-147). An unterminated literal is this
kind either way, holes or not: the lexer only splits a literal it has
already proved closes on its line, so T004 reports the whole run as one
token.
InterpOpen = 7
The first fragment of an interpolated text literal: the opening ", the
literal text before the first hole, and the { that opens it — e.g.
"Part 2: { (§8.1, ADR-147).
The delimiters are inside the token, one byte at each end, so the three
fragment kinds decode identically (&text[1..len-1] through
praxis_syntax::literal::decode_text_body) and the token stream still
tiles the source (ADR-003).
The fragments are separate tokens rather than one opaque literal because
a name inside a hole has to be a token at its own range in the
lossless tree: that is the only way praxis-hir’s capture analysis,
which looks token ranges up in the resolver’s map, sees it. A closure
body of "{outer}" would otherwise capture nothing and read a slot
nothing filled (ADR-147 decision 1).
InterpMiddle = 8
A fragment between two holes: the } closing one, the literal text, and
the { opening the next — e.g. } and {. Empty text is ordinary
("{a}{b}" has the two-byte fragment }{).
InterpClose = 9
The last fragment: the } closing the final hole, the trailing literal
text, and the closing " — e.g. }!".
CharLit = 10
A single-quoted character literal, e.g. '#' (ADR-141).
Exactly one Unicode scalar, and the lexer is where that is decided:
'' and 'ab' are T007, not a silently truncated Char. Its escapes
are the text literal’s — \n \r \t \0 \\ \" — plus \', and there are
no \x/\u{…} forms, because two escape tables for one language is the
drift praxis_syntax::literal’s module doc was written to forbid.
This kind means the literal closed. An unterminated run is still
pushed as a CharLit (losslessness, ADR-003) after a T006, so a
consumer must ask [praxis_syntax::literal::decode_char_literal] rather
than assume; there is no second kind here the way there is for a
template, because a ' cannot open a sublanguage nobody scanned.
BacktickTemplate = 11
A backtick-delimited parser template, e.g. `{x:int}`. The whole
template is one token; its interior is re-scanned by the input-parser
lexer (§7).
This kind means the template closed. A run that did not is
SyntaxKind::UnterminatedBacktickTemplate, so a BacktickTemplate’s
text is a complete template by construction and no consumer has to
re-derive that (ADR-094).
UnterminatedBacktickTemplate = 12
A backtick run that did not close before its line ended (ADR-094).
Two kinds rather than one predicate, because “is this token terminated”
must not be re-derived by each consumer. A template ends at its line, so
the common unterminated token is `{int`: a hand-rolled
strip_prefix('‘).and_then(strip_suffix(’')) succeeds on it, the
interior scanner is handed {int, and I030 comes back describing an
interior nobody wrote — the fabricated-interior class that
an_unterminated_template_does_not_also_report_a_fabricated_interior
exists to forbid.
So the state is made unrepresentable instead: the lexer decides once,
and a consumer that receives this kind knows there is nothing to scan.
It also means such a token can be typed with a fresh variable rather than
drawing Y023 (“write read before it”) — advice that cannot close a
template.
KW_VAR = 13
KW_FN = 14
KW_IF = 15
KW_ELSE = 16
KW_WHILE = 17
KW_FOR = 18
KW_IN = 19
KW_LOOP = 20
KW_MATCH = 21
KW_RETURN = 22
KW_BREAK = 23
KW_CONTINUE = 24
KW_READ = 25
KW_STRUCT = 26
KW_ENUM = 27
KW_TRUE = 28
KW_FALSE = 29
L_PAREN = 30
(
R_PAREN = 31
)
L_BRACE = 32
{
R_BRACE = 33
}
L_BRACK = 34
[
R_BRACK = 35
]
COMMA = 36
,
DOT = 37
.
DOT2 = 38
..
DOT2EQ = 39
..=
COLON = 40
:
SEMICOLON = 41
;
THIN_ARROW = 42
->
FAT_ARROW = 43
=>
HASH = 44
#
PIPE = 45
|
PIPE2 = 46
||
AMP = 47
&
AMP2 = 48
&& — logical and. The lexer’s max-munch keeps it one token, as it does
||, so a bare AMP is never part of one.
UNDERSCORE = 49
_ — a lone underscore (placeholder/punning site).
PLUS = 50
+
MINUS = 51
-
STAR = 52
*
SLASH = 53
/
PERCENT = 54
%
PLUS_EQ = 55
+=
MINUS_EQ = 56
-=
STAR_EQ = 57
*=
SLASH_EQ = 58
/=
PERCENT_EQ = 59
%=
EQ2 = 60
==
NEQ = 61
!=
LT = 62
<
GT = 63
>
LTEQ = 64
<=
GTEQ = 65
>=
EQ = 66
= (assignment / binding).
BANG = 67
! (logical not).
QUESTION = 68
? (reserved for later use).
EOF = 69
End of input. Emitted as the final token so the parser can treat EOF uniformly.
ERROR = 70
A byte the lexer does not recognize. The lexer also emits a real
diagnostic (T003) for it rather than silently dropping it.
SOURCE_FILE = 71
The root node of a parsed file.
VAR_STMT = 72
A var name = expr binding — the language’s one binding form (ADR-125).
EXPR_STMT = 73
A bare expression used as a statement.
ASSIGN_STMT = 74
A reassignment statement: name = expr or name += expr etc. (§4.2).
PLACE_ASSIGN_STMT = 75
A reassignment through a place expression: m[key] = expr,
counts[key] += 1 (§6.2).
Its own kind rather than an ASSIGN_STMT with an expression target: an
ASSIGN_STMT’s target is a token and its single expression child is the
value, so a target that is itself an expression cannot be told from the
value. The target here is the first expression child and the value the
second.
UPDATE_OP = 76
The two-token min= / max= operator of an updating store (§6.2): an
Ident spelling min or max, immediately followed by =.
A node rather than a token because min is an identifier — the lexer
cannot claim it without taking min away from every program that names
the prelude helper — so the operator is decided contextually, at the one
position where an identifier cannot otherwise appear. Wrapping the pair
keeps the = from being a direct child of the statement, where a walk
looking for the assignment operator would read the update as a plain
store.
BREAKPOINT = 77
The two-token :bp marker a statement may end with (§9.8): a COLON
immediately followed by an Ident spelling bp.
A node rather than a token for UPDATE_OP’s reason,
and the same reason it is decided by position instead of by the lexer:
bp is an identifier everywhere else, and a lexer rule claiming :bp
would take bp away from every program that annotates a binding with a
type whose name begins that way. The one place an identifier cannot
otherwise follow a : is the end of a statement, which is exactly where
this is admitted. Wrapping the pair keeps the : from being a direct
child of the statement, where a walk looking for a type annotation would
find it.
FN_ITEM = 78
A top-level or nested fn declaration.
STRUCT_ITEM = 79
A struct Name { field: Type, … } declaration (§4.5).
ENUM_ITEM = 80
An enum Name { Variant, Variant(Type), … } declaration (§4.6).
ENUM_VARIANT = 81
One variant of an enum: Name or Name(Type, …).
FIELD_LIST = 82
The { field: Type, … } body of a struct declaration.
FIELD = 83
A single name: Type field of a struct.
RECORD_LIT_EXPR = 84
A Name { field: expr, … } record-literal expression (§4.5).
TUPLE_INDEX_EXPR = 85
A receiver.0 tuple-element expression (§4.4).
Its own kind rather than a FIELD_EXPR holding an IntLit: an element is
selected by position and the index must be a literal, where a field is
selected by name — two different operations that lower to two different
runtime calls.
TYPE_ARG_LIST = 86
The [Type, …] type-argument list of a constructor call (§3.3):
the brackets in Counter[(Int, Int)]().
Its own kind rather than an INDEX_EXPR holding types: the brackets in
Counter[(Int, Int)]() and in m[key] are the same two characters and
two different operations, and only the name in front tells them apart
(Int is a legal expression too, so the contents cannot).
INDEX_EXPR = 87
A receiver[index] subscript expression (§4.7/§6.2/§6.4).
The index list is an ARG_LIST, because §6.4’s grid[x, y] makes a
subscript variadic: the arity is part of what selects the operation, the
same way a method call’s is.
FIELD_EXPR = 88
A receiver.field field-access expression (§4.5).
MATCH_EXPR = 89
A match scrutinee { pattern => expr, … } expression (§4.6/§4.11).
CLOSURE_EXPR = 90
A closure expression |params| expr (§4.10). Bare PIPE claims the
| (lexer max-munch keeps || as logical-or PIPE2).
MATCH_ARM = 91
One pattern => expr arm of a match expression.
PATTERN = 92
A pattern (§4.6): wildcard _, literal, variable bind, enum variant,
or tuple/record destructuring.
PATTERN_FIELD = 93
One name or name: pattern field of a record pattern (§4.5).
Its own kind rather than the FIELD a struct declaration
and a record literal share: those hold a type and an expression, and this
holds a pattern. A punned P { x } and an explicit P { x: p } are
then one node shape — the name is always the token, the sub-pattern is
always the optional child — so pairing a field with its pattern never has
to count identifiers.
PARAM = 94
A single name: Type parameter.
PARAM_LIST = 95
The (...) parameter list.
BLOCK_EXPR = 96
A { ... } block expression.
IF_EXPR = 97
An if cond { ... } else { ... } expression.
ELSE_BRANCH = 98
The else arm (block or else if).
WHILE_EXPR = 99
A while cond { ... } expression.
FOR_EXPR = 100
A for pat in iter { ... } expression (§4.11).
LOOP_EXPR = 101
A loop { ... } expression (§4.11).
BREAK_EXPR = 102
A break [expr] expression (§4.11).
CONTINUE_EXPR = 103
A continue expression (§4.11).
RETURN_EXPR = 104
A return [expr] expression (§4.11).
CALL_EXPR = 105
A callee(args) call expression (covers out(...)).
METHOD_CALL_EXPR = 106
A receiver.method(args) method-call expression (§16.2).
ARG_LIST = 107
The (arg, arg, ...) argument list of a call.
PATH_EXPR = 108
A path: an identifier or a dotted name.
LITERAL = 109
A literal value
(IntLit/FloatLit/TextLit/CharLit/true/false/backtick
template).
INTERP_EXPR = 110
An interpolated text literal: "a{x}b" (§8.1, ADR-147).
Its children alternate — InterpOpen, an expression,
then zero or more InterpMiddle/expression pairs,
then InterpClose — and the expressions are
ordinary expression subtrees, not a sublanguage.
Its own kind rather than a LITERAL with children,
because it is not one: a LITERAL is a leaf whose value the lowerer
reads off a token, and every walk in the workspace that finds names,
resolves them, renames them or captures them has to descend into a hole.
Giving LITERAL children would have made “does this node contain a name”
a question with two answers.
NAME_REF = 111
A reference to a name (identifier used as a value).
BIN_EXPR = 112
A binary operator expression, e.g. a + b.
RANGE_EXPR = 113
A range expression: a..b (half-open) or a..=b (inclusive) — §4.11,
ADR-059. Its own node kind rather than a BIN_EXPR:
a range is not an operator applied to two numbers, it is a collection
built from two bounds, and every consumer that asks “what binary
operator is this” would otherwise have to answer “none of them”.
UNARY_EXPR = 114
A unary operator expression, e.g. -x.
PAREN_EXPR = 115
A parenthesized expression ( expr ).
TUPLE_EXPR = 116
A tuple expression ( e1, e2, … ) with two or more elements. A
single parenthesized value is PAREN_EXPR, not this.
LIST_EXPR = 117
A list expression [ e1, e2, … ] — a Vec literal (§6.1).
Its own kind rather than an INDEX_EXPR with no
receiver: the brackets in [1, 2] and in m[k] are the same two
characters and two different operations, and what tells them apart is
position — a subscript continues an expression, a list begins one.
That is the rule TYPE_ARG_LIST is decided by, and
the rule that decides the ( too.
TYPE_REF = 118
A type written in source: a scalar or grouped type name (Int, Text, …),
with or without a bracketed type-argument list (§4.4). Tuple and
function types carry their own kinds.
TUPLE_TYPE = 119
A tuple type (T, U, …). A parenthesized single type (T) is just T,
so this always carries two or more elements.
FN_TYPE = 120
A function type (P0, P1, …) -> R.
PARSE_ERROR = 121
A parse-error placeholder node wrapping tokens the parser could not place. Recovery (§15.2) emits these so the tree stays well-formed.
READ_EXPR = 122
read parser_expression — a prefix expression applying a parser to the
whole process-input buffer (§7.1).
PARSE_EXPR = 123
parse(text, parser_expression) — apply a parser to an existing Text
value (§7.1).
PARSER_EXPR = 124
A parser expression (§7 EBNF): an atomic, a template, or a constructor
call. The body of read and the second arg of parse.
PARSER_ATOM = 125
An atomic parser name: int, char, word, etc. (§7.4).
PARSER_TEMPLATE = 126
A backtick template `{x:int},{y:int}` inside a parser expression
(§7.2). Its children are the scanned template parts.
PARSER_CAPTURE = 127
A {name:parser} or {parser} capture inside a template (§7.3).
PARSER_CALL = 128
A constructor call lines(P), csv(P), sep(sep, P), etc. (§7.5).
PARSER_ARG_LIST = 129
The (arg, arg, ...) argument list of a parser constructor call.
PARSER_NAMED_ARG = 130
A named argument inside a parser constructor call (§7.5):
name: parser_expr, e.g. rules: lines(int) in heterogeneous
sections, or skip: whitespace in chars. Holds the name ident, the
:, and the parser-expr value.
PARSER_KEYWORD_VALUE = 131
The literal value of a keyword argument inside a parser constructor
call: the 0 of grid(char, ragged, fill: 0) or the "-" of
fill: "-" (§7.5).
Its own kind because a keyword argument’s value is not a parser
expression and cannot be parsed as one: handing it to parse_parser_expr
reports P001 expected a parser expression and leaves a PARSE_ERROR
with no literal for the HIR bridge to read, so §7.5’s own documented
spelling would build a ragged grid padded with "" instead of 0.
Implementations§
Source§impl SyntaxKind
impl SyntaxKind
Sourcepub fn is_trivia(self) -> bool
pub fn is_trivia(self) -> bool
Whether this kind is trivia: whitespace or a comment. Trivia is kept in the lossless tree (§13.1) but skipped for parsing decisions.
Sourcepub fn is_keyword(self) -> bool
pub fn is_keyword(self) -> bool
Whether this kind is a keyword token.
Derived from SyntaxKind::keyword_text rather than maintained as a
second list, so a kind cannot be a keyword in one table and not in the
other.
Sourcepub fn all_keyword_texts() -> Vec<&'static str>
pub fn all_keyword_texts() -> Vec<&'static str>
Every keyword’s source spelling, in discriminant order.
Swept, not listed. The whole kind space is walked and filtered by
is_keyword, so a keyword added to
keyword_text joins this by construction.
The TextMate grammar is tested against this: the editor’s keyword pattern is a copy of the lexer’s table that no compiler checks, and the failure — a word quietly stopping being coloured — is one nobody files.
Sourcepub fn is_type_node(self) -> bool
pub fn is_type_node(self) -> bool
Whether this kind is one of the three shapes a written type annotation can take: a name (with or without bracketed arguments), a tuple, or a function type.
The set lives here, once, because everything that looks at an annotation
needs the same answer: praxis_ast::TypeRef::cast accepts exactly these
kinds, and type resolution recurses through exactly these children. A
site that spelled the list out for itself and listed only TYPE_REF
would silently drop every direct tuple and function annotation.
Sourcepub fn is_literal_token(self) -> bool
pub fn is_literal_token(self) -> bool
Whether this kind is a token the parser wraps in a
LITERAL node: the four scalar literals, true/false,
and both backtick-template kinds.
Here for is_type_node’s reason: the parser writes
this set when it builds the node and praxis_ast::Literal::token reads
it back. Two copies drift, and a reader missing a kind answers None for
a LITERAL the parser really did build, dropping every HIR pass into its
“no token at all” branch.
Both template kinds are in. A template in value position has no
meaning — §7.1 enters the parser sublanguage at read/parse and nowhere
else — and is reported as Y023, but it is reported about the token,
and an accessor that cannot see the token cannot report on it. The
unterminated one draws no Y023, since that advice cannot close a
template (ADR-094); it types as a fresh variable, which is exactly what
the missing-token branch happened to produce.
true/false are literals too, and take the same parse arm: an arm of
their own that did not eat leading trivia first would make true span
" true" where 1 spans "1".
Sourcepub fn is_pattern_literal(self) -> bool
pub fn is_pattern_literal(self) -> bool
Whether this kind is a literal a pattern may test against (§4.6): an
integer, text, a character, true or false.
Strictly narrower than is_literal_token, and
the difference is that a pattern tests a constant. There is no float
pattern (§4.6), and a backtick template is not a constant either — nor is
an interpolated literal, which the parser refuses in pattern position
outright (ADR-147): match s { "{x}" => … } would otherwise leave a
pattern whose only direct Ident is the hole’s x, read as a variable
bind, and swallow every value.
CharLit is in the set (ADR-141). A caller’s copy of this list that
omitted it would stop a match arm list after '#' => …, dropping every
arm below it from the tree with no diagnostic at all.
Sourcepub const fn from_raw_u16(raw: u16) -> SyntaxKind
pub const fn from_raw_u16(raw: u16) -> SyntaxKind
Total conversion from a raw u16. Out-of-range values become
SyntaxKind::ERROR — the safe rowan Language boundary must never
construct an invalid enum discriminant, whatever the input.
Sourcepub fn is_token(self) -> bool
pub fn is_token(self) -> bool
Whether this kind is a leaf token (emitted by the lexer), as opposed to trivia or an interior tree node.
Sourcepub fn is_node(self) -> bool
pub fn is_node(self) -> bool
Whether this kind is an interior tree node (produced by the parser).
Sourcepub fn from_keyword(text: &str) -> Option<SyntaxKind>
pub fn from_keyword(text: &str) -> Option<SyntaxKind>
Look up the keyword kind for an identifier’s text, or None if it is a
plain identifier. Used by the lexer to split keywords out of the ident
run via a single table.
Sourcepub fn keyword_text(self) -> Option<&'static str>
pub fn keyword_text(self) -> Option<&'static str>
The source spelling of a keyword, or None for non-keywords. The
inverse of [from_keyword]; handy for diagnostics and completion, which
have to spell a keyword back out.
Trait Implementations§
Source§impl Clone for SyntaxKind
impl Clone for SyntaxKind
Source§fn clone(&self) -> SyntaxKind
fn clone(&self) -> SyntaxKind
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more