packages feed

happy-arbitrary-0.0.1: src/Language/Happy/Parser.y

{
{-# LANGUAGE CPP               #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell   #-}
module Language.Happy.Parser
    ( parseGrammar
    , source
    ) where

import qualified Data.ByteString       as BS
import           Data.FileEmbed        (embedFile)
import           Data.Fix              (Fix (..))
import           Data.Text             (Text)
import qualified Data.Text             as Text
import           Language.Happy.Ast    (Node, NodeF (..))
import           Language.Happy.Lexer  (Alex, AlexPosn (..), Lexeme (..),
                                        alexError, alexMonadScan)
import           Language.Happy.Tokens (LexemeClass (..))
}

%expect 0

%name parseGrammar Grammar

%error {parseError}
%errorhandlertype explist
%lexer {lexwrap} {L _ Eof _}
%monad {Alex}
%tokentype {Term}
%token
    ID_NAME			{ L _ IdName			_ }

    '{}'			{ L _ LitCode			_ }

    '%errorhandlertype'		{ L _ KwErrorhandlertype	_ }
    '%error'			{ L _ KwError			_ }
    '%expect'			{ L _ KwExpect			_ }
    '%left'			{ L _ KwLeft			_ }
    '%lexer'			{ L _ KwLexer			_ }
    '%monad'			{ L _ KwMonad			_ }
    '%name'			{ L _ KwName			_ }
    '%right'			{ L _ KwRight			_ }
    '%token'			{ L _ KwToken			_ }
    '%tokentype'		{ L _ KwTokentype		_ }

    '%%'			{ L _ PctPercentPercent		_ }
    '::'			{ L _ PctColonColon		_ }
    ':'				{ L _ PctColon			_ }
    '|'				{ L _ PctPipe			_ }

    LIT_STRING			{ L _ LitString			_ }
    LIT_INTEGER			{ L _ LitInteger		_ }

%%

Grammar :: { NonTerm }
Grammar
:	Code Pragmas '%%' Rules Code			{ Fix $ Grammar $1 $2 $4 $5 }

Code :: { [Term] }
Code
:	'{}'						{ [$1] }
|	Code '{}'					{ $1 ++ [$2] }

Pragmas :: { [NonTerm] }
Pragmas
:	Pragma						{ [$1] }
|	Pragmas Pragma					{ $1 ++ [$2] }

Pragma :: { NonTerm }
Pragma
:	'%expect' LIT_INTEGER				{ Fix $ PragmaExpect $2 }
|	'%name' ID_NAME ID_NAME				{ Fix $ PragmaName $2 $3 }
|	'%errorhandlertype' ID_NAME			{ Fix $ PragmaErrorHandlerType $2 }
|	'%error' '{}'					{ Fix $ PragmaError $2 }
|	'%lexer' '{}' '{}'				{ Fix $ PragmaLexer $2 $3 }
|	'%monad' '{}'					{ Fix $ PragmaMonad $2 }
|	'%tokentype' '{}'				{ Fix $ PragmaTokenType $2 }
|	'%token' Tokens					{ Fix $ PragmaToken $2 }
|	'%left' TokenNames				{ Fix $ PragmaLeft $2 }
|	'%right' TokenNames				{ Fix $ PragmaRight $2 }

TokenNames :: { [Term] }
TokenNames
:	TokenName					{ [$1] }
|	TokenNames TokenName				{ $1 ++ [$2] }

Tokens :: { [NonTerm] }
Tokens
:	Token						{ [$1] }
|	Tokens Token					{ $1 ++ [$2] }

Token :: { NonTerm }
Token
:	TokenName '{}'					{ Fix $ Token $1 $2 }

TokenName :: { Term }
TokenName
:	LIT_STRING					{ $1 }
|	ID_NAME						{ $1 }

Rules :: { [NonTerm] }
Rules
:	Rule						{ [$1] }
|	Rules Rule					{ $1 ++ [$2] }

Rule :: { NonTerm }
Rule
:	RuleType RuleDefn				{ Fix $ Rule $1 $2 }

RuleType :: { NonTerm }
RuleType
:	ID_NAME '::' '{}'				{ Fix $ RuleType $1 $3 }

RuleDefn :: { NonTerm }
RuleDefn
:	ID_NAME ':' RuleLines				{ Fix $ RuleDefn $1 $3 }

RuleLines :: { [NonTerm] }
RuleLines
:	RuleLine					{ [$1] }
|	RuleLines '|' RuleLine				{ $1 ++ [$3] }

RuleLine :: { NonTerm }
RuleLine
:	TokenNames '{}'					{ Fix $ RuleLine $1 $2 }


{
type Term = Lexeme Text
type NonTerm = Node Term

parseError :: Show text => (Lexeme text, [String]) -> Alex a
parseError (L (AlexPn _ line col) c t, options) =
    alexError $ ":" <> show line <> ":" <> show col <> ": Parse error near " <> show c <> ": "
        <> show t <> "; expected one of " <> show options

lexwrap :: (Lexeme Text -> Alex a) -> Alex a
lexwrap = (alexMonadScan >>=)

source :: BS.ByteString
#ifdef SOURCE
source = $(embedFile SOURCE)
#else
source = BS.empty
#endif
}