token.bend

yaml-for-bend@0.1.1.0 · 96 lines · 13 definitions

1# The pieces the scanner hands the parser, and the errors both report.
2
3import Base
4
5# A place in the text: the line and column (each from 0, a column counted in
6# characters) and the character's index from the start.
7type Mark is Data:
8  Mark{line: Nat, col: Nat, idx: Nat}
9
10# How a scalar was written.
11type Style is Data:
12  Plain{}
13  Single{}
14  Double{}
15  Literal{}
16  Folded{}
17
18# A token, as libyaml names them. A scanner error ends the tokens with Broken.
19type Tok is Data:
20  StreamStart{}
21  StreamEnd{}
22  VersionDir{major: Nat, minor: Nat}
23  TagDir{handle: String, prefix: String}
24  DocStart{}
25  DocEnd{}
26  BSeqStart{}
27  BMapStart{}
28  BEnd{}
29  FSeqStart{}
30  FSeqEnd{}
31  FMapStart{}
32  FMapEnd{}
33  BEntry{}
34  FEntry{}
35  KeyTok{}
36  ValueTok{}
37  AliasTok{name: String}
38  AnchorTok{name: String}
39  TagTok{handle: String, suffix: String}
40  ScalarTok{text: String, style: Style}
41  Broken{error: Error}
42
43type Token is Data:
44  Token{tok: Tok, start: Mark, end: Mark}
45
46# Why a text didn't load: it isn't YAML; it is, but the schema can't load
47# it (a bad !!int, an unknown alias, a repeated key); or it would pass one
48# of the limits a load sets (its size, its depth, its aliases).
49type Cause is Data:
50  Syntax{}
51  Content{}
52  Limit{}
53
54# What went wrong, where, and why. A syntax error reads as a problem and
55# what was being read: "did not find expected key while parsing a block
56# mapping".
57type Error is Data:
58  Error{why: String, at: Mark, cause: Cause}
59
60def mark.line(m: Mark) -> Nat:
61  match m:
62    case Mark{line, col, idx}:
63      line
64
65def mark.col(m: Mark) -> Nat:
66  match m:
67    case Mark{line, col, idx}:
68      col
69
70def mark.idx(m: Mark) -> Nat:
71  match m:
72    case Mark{line, col, idx}:
73      idx
74
75# "at line 2 column 5", counting from 1.
76def mark.show(m: Mark) -> String:
77  match m:
78    case Mark{line, col, idx}:
79      "line " ++ Nat.show(1n+line) ++ " column " ++ Nat.show(1n+col)
80
81# The error as one line: "mapping values are not allowed in this context at
82# line 1 column 5".
83def error.show(e: Error) -> String:
84  match e:
85    case Error{why, at, cause}:
86      why ++ " at " ++ mark.show(at)
87
88def error.why(e: Error) -> String:
89  match e:
90    case Error{why, at, cause}:
91      why
92
93def error.at(e: Error) -> Mark:
94  match e:
95    case Error{why, at, cause}:
96      at