syntax/tree.bend checks
raw source on the hub · import 0x729eecea86ea5a2cdba3a2856a313bca/syntax/tree.bend as Tree
syntax/tree: a source as a concrete syntax tree over its significant tokens:
statements by line and indentation, groups by brackets. Built by one stack
machine over the token list, so a half-written file still yields a tree:
- a bracket that never closes is closed by the next line at column 0
(so damage stays inside one item), or by the end of the file;
- a close bracket that matches nothing on the stack is a stray leaf;
- < opens type arguments only when glued to a name (List<, Maybe<&);
a >-only operator closes as many angle groups as it has >s.
Trivia (spaces, newlines, comments) is not in the tree: read the tokens for
that. The cells (NNil, NCons) live inside the type, as json/value does, so
every walk is a structural recursion on one argument.
3 imports
import Base import ../lazy/lazy.bend as Lazy import ./lex.bend as Lex
Types
type StmtKind source · line 20 · raw
Data
what a statement is, by its shape: SDef def f(..) (also @unsafe def),
SType, SLaw, SImport, SCase case p:, SFor for x: T / exs x: T, SLet
(a = or <- among its own tokens), else STerm (match x:, do M<T>:,
return e, a call)
SDefStmtKind
STypeStmtKind
SLawStmtKind
SImportStmtKind
SCaseStmtKind
SForStmtKind
SLetStmtKind
STermStmtKind
type Node source · line 33 · raw
Data
a leaf holds one token; a group its bracket, what is inside, and its close (None when it never closed); a statement its own tokens and the statements under it; NNil and NCons chain nodes
Leaf@tok:0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok -> Node
Group@open:0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok -> @kids:Node -> @close:Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok> -> Node
Stmt@kind:StmtKind -> @kids:Node -> @body:Node -> Node
NNilNode
NCons@head:Node -> @tail:Node -> Node
type Frame source · line 168 · raw
Data
an open group (its kids reversed), or an open statement (its kids and the finished statements under it, both reversed); the root holds the items
FGroup@open:0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok -> @kids:Node -> Frame
FStmt@indent:U32 -> @kids:Node -> @body:Node -> Frame
FRoot@body:Node -> Frame
type B source · line 174 · raw
Data
fresh: the next significant token starts a line
B@fresh:Bool -> @stack:List<&2, Frame> -> B
Definitions
def reverse source · line 44 · raw
@cells:Node -> @acc:Node -> Node
a chain, reversed onto acc
def to_list source · line 52 · raw
@cells:Node -> List<&2, Node>
a chain as a list
def of_list source · line 60 · raw
@ns:List<&2, Node> -> Node
a list as a chain
def first source · line 68 · raw
@n:Node -> Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok>
the token a leaf holds; a group's open, a statement's first token
def text.of source · line 81 · raw
@m:Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok> -> String
def text source · line 89 · raw
@n:Node -> String
the text of a node's first token ("" for none)
def line.of source · line 92 · raw
@m:Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok> -> U32
def line source · line 100 · raw
@n:Node -> U32
the line of a node's first token (0 for none)
def col.of source · line 103 · raw
@m:Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok> -> U32
def col source · line 111 · raw
@n:Node -> U32
the column of a node's first token (0 for none)
def is_leaf source · line 115 · raw
@n:Node -> Bool
is it a single token?
def is_text source · line 123 · raw
@n:Node -> @+s:String -> Bool
is it the leaf with this text?
def opens source · line 131 · raw
@n:Node -> @+s:String -> Bool
is it a group opened by this bracket?
def leaf_close source · line 139 · raw
@close:Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok> -> @acc:List<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok> -> List<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok>
the leaves of a tree, in order: the significant tokens
def leaves.go source · line 146 · raw
@n:Node -> @acc:List<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok> -> List<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok>
def leaves source · line 160 · raw
@n:Node -> List<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok>
the leaves of a tree, in order: the significant tokens when the tree is faithful
def closer source · line 178 · raw
@+o:String -> String
the bracket that closes an opener (> for < and <&)
def all_gt source · line 184 · raw
@cs:List<&2, Char> -> Bool
is every char a >?
def closes_with source · line 192 · raw
@k:0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.TokKind -> @+t:String -> Bool
a token that closes a group: ), ], } or a run of >
def opens_angle source · line 202 · raw
@k:0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.TokKind -> @+t:String -> @glued:Bool -> Bool
< or <& right after a name opens type arguments
def put source · line 210 · raw
@stack:List<&2, Frame> -> @n:Node -> List<&2, Frame>
a finished node lands in the frame below
def close_one source · line 222 · raw
@stack:List<&2, Frame> -> @close:Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok> -> List<&2, Frame>
the innermost open group, closed by close (None: never closed)
def depth_to source · line 231 · raw
@stack:List<&2, Frame> -> @+c:String -> Nat
how many groups sit open above the one that c closes (counting it); 0 when none does
def groups source · line 243 · raw
@stack:List<&2, Frame> -> Nat
how many groups sit open on top of the stack
def close_n source · line 251 · raw
@n:Nat -> @stack:List<&2, Frame> -> @close:Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok> -> List<&2, Frame>
n groups close, innermost first; only the last gets the close token
def close_all source · line 261 · raw
@+stack:List<&2, Frame> -> List<&2, Frame>
every open group closes, unclosed
def close_tok source · line 265 · raw
@+stack:List<&2, Frame> -> @+close:0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok -> List<&2, Frame>
a close bracket: to its match if it has one, else a stray leaf
def close_gts source · line 271 · raw
@cs:List<&2, Char> -> @stack:List<&2, Frame> -> @+l:U32 -> @+c:U32 -> List<&2, Frame>
>> closes two angle groups
def close_any.at source · line 280 · raw
@+gt:Bool -> @+stack:List<&2, Frame> -> @+close:0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok -> @+t:String -> @+l:U32 -> @+c:U32 -> List<&2, Frame>
the close a bracket makes, given whether it is a run of >: a match, so
only the side taken runs
def close_any source · line 289 · raw
@+stack:List<&2, Frame> -> @+close:0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok -> List<&2, Frame>
a close bracket, or a run of >, closes what it can
def put_stmt source · line 294 · raw
@stack:List<&2, Frame> -> @n:Node -> List<&2, Frame>
a finished statement lands in the body of the frame below
def binds_in source · line 304 · raw
@kids:Node -> Bool
a = or <- among a statement's own tokens
def keyword_kind source · line 316 · raw
@+t:String -> StmtKind
the kind of a statement led by this keyword
def classify source · line 325 · raw
@kids:Node -> StmtKind
a statement's kind from its own tokens
def end_stmt source · line 335 · raw
@stack:List<&2, Frame> -> List<&2, Frame>
the innermost open statement is finished and lands in its parent
def end_n source · line 344 · raw
@n:Nat -> @stack:List<&2, Frame> -> List<&2, Frame>
n statements finish, innermost first
def deeper source · line 352 · raw
@stack:List<&2, Frame> -> @+col:U32 -> Nat
the statements a line at column col ends: those not shallower than it
def stmts source · line 361 · raw
@stack:List<&2, Frame> -> Nat
how many statements sit open on the stack
def in_group source · line 369 · raw
@stack:List<&2, Frame> -> Bool
is the innermost frame an open group?
def open_stmt source · line 378 · raw
@+stack:List<&2, Frame> -> @+c:U32 -> List<&2, Frame>
a new statement at column c, once the ones it ends are finished; inside a group a line is just more tokens
def fresh source · line 385 · raw
@+stack:List<&2, Frame> -> @+tok:0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok -> List<&2, Frame>
a significant token that starts a line: at column 0 it closes every open group (unless it is a bracket closing one of them); outside a group it opens a statement
def push source · line 391 · raw
@+stack:List<&2, Frame> -> @+tok:0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok -> @glued:Bool -> List<&2, Frame>
an open bracket or a leaf into the innermost frame
def step source · line 399 · raw
@+tok:0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok -> @st:B -> @glued:Bool -> B
glued: the previous token was a name with nothing between
def is_name_tok source · line 406 · raw
@tok:0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok -> Bool
an identifier of any kind (what < glues to)
def run source · line 411 · raw
@toks:List<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok> -> @st:B -> @glued:Bool -> B
every token, in order
def root source · line 420 · raw
@stack:List<&2, Frame> -> Node
the items gathered in the root frame
def finish source · line 428 · raw
@st:B -> Node
the tree once the tokens are over: every group and statement closes
def of_tokens source · line 434 · raw
@toks:List<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok> -> Node
the items of a source: a chain of statements
def parse source · line 438 · raw
@source:String -> Node
the items of a source: a chain of statements
def show_close source · line 445 · raw
@close:Maybe<&2, 0x729eecea86ea5a2cdba3a2856a313bca/syntax/lex.Tok> -> String
a group's close bracket, .. when it never closed
def show source · line 455 · raw
@n:Node -> String
[def f (x : U32) -> U32 : {[match x {[case A {} : {[1]}]}]}]: a statement
in brackets, its body in braces, a group as its brackets (an unclosed one
ends in ..)