module TRSParser where

import Term
import Rule
import TRS
import Text.ParserCombinators.Parsec
        
-- Scanners

comment :: Parser ()
comment = do
  _ <- char ';'
  skipMany (noneOf "\n")

whitespaces :: Parser ()
whitespaces = skipMany (do { _ <- space; return () } <|> comment)

identifier :: Parser String
identifier = do
  whitespaces
  x <- many1 (noneOf "();, \t\r\n")
  whitespaces
  return x

number :: Parser Int
number = do
  whitespaces
  s <- many1 digit
  whitespaces
  return (read s :: Int)

keyword :: String -> Parser ()
keyword s = do
  whitespaces
  _ <- string s
  whitespaces

param :: String -> a -> Parser a
param s x = do
  keyword s
  return x
            
-- Parsing functions.

parse_term :: Parser Term
parse_term = try parse_fun <|> parse_var

parse_var :: Parser Term
parse_var = do
  x <- identifier
  return (V x)

parse_fun :: Parser Term
parse_fun = do
  f <- identifier
  keyword "("
  ts <- sepBy parse_term (keyword ",")
  keyword ")"
  return (F f ts)

parse_rule :: Parser Rule
parse_rule = do
  l <- parse_term
  keyword "->"
  r <- parse_term
  return (l, r)

parse_trs :: Parser TRS
parse_trs = many parse_rule

-- A reader function.

read_with :: Parser a -> String -> a
read_with parser s = 
  case parse parser "(input)" s of
    Left e -> error (show e)
    Right t -> t

read_term :: String -> Term
read_term s = read_with parse_term s

read_rule :: String -> Rule
read_rule s = read_with parse_rule s

read_trs :: String -> TRS
read_trs s = read_with parse_trs s
