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; 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). 49 type 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". 57 type Error is Data: 58 Error{why: String, at: Mark, cause: Cause} 59 60 def mark.line(m: Mark) -> Nat: 61 match m: 62 case Mark{line, col, idx}: 63 line 64 65 def mark.col(m: Mark) -> Nat: 66 match m: 67 case Mark{line, col, idx}: 68 col 69 70 def 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. 76 def 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". 83 def error.show(e: Error) -> String: 84 match e: 85 case Error{why, at, cause}: 86 why ++ " at " ++ mark.show(at) 87 88 def error.why(e: Error) -> String: 89 match e: 90 case Error{why, at, cause}: 91 why 92 93 def error.at(e: Error) -> Mark: 94 match e: 95 case Error{why, at, cause}: 96 at