layout.tri (4150B)
1 !import prelude * 2 !import source_lexer as L 3 !import consumers_structural as SCP 4 !export * 5 -- Reusable authored layout transition over located source tokens. 6 -- Entry points: layoutConsumer committed, layout, layoutWithCommit, renamedLayout. 7 -- State is (afterNewlines?, committed?); replies use the parser protocol. 8 -- This constructs inspectable SCP data, not a source frontend or deployment API. 9 10 -- Reply/diagnostic trees follow lib/parser.tri exactly. These builders are 11 -- template constructors; they never interpret a token or invoke a host API. 12 replySuccess value rest consumed committed = 13 SCP.outFork (SCP.outLiteral true) (SCP.outFork value (SCP.outFork rest 14 (SCP.outFork (SCP.outLiteral consumed) committed))) 15 replyFailure diagnostic rest consumed committed = 16 SCP.outFork (SCP.outLiteral false) (SCP.outFork diagnostic (SCP.outFork rest 17 (SCP.outFork (SCP.outLiteral consumed) committed))) 18 diagnostic code expected found location = 19 SCP.outFork (SCP.outLiteral code) (SCP.outFork expected (SCP.outFork found 20 (SCP.outFork location (SCP.outLiteral t)))) 21 expectedName found location = 22 diagnostic 2 (SCP.outLiteral L.sourceTokenName) found location 23 24 -- `As` retains the entire located token as a capture while its nested 25 -- pattern inspects the kind and, for the indented branch, its column. 26 nameAtColumn column = 27 SCP.patFork (SCP.patLiteral L.sourceTokenName) (SCP.patFork SCP.patAny 28 (SCP.patFork 29 (SCP.patFork SCP.patAny (SCP.patFork column SCP.patAny)) 30 SCP.patAny)) 31 nameAny = SCP.patFork (SCP.patLiteral L.sourceTokenName) SCP.patAny 32 newline = SCP.patFork (SCP.patLiteral L.sourceTokenNewline) SCP.patAny 33 anyToken = SCP.patFork (SCP.patCapture 3) (SCP.patFork SCP.patAny 34 (SCP.patFork (SCP.patCapture 4) SCP.patAny)) 35 36 -- State = pair afterNewlines? committed?. The second field models an 37 -- explicit commit *before* parsing; it is not conflated with consumption. 38 afterNewlines = SCP.outFork (SCP.outLiteral (t t)) (SCP.outCapture 8) 39 inlineValue = SCP.outFork (SCP.outLiteral 0) (SCP.outCapture 0) 40 indentedValue = SCP.outFork (SCP.outCapture 2) (SCP.outCapture 0) 41 42 layoutConsumer committed = SCP.makeConsumer (pair t committed) [(SCP.makeRule SCP.patLeaf (SCP.patFork SCP.patLeaf (SCP.patCapture 8)) 43 (replyFailure (expectedName (SCP.outLiteral t) (SCP.outLiteral t)) 44 (SCP.outLiteral t) false (SCP.outCapture 8))) 45 (SCP.makeRule SCP.patLeaf (SCP.patFork (SCP.patStem SCP.patAny) (SCP.patCapture 8)) 46 (replyFailure (diagnostic 40 (SCP.outLiteral "definition body") 47 (SCP.outLiteral t) (SCP.outLiteral t)) 48 (SCP.outLiteral t) true (SCP.outCapture 8))) 49 (SCP.makeRule (SCP.patFork (SCP.patAs 0 newline) (SCP.patCapture 1)) 50 (SCP.patFork SCP.patAny (SCP.patCapture 8)) 51 (SCP.outRecur (SCP.outCapture 1) afterNewlines)) 52 (SCP.makeRule (SCP.patFork (SCP.patAs 0 nameAny) (SCP.patCapture 1)) 53 (SCP.patFork SCP.patLeaf (SCP.patCapture 8)) 54 (replySuccess inlineValue (SCP.outCapture 1) true (SCP.outCapture 8))) 55 (SCP.makeRule (SCP.patFork 56 (SCP.patAs 0 (nameAtColumn (SCP.patLiteral 1))) (SCP.patCapture 1)) 57 (SCP.patFork (SCP.patStem SCP.patAny) (SCP.patCapture 8)) 58 (replySuccess inlineValue (SCP.outCapture 1) true (SCP.outCapture 8))) 59 (SCP.makeRule (SCP.patFork 60 (SCP.patAs 0 (nameAtColumn (SCP.patCapture 2))) (SCP.patCapture 1)) 61 (SCP.patFork (SCP.patStem SCP.patAny) (SCP.patCapture 8)) 62 (replySuccess indentedValue (SCP.outCapture 1) true (SCP.outCapture 8))) 63 (SCP.makeRule (SCP.patAs 0 (SCP.patFork anyToken SCP.patAny)) 64 (SCP.patFork SCP.patLeaf (SCP.patCapture 8)) 65 (replyFailure (expectedName (SCP.outCapture 3) (SCP.outCapture 4)) 66 (SCP.outCapture 0) false (SCP.outCapture 8))) 67 (SCP.makeRule (SCP.patAs 0 (SCP.patFork anyToken SCP.patAny)) 68 (SCP.patFork (SCP.patStem SCP.patAny) (SCP.patCapture 8)) 69 (replyFailure (expectedName (SCP.outCapture 3) (SCP.outCapture 4)) 70 (SCP.outCapture 0) true (SCP.outCapture 8)))] 71 layout = layoutConsumer false 72 layoutWithCommit = layoutConsumer true 73 renamedLayout = SCP.replaceLiteral layout "definition body" "missing indented value"