module Bergamot.Parser exposing (..) import Bergamot.Syntax exposing (Term(..), Metavariable) import Bergamot.Rules exposing (Rule, RuleEnv) import Parser exposing (Parser, Trailing(..), (|.), (|=)) import Set intLit : Parser Int intLit = Parser.int name : Parser String name = Parser.variable { start = \c -> Char.isAlphaNum c || c == '_' , inner = \c -> Char.isAlphaNum c || c == '_' , reserved = Set.empty } variable : Parser String variable = Parser.variable { start = \c -> c == '?' , inner = \c -> Char.isAlphaNum c || c == '_' , reserved = Set.empty } term : Parser (Term Metavariable) term = Parser.lazy (\() -> Parser.oneOf [ Parser.succeed IntLit |= intLit , Parser.backtrackable <| Parser.succeed Call |= name |= Parser.sequence { start = "(" , separator = "," , end = ")" , spaces = Parser.spaces , item = term , trailing = Forbidden } , Parser.succeed (\n -> Call n []) |= name , Parser.succeed Var |= variable ]) rule : Parser Rule rule = let makeRule n c ps = { name = n, conclusion = c, premises = ps } in Parser.succeed makeRule |= name |. Parser.spaces |. Parser.symbol "@" |. Parser.spaces |= term |. Parser.spaces |. Parser.symbol "<-" |. Parser.spaces |= Parser.sequence { start = "" , separator = "," , end = "" , spaces = Parser.spaces , item = term , trailing = Forbidden } program : Parser RuleEnv program = Parser.succeed (\rs -> { rules = rs }) |= Parser.sequence { start = "" , separator = ";" , end = "" , spaces = Parser.spaces , item = rule , trailing = Mandatory } |. Parser.end run : Parser a -> String -> Maybe a run prs s = case Parser.run prs s of Ok a -> Just a Err _ -> Nothing