Formerly davidcavazos/parser. Search finds this package by either name.
Parsers for expressions with operator precedence.
Defines an individual term. This is usually a number, or a variable name, or anything not containing an operator.
import Parser exposing (Parser, parse)
import Parser.Common exposing (number)
expr : Parser Float
expr =
expression [ [ term identity number ] ]
parse "5" expr --> Ok 5
-- It does not trim spaces beforehand.
parse " 5" expr |> Result.toMaybe --> NothingDefines a unary prefix operator.
import Parser exposing (Parser, parse)
import Parser.Char exposing (char)
import Parser.Common exposing (number)
expr : Parser Float
expr =
expression
[ [ prefix (\x -> -x) (char '-') ]
, [ term identity number ]
]
parse "-5" expr --> Ok -5
-- It does not trim spaces beforehand.
parse " -5" expr |> Result.toMaybe --> Nothing
-- But it does afterwards.
parse "- 5" expr --> Ok -5Defines a unary suffix operator.
import Parser exposing (Parser, parse)
import Parser.Char exposing (char)
import Parser.Common exposing (number)
factorial : Float -> Float
factorial n =
List.product (List.range 1 (floor n) |> List.map toFloat)
expr : Parser Float
expr =
expression
[ [ suffix factorial (char '!') ]
, [ term identity number ]
]
parse "5!" expr --> Ok 120
-- It trims spaces beforehand.
parse "5 !" expr --> Ok 120Defines an expression surrounded by an open and close operator.
import Parser exposing (Parser, parse)
import Parser.Char exposing (char)
import Parser.Common exposing (number)
expr : Parser Float
expr =
expression
[ [ inbetween identity (char '(') (char ')') ]
, [ term identity number ]
]
parse "(5)" expr --> Ok 5
parse "(5" expr |> Result.toMaybe --> Nothing
parse "()" expr |> Result.toMaybe --> Nothing
-- It does not trim spaces beforehand.
parse " (5)" expr |> Result.toMaybe --> Nothing
-- But it does inbetween.
parse "( 5 )" expr --> Ok 5Defines a binary left-associative operator.
import Parser exposing (Parser, parse)
import Parser.Char exposing (char)
import Parser.Common exposing (number)
expr : Parser Float
expr =
expression
[ [ fromLeft (+) (char '+')
, fromLeft (-) (char '-')
]
, [ term identity number ]
]
parse "1+2" expr --> Ok 3
parse "1+2+3" expr --> Ok 6
parse "1-2-3" expr --> Ok -4
-- It does not trim spaces beforehand.
parse " 1+2" expr |> Result.toMaybe --> Nothing
-- But it does inbetween.
parse "1 + 2" expr --> Ok 3Defines a binary right-associative operator.
import Parser exposing (Parser, parse)
import Parser.Char exposing (char)
import Parser.Common exposing (number)
expr : Parser Float
expr =
expression
[ [ fromRight (^) (char '^') ]
, [ term identity number ]
]
parse "2^3" expr --> Ok 8
parse "2^3^2" expr --> Ok 512 -- 2 ^ (3 ^ 2)
-- It does not trim spaces beforehand.
parse " 2^3" expr |> Result.toMaybe --> Nothing
-- But it does inbetween.
parse "2 ^ 3" expr --> Ok 8Describes an operator as a parser.
They take a Parser a as an input, which is used to parse subexpressions
recursively.
ℹ️ Both
PrefixandInfix*operators must start by parsing something other than a subexpression, otherwise there will be a stack overflow.
import Parser exposing (Parser, drop, parse, succeed, take)
import Parser.Char exposing (char)
import Parser.Common exposing (number)
-- Prefix operators simply parse and apply the operation.
neg : Operator Float
neg =
Prefix
(\expr ->
succeed (\x -> -x)
|> drop (char '-')
|> take expr
)
-- Infix operators parse only the right side of the subexpression.
-- The Parser returns a function that takes the left side of the
-- subexpression as an input, and applies the operation.
-- This is for a left-associative infix operator.
add : Operator Float
add =
InfixFromLeft
(\expr ->
succeed (\right left -> left + right)
|> drop (char '+')
|> take expr
)
-- You can also define a right-associative infix operator.
pow : Operator Float
pow =
InfixFromLeft
(\expr ->
succeed (\right left -> left ^ right)
|> drop (char '^')
|> take expr
)
-- A term can be achieved by simply parsing a token but not recursing.
num : Operator Float
num =
Prefix (\_ -> number)
calculate : Parser Float
calculate =
expression
[ [ neg ] -- -1
, [ pow ] -- 1 ^ 2
, [ add ] -- 1 + 2
, [ num ] -- 1
]
parse "1+-2^3" calculate --> Ok -7 -- 1 + ((-2) ^ 3)
Parses an expression using the provided operators with operator precedence. There can be multiple operators sharing the same precedence like
+and-, or*and/.