2022-09-28 05:05:16 +00:00
|
|
|
module Parse where
|
|
|
|
|
2022-09-29 01:57:05 +00:00
|
|
|
open import Agda.Builtin.Bool
|
2022-09-28 05:05:16 +00:00
|
|
|
open import Agda.Builtin.Char
|
|
|
|
open import Agda.Builtin.List
|
|
|
|
open import Agda.Builtin.Maybe
|
|
|
|
open import Agda.Builtin.Nat
|
|
|
|
open import Agda.Builtin.String
|
|
|
|
|
2022-09-28 23:04:00 +00:00
|
|
|
open import Data.List using (_++_; reverse)
|
2022-09-29 01:57:05 +00:00
|
|
|
open import Data.Nat.DivMod using (_/_)
|
2022-09-28 22:32:35 +00:00
|
|
|
|
2022-09-28 05:05:16 +00:00
|
|
|
open import Util
|
|
|
|
|
2022-09-28 23:04:00 +00:00
|
|
|
data Token : Set where
|
|
|
|
Digit : Nat → Token
|
|
|
|
Delim : Char → Token
|
|
|
|
Oper : Char → Token
|
|
|
|
Skip : Char → Token
|
|
|
|
Term : Token
|
|
|
|
|
2022-09-28 22:06:38 +00:00
|
|
|
record Result (A : Set) : Set where
|
|
|
|
constructor emit
|
|
|
|
field
|
|
|
|
res : Maybe A
|
|
|
|
rem : List Char
|
|
|
|
|
2022-09-29 02:31:34 +00:00
|
|
|
emit↓ : {A : Set} → A → List Char → Result A
|
|
|
|
emit↓ a rem = emit (just a) rem
|
|
|
|
|
|
|
|
emit↑ : {A : Set} → List Char → Result A
|
|
|
|
emit↑ rem = emit nothing rem
|
|
|
|
|
2022-09-28 22:06:38 +00:00
|
|
|
showResult : {A : Set} → (A → String) → Result A → String
|
|
|
|
showResult f (emit nothing rem) = primStringAppend "remainder: " (primStringFromList rem)
|
2022-09-29 02:31:34 +00:00
|
|
|
showResult f (emit (just r) []) = primStringAppend "result: " (f r)
|
|
|
|
showResult f (emit (just r) xs) = primStringAppend (primStringAppend "result: " (f r)) (primStringAppend ", remainder: " (primStringFromList xs))
|
2022-09-28 22:06:38 +00:00
|
|
|
|
|
|
|
-- take consecutive occurences of a character set
|
|
|
|
takeCons : List Char → List Char → Result (List Char)
|
2022-09-29 02:31:34 +00:00
|
|
|
takeCons _ [] = emit↑ []
|
|
|
|
takeCons [] r = emit↑ r
|
2022-09-28 22:06:38 +00:00
|
|
|
takeCons cs (x ∷ xs) with (findCharIndex 0 x cs)
|
2022-09-29 02:31:34 +00:00
|
|
|
... | nothing = emit↑ (x ∷ xs)
|
2022-09-28 22:06:38 +00:00
|
|
|
... | just n with (takeCons cs xs)
|
2022-09-29 02:31:34 +00:00
|
|
|
... | emit nothing rem = emit↓ (x ∷ []) xs
|
|
|
|
... | emit (just res) rem = emit↓ (x ∷ res) rem
|
2022-09-28 04:12:48 +00:00
|
|
|
|
2022-09-28 22:32:35 +00:00
|
|
|
digits : List Char
|
|
|
|
digits = primStringToList "0123456789"
|
|
|
|
|
2022-09-28 22:34:13 +00:00
|
|
|
opers : List Char
|
2022-09-29 01:57:05 +00:00
|
|
|
opers = primStringToList "-+*/"
|
2022-09-28 22:34:13 +00:00
|
|
|
|
2022-09-28 22:32:35 +00:00
|
|
|
-- parse a single character into a typed token
|
2022-09-28 04:12:48 +00:00
|
|
|
parseChar : Char → Token
|
|
|
|
parseChar '0' = Digit 0
|
|
|
|
parseChar '1' = Digit 1
|
|
|
|
parseChar '2' = Digit 2
|
|
|
|
parseChar '3' = Digit 3
|
|
|
|
parseChar '4' = Digit 4
|
|
|
|
parseChar '5' = Digit 5
|
|
|
|
parseChar '6' = Digit 6
|
|
|
|
parseChar '7' = Digit 7
|
|
|
|
parseChar '8' = Digit 8
|
|
|
|
parseChar '9' = Digit 9
|
|
|
|
parseChar ',' = Delim ','
|
2022-09-28 23:16:26 +00:00
|
|
|
parseChar '-' = Oper '-'
|
2022-09-28 04:12:48 +00:00
|
|
|
parseChar '+' = Oper '+'
|
2022-09-29 01:57:05 +00:00
|
|
|
parseChar '*' = Oper '*'
|
|
|
|
parseChar '/' = Oper '/'
|
2022-09-28 22:06:38 +00:00
|
|
|
parseChar ' ' = Skip ' '
|
2022-09-28 04:12:48 +00:00
|
|
|
parseChar _ = Term
|
|
|
|
|
2022-09-28 22:32:35 +00:00
|
|
|
-- parse a number from a list of characters
|
2022-09-28 22:06:38 +00:00
|
|
|
parseNat : Maybe Nat → List Char → Result Nat
|
|
|
|
parseNat a [] = emit a []
|
2022-09-28 05:05:16 +00:00
|
|
|
parseNat a (x ∷ xs) with parseChar x
|
2022-09-28 22:06:38 +00:00
|
|
|
... | Digit n = parseNat (just (((default 0 a) * 10) + n)) xs
|
2022-09-29 02:31:34 +00:00
|
|
|
... | _ = emit↑ xs
|
2022-09-28 05:05:16 +00:00
|
|
|
|
2022-09-28 22:06:38 +00:00
|
|
|
takeNat : List Char → Result Nat
|
|
|
|
takeNat s with takeCons digits s
|
|
|
|
... | emit nothing rem₁ = emit nothing rem₁
|
2022-09-28 23:16:15 +00:00
|
|
|
... | emit (just xs) rem₁ with parseNat nothing xs
|
2022-09-29 02:31:34 +00:00
|
|
|
... | emit nothing rem₂ = emit↑ rem₁
|
|
|
|
... | emit (just n) rem₂ = emit↓ n rem₁
|
2022-09-28 22:06:38 +00:00
|
|
|
|
|
|
|
takeOper : List Char → Result Token
|
2022-09-28 22:34:13 +00:00
|
|
|
takeOper s with takeCons opers s
|
2022-09-29 02:31:34 +00:00
|
|
|
... | emit nothing rem = emit↑ rem
|
|
|
|
... | emit (just []) rem = emit↑ rem
|
2022-09-28 22:06:38 +00:00
|
|
|
... | emit (just (x ∷ xs)) rem with parseChar x
|
2022-09-29 02:31:34 +00:00
|
|
|
... | Oper o = emit↓ (Oper o) (xs ++ rem)
|
|
|
|
... | _ = emit↑ s
|
2022-09-28 05:05:16 +00:00
|
|
|
|
2022-09-28 22:06:38 +00:00
|
|
|
data BinExpr : Set where
|
|
|
|
bin : Token → Token → Token → BinExpr
|
2022-09-28 05:05:16 +00:00
|
|
|
|
2022-09-28 22:06:38 +00:00
|
|
|
evalBin : Result BinExpr → Result Nat
|
2022-09-29 02:31:34 +00:00
|
|
|
evalBin (emit nothing rem) = emit↑ rem
|
|
|
|
evalBin (emit (just (bin (Oper '+') (Digit a) (Digit b))) rem) = emit↓ (a + b) rem
|
|
|
|
evalBin (emit (just (bin (Oper '-') (Digit a) (Digit b))) rem) = emit↓ (a - b) rem
|
|
|
|
evalBin (emit (just (bin (Oper '*') (Digit a) (Digit b))) rem) = emit↓ (a * b) rem
|
2022-09-29 01:57:05 +00:00
|
|
|
evalBin (emit (just (bin (Oper '/') (Digit a) (Digit b))) rem) with (b == zero)
|
2022-09-29 02:31:34 +00:00
|
|
|
... | false = emit↓ (a / (suc (b - 1))) rem -- todo: why tho
|
|
|
|
... | true = emit↑ rem
|
|
|
|
evalBin (emit (just (bin _ _ _)) rem) = emit↑ rem
|
2022-09-28 05:05:16 +00:00
|
|
|
|
2022-09-28 22:06:38 +00:00
|
|
|
takeBin : List Char → Result BinExpr
|
|
|
|
takeBin s with takeNat s
|
2022-09-29 02:31:34 +00:00
|
|
|
... | emit nothing rem₁ = emit↑ s
|
2022-09-28 22:06:38 +00:00
|
|
|
... | emit (just res₁) rem₁ with takeOper rem₁
|
2022-09-29 02:31:34 +00:00
|
|
|
... | emit nothing rem₂ = emit↑ rem₁
|
2022-09-28 22:09:14 +00:00
|
|
|
... | emit (just oper) rem₂ with takeNat rem₂
|
2022-09-29 02:31:34 +00:00
|
|
|
... | emit nothing rem₃ = emit↑ rem₁
|
|
|
|
... | emit (just res₃) rem₃ = emit↓ (bin oper (Digit res₁) (Digit res₃)) rem₃
|
2022-09-28 04:12:48 +00:00
|
|
|
|
2022-09-28 22:06:38 +00:00
|
|
|
takeLine : List Char → List (Result BinExpr)
|
2022-09-28 23:16:15 +00:00
|
|
|
takeLine s = map takeBin (map reverse (reverse (split (';' ∷ []) s)))
|