0740adbe2a2c04e682113e661c24f4e39a29b2af22255d27dc5650b05f096acc.tri (6595B)
1 !import prelude * 2 !import parser * 3 !export * 4 5 -- Located character-scanning tools. Input is the canonical character list. 6 -- A scan returns a parser reply whose payload is (state, endPosition). 7 -- The remainder starts with the first character that failed the predicate. 8 lexerPosition line column offset = pair line (pair column offset) 9 lexerPositionLine position = fst position 10 lexerPositionColumn position = fst (snd position) 11 lexerPositionOffset position = snd (snd position) 12 lexerStart = lexerPosition 1 1 0 13 14 lexerAdvance position character = 15 lazyBool 16 (_ : lexerPosition (succ (lexerPositionLine position)) 1 17 (succ (lexerPositionOffset position))) 18 (_ : lexerPosition (lexerPositionLine position) 19 (succ (lexerPositionColumn position)) 20 (succ (lexerPositionOffset position))) 21 (equal? character 10) 22 23 lexerToken kind payload start end = pair kind (pair payload (pair start end)) 24 lexerTokenKind token = fst token 25 lexerTokenPayload token = fst (snd token) 26 lexerTokenStart token = fst (snd (snd token)) 27 lexerTokenEnd token = snd (snd (snd token)) 28 29 -- The consumed input is the first recursive argument. The accumulator and 30 -- predicate cannot cause an abstract source stream to unfold on import. 31 lexerScanWhile_ self input position state predicate update consumed = 32 lazyList 33 (_ : parserReplyOk (pair state position) input consumed false) 34 (character rest : 35 lazyBool 36 (_ : self rest (lexerAdvance position character) 37 (update state character) predicate update true) 38 (_ : parserReplyOk (pair state position) input consumed false) 39 (predicate character)) 40 input 41 42 lexerScanWhile = (input position state predicate update : 43 y lexerScanWhile_ input position state predicate update false) 44 45 -- Transform the accumulated state without changing the location, remainder, 46 -- or consumption flags. Useful for reversing a name after scanning it. 47 lexerMapScan transform reply = 48 parserMatchReply 49 (diagnostic rest consumed committed : 50 parserReplyFail diagnostic rest consumed committed) 51 (stateAndEnd rest consumed committed : 52 parserReplyOk (pair (transform (fst stateAndEnd)) (snd stateAndEnd)) 53 rest consumed committed) 54 reply 55 56 -- A successful scan can be used as a trivia skip without inspecting its 57 -- accumulator. This destructures only the fixed-format reply; no rescan. 58 lexerRemainingAndEnd reply = 59 pair (parserReplyRest reply) (snd (parserReplyPayload reply)) 60 61 -- Ordered, single-character lexical alternatives. Each rule is a pair of 62 -- predicate and handler; the first matching handler owns its input and any 63 -- failure. This is dispatch, not implicit backtracking over failed scans. 64 lexerDispatch_ self rules character fallback = 65 lazyList 66 (_ : fallback character) 67 (rule rest : 68 lazyBool 69 (_ : snd rule character) 70 (_ : self rest character fallback) 71 (fst rule character)) 72 rules 73 74 lexerDispatch = (rules fallback character : 75 y lexerDispatch_ rules character fallback) 76 77 -- Turn a completed state scan into one located token. `classify state` 78 -- supplies (kind, payload); `next` is the enclosing lexer continuation. 79 lexerEmitScan scan start reversed classify next = 80 parserMatchReply 81 (diagnostic rest consumed committed : 82 parserReplyFail diagnostic rest true committed) 83 (stateAndEnd rest consumed committed : 84 matchPair 85 (kind payload : 86 next rest (snd stateAndEnd) 87 (pair (lexerToken kind payload start (snd stateAndEnd)) reversed)) 88 (classify (fst stateAndEnd))) 89 scan 90 91 -- Consume trivia and resume the outer lexer at its first unconsumed input. 92 lexerResumeScan scan next = 93 parserMatchReply 94 (diagnostic rest consumed committed : 95 parserReplyFail diagnostic rest true committed) 96 (stateAndEnd rest consumed committed : next rest (snd stateAndEnd)) 97 scan 98 99 -- Scan until a two-character terminator, leaving everything after it intact. 100 -- The supplied diagnostic describes EOF before the terminator. This is a 101 -- non-nesting primitive; callers that require nesting need an explicit state. 102 lexerSkipUntilPair_ self input position first second missing consumed = 103 lazyList 104 (_ : parserReplyFail missing input consumed false) 105 (character rest : 106 lazyBool 107 (_ : lazyList 108 (_ : self rest (lexerAdvance position character) 109 first second missing true) 110 (next tail : 111 lazyBool 112 (_ : parserReplyOk 113 (pair t (lexerAdvance (lexerAdvance position character) next)) 114 tail true false) 115 (_ : self rest (lexerAdvance position character) 116 first second missing true) 117 (equal? next second)) 118 rest) 119 (_ : self rest (lexerAdvance position character) 120 first second missing true) 121 (equal? character first)) 122 input 123 124 lexerSkipUntilPair = (input position first second missing : 125 y lexerSkipUntilPair_ input position first second missing false) 126 127 -- Quoted strings use a caller-supplied escape decoder (character -> Maybe 128 -- decodedCharacter). Both diagnostics are values, not host exceptions. 129 -- `position` is immediately after an already-consumed opening delimiter. 130 lexerQuotedEscape self input rest position reversed close escape decode missing invalid = 131 lazyList 132 (_ : parserReplyFail missing input true false) 133 (character remaining : 134 lazyMaybe 135 (_ : parserReplyFail 136 (invalid character (lexerAdvance position escape)) input true false) 137 (decoded : self remaining 138 (lexerAdvance (lexerAdvance position escape) character) 139 (pair decoded reversed) close escape decode missing invalid) 140 (decode character)) 141 rest 142 143 lexerScanQuoted_ self input position reversed close escape decode missing invalid = 144 lazyList 145 (_ : parserReplyFail missing input true false) 146 (character rest : 147 lazyBool 148 (_ : parserReplyOk 149 (pair (reverse reversed) (lexerAdvance position character)) 150 rest true false) 151 (_ : lazyBool 152 (_ : lexerQuotedEscape self input rest position reversed 153 close escape decode missing invalid) 154 (_ : self rest (lexerAdvance position character) 155 (pair character reversed) close escape decode missing invalid) 156 (equal? character escape)) 157 (equal? character close)) 158 input 159 160 lexerScanQuoted = (input position close escape decode missing invalid : 161 y lexerScanQuoted_ input position t close escape decode missing invalid) 162