a gleam implementation of a CS assignment originally written in cpp
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add state machine parser and 2-word book support

+99 -8
+99 -8
src/bible_search.gleam
··· 1 1 import gleam/int 2 2 import gleam/io 3 3 import gleam/list 4 + import gleam/result 4 5 import gleam/string 5 6 import input.{input} 6 7 import simplifile ··· 11 12 Reference(book: String, chapter: Int, verse: Int) 12 13 } 13 14 15 + pub type Phase { 16 + Book 17 + Chapter 18 + Verse 19 + Done 20 + } 21 + 22 + pub type ScanState { 23 + ScanState( 24 + phase: Phase, 25 + ref: Reference, 26 + found_book: Bool, 27 + found_chapter: Bool, 28 + verse_text: Result(String, String), 29 + ) 30 + } 31 + 14 32 pub fn parse_reference(input: String) -> Result(Reference, String) { 15 33 let parts = string.split(input, on: " ") 16 34 ··· 21 39 case int.parse(verse_s) { 22 40 Ok(verse) -> 23 41 Ok(Reference(book: string.uppercase(book), chapter:, verse:)) 24 - Error(_) -> Error("Invalid verse" <> verse_s) 42 + Error(_) -> Error("Invalid verse: " <> verse_s) 25 43 } 26 - Error(_) -> Error("Invalid chapter" <> chapter_s) 44 + Error(_) -> Error("Invalid chapter: " <> chapter_s) 27 45 } 46 + [book_p1, book_p2, chapter_s, verse_s] -> 47 + case int.parse(chapter_s) { 48 + Ok(chapter) -> 49 + case int.parse(verse_s) { 50 + Ok(verse) -> 51 + Ok(Reference( 52 + book: string.uppercase(book_p1 <> " " <> book_p2), 53 + chapter:, 54 + verse:, 55 + )) 56 + Error(_) -> Error("Invalid verse: " <> verse_s) 57 + } 58 + Error(_) -> Error("Invalid chapter: " <> chapter_s) 59 + } 60 + 28 61 _ -> Error("invalid parse") 29 62 } 30 63 } ··· 38 71 39 72 let assert Ok(reference) = parse_reference(search) 40 73 41 - list.each(biblelines, fn(line) { 42 - case line { 43 - "THE BOOK OF " <> book if book == reference.book -> io.println(book) 44 - _ -> io.print("") 45 - } 46 - }) 74 + let inital = 75 + ScanState( 76 + phase: Book, 77 + ref: reference, 78 + found_book: False, 79 + found_chapter: False, 80 + verse_text: Error("Verse not found"), 81 + ) 82 + 83 + let result = 84 + list.fold(biblelines, inital, fn(state, line) -> ScanState { 85 + case state.phase { 86 + Done -> state 87 + Book -> 88 + case line { 89 + "THE BOOK OF " <> book -> 90 + case book == state.ref.book { 91 + True -> ScanState(..state, phase: Chapter, found_book: True) 92 + False -> state 93 + } 94 + _ -> state 95 + } 96 + Chapter -> 97 + case line { 98 + "CHAPTER " <> chapter -> 99 + case result.unwrap(int.parse(chapter), 0) == state.ref.chapter { 100 + True -> ScanState(..state, phase: Verse, found_chapter: True) 101 + False -> state 102 + } 103 + _ -> state 104 + } 105 + Verse -> 106 + fn() { 107 + let parts = string.split(line, " ") 108 + case parts { 109 + [first, ..rest] -> 110 + case result.unwrap(int.parse(first), 0) == state.ref.verse { 111 + True -> 112 + ScanState( 113 + ..state, 114 + phase: Done, 115 + verse_text: Ok(string.join(rest, " ")), 116 + ) 117 + False -> state 118 + } 119 + _ -> state 120 + } 121 + }() 122 + } 123 + }) 124 + 125 + case result.verse_text { 126 + Ok(text) -> 127 + io.println( 128 + result.ref.book 129 + <> " " 130 + <> int.to_string(result.ref.chapter) 131 + <> ":" 132 + <> int.to_string(result.ref.chapter) 133 + <> " " 134 + <> text, 135 + ) 136 + Error(e) -> io.println_error(e) 137 + } 47 138 }