From 6c26bcb5eb0c3736aae13d9411610abb6fcd81a9 Mon Sep 17 00:00:00 2001 From: Smaug123 Date: Mon, 22 Jan 2024 19:22:36 +0000 Subject: [PATCH] If-then-else --- PrattParser.Test/TestParser.fs | 13 ++++++++++++- PrattParser/Domain.fs | 3 +++ PrattParser/Parser.fs | 18 ++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/PrattParser.Test/TestParser.fs b/PrattParser.Test/TestParser.fs index ea8521c..ae9eee1 100644 --- a/PrattParser.Test/TestParser.fs +++ b/PrattParser.Test/TestParser.fs @@ -16,7 +16,18 @@ module TestParser = "-a!", Expr.unaryMinus (Expr.factorial (Expr.var "a")) "-a! + b", Expr.plus (Expr.unaryMinus (Expr.factorial (Expr.var "a"))) (Expr.var "b") "(-a)! + b", Expr.plus (Expr.factorial (Expr.paren (Expr.unaryMinus (Expr.var "a")))) (Expr.var "b") - // TODO: if-then-else + "if x then y else z", Expr.ifThenElse (Expr.var "x") (Expr.var "y") (Expr.var "z") + "if x then y", Expr.ifThen (Expr.var "x") (Expr.var "y") + "1 + if x then y", Expr.plus (Expr.constInt 1) (Expr.ifThen (Expr.var "x") (Expr.var "y")) + "if x + 1 then y else z + 3", + Expr.ifThenElse + (Expr.plus (Expr.var "x") (Expr.constInt 1)) + (Expr.var "y") + (Expr.plus (Expr.var "z") (Expr.constInt 3)) + "(if x + 1 then y else z) + 3", + Expr.plus + (Expr.paren (Expr.ifThenElse (Expr.plus (Expr.var "x") (Expr.constInt 1)) (Expr.var "y") (Expr.var "z"))) + (Expr.constInt 3) "g x y + a * (func b c)", let gXY = diff --git a/PrattParser/Domain.fs b/PrattParser/Domain.fs index 8c952e0..bf99ab3 100644 --- a/PrattParser/Domain.fs +++ b/PrattParser/Domain.fs @@ -12,6 +12,7 @@ type Expr = | Factorial of Expr | Paren of Expr | IfThenElse of Expr * Expr * Expr + | IfThen of Expr * Expr [] module Expr = @@ -28,6 +29,8 @@ module Expr = let ifThenElse ifClause thenClause elseClause = Expr.IfThenElse (ifClause, thenClause, elseClause) + let ifThen ifClause thenClause = Expr.IfThen (ifClause, thenClause) + [] type TokenType = | Plus diff --git a/PrattParser/Parser.fs b/PrattParser/Parser.fs index 6a90d38..9089bb5 100644 --- a/PrattParser/Parser.fs +++ b/PrattParser/Parser.fs @@ -71,6 +71,24 @@ module Parser = Expr.paren contents, rest + elif firstToken.Type = TokenType.If then + let ifClause, rest = parseInner inputString rest 0 + + match rest with + | [] -> failwith "if requires a trailing then" + | head :: _ when head.Type <> TokenType.Then -> failwithf "if was not followed by then, got: %+A" head + | _ :: rest -> + + let thenClause, rest = parseInner inputString rest 0 + + match rest with + | [] -> Expr.ifThen ifClause thenClause, rest + | head :: _ when head.Type <> TokenType.Else -> Expr.ifThen ifClause thenClause, rest + | _ :: rest -> + + let elseClause, rest = parseInner inputString rest 0 + Expr.ifThenElse ifClause thenClause elseClause, rest + else match Token.prefixPrecedence firstToken.Type with