~/bend-docscommunity

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)

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

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

type B source · line 174 · raw

Data

fresh: the next significant token starts a line

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 ..)