1 # The pieces the scanner hands the parser, and the errors both report. 2 3 import 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. 7 type Mark is Data: 8 Mark{line: Nat, col: Nat, idx: Nat} 9 10 # How a scalar was written. 11 type 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. 19 type 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 43 type Token is Data: 44 Token{tok: Tok, start: Mark, end: Mark} 45 46 # Why a text didn't load: it isn't YAML, or it is but the schema can't 47 # load it (a bad !!int, an unknown alias, a repeated key). 48 type Cause is Data: 49 Syntax{} 50 Content{} 51 52 # What went wrong, where, and why. A syntax error reads as a problem and 53 # what was being read: "did not find expected key while parsing a block 54 # mapping". 55 type Error is Data: 56 Error{why: String, at: Mark, cause: Cause} 57 58 def mark.line(m: Mark) -> Nat: 59 match m: 60 case Mark{line, col, idx}: 61 line 62 63 def mark.col(m: Mark) -> Nat: 64 match m: 65 case Mark{line, col, idx}: 66 col 67 68 def mark.idx(m: Mark) -> Nat: 69 match m: 70 case Mark{line, col, idx}: 71 idx 72 73 # "at line 2 column 5", counting from 1. 74 def mark.show(m: Mark) -> String: 75 match m: 76 case Mark{line, col, idx}: 77 "line " ++ Nat.show(1n+line) ++ " column " ++ Nat.show(1n+col) 78 79 # The error as one line: "mapping values are not allowed in this context at 80 # line 1 column 5". 81 def error.show(e: Error) -> String: 82 match e: 83 case Error{why, at, cause}: 84 why ++ " at " ++ mark.show(at) 85 86 def error.why(e: Error) -> String: 87 match e: 88 case Error{why, at, cause}: 89 why 90 91 def error.at(e: Error) -> Mark: 92 match e: 93 case Error{why, at, cause}: 94 at