<commit_before>module Uroboro.Parser
    (
      pmain
    ) where

import Control.Applicative ((<*), (<*>), (*>))
import Control.Monad (liftM)
import Control.Monad.Identity (Identity)
import Text.Parsec

import Uroboro.Token
import Uroboro.Tree

-- |Parser without user state
type Parser = ParsecT String () Identity

-- |Parse "(p, ...)"
args :: Parser a -> Parser [a]
args p = parens (commaSep p)

-- |Recursively apply a list of functions to a start value, from left to right
fold :: a -> [a -> a] -> a
fold x [] = x
fold x (f:fs) = f (fold x fs)

-- |Parse "a.name(b, ...)..."
dotNotation :: (String -> [b] -> a -> a) -> Parser a -> Parser b -> Parser a
dotNotation make a b = liftM fold a <*> (dot *> sepBy1 name dot)
            where name = liftM make identifier <*> args b

-- |Parse expression
pexp :: Parser PExp
pexp = choice [des, app, var] <?> "expression"
  where
    des = try $ dotNotation PDes (app <|> var <?> "function or variable") pexp
    app = try $ liftM PApp identifier <*> args pexp
    var = liftM PVar identifier

-- |Parse exactly one expression
pmain :: Parser PExp
pmain = whiteSpace *> pexp <* eof

-- |Parse pattern
pp :: Parser PP
pp = choice [con, var] <?> "pattern"
  where
    con = try $ liftM PPCon identifier <*> args pp
    var = liftM PPVar identifier

-- |Parse copattern
pq :: Parser PQ
pq = choice [des, app] <?> "copattern"
  where
    des = try $ dotNotation PQDes (app <?> "function") pp
    app = liftM PQApp identifier <*> args pp

-- |Parse data definition
ptpos :: Parser PT
ptpos = liftM PTPos (reserved "data" *> identifier <* reserved "where")
    <*> many1 (liftM PTCon identifier <*> parens (commaSep identifier) <*> (colon *> identifier))

-- |Parse codata definition<commit_msg>Move try around to get rid of $<commit_after>module Uroboro.Parser
    (
      pmain
    ) where

import Control.Applicative ((<*), (<*>), (*>))
import Control.Monad (liftM)
import Control.Monad.Identity (Identity)
import Text.Parsec

import Uroboro.Token
import Uroboro.Tree

-- |Parser without user state
type Parser = ParsecT String () Identity

-- |Parse "(p, ...)"
args :: Parser a -> Parser [a]
args p = parens (commaSep p)

-- |Recursively apply a list of functions to a start value, from left to right
fold :: a -> [a -> a] -> a
fold x [] = x
fold x (f:fs) = f (fold x fs)

-- |Parse "a.name(b, ...)..."
dotNotation :: (String -> [b] -> a -> a) -> Parser a -> Parser b -> Parser a
dotNotation make a b = liftM fold a <*> (dot *> sepBy1 name dot)
            where name = liftM make identifier <*> args b

-- |Parse expression
pexp :: Parser PExp
pexp = choice [try des, try app, var] <?> "expression"
  where
    des = dotNotation PDes (app <|> var <?> "function or variable") pexp
    app = liftM PApp identifier <*> args pexp
    var = liftM PVar identifier

-- |Parse exactly one expression
pmain :: Parser PExp
pmain = whiteSpace *> pexp <* eof

-- |Parse pattern
pp :: Parser PP
pp = choice [try con, var] <?> "pattern"
  where
    con = liftM PPCon identifier <*> args pp
    var = liftM PPVar identifier

-- |Parse copattern
pq :: Parser PQ
pq = choice [try des, app] <?> "copattern"
  where
    des = dotNotation PQDes (app <?> "function") pp
    app = liftM PQApp identifier <*> args pp

-- |Parse data definition
ptpos :: Parser PT
ptpos = liftM PTPos (reserved "data" *> identifier <* reserved "where")
    <*> many1 (liftM PTCon identifier <*> parens (commaSep identifier) <*> (colon *> identifier))

-- |Parse codata definition
{'fraction_non_alphanumeric': 0.1448651749856569, 'fraction_numerical': 0.0011474469305794606, 'mean_word_length': 3.1610978520286395, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 63, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '197685', 'n_tokens_mistral': 1184, 'n_tokens_neox': 1164, 'n_words': 436}