hwhile-0.1.1.0: src/lib/SourceParser.y
{
module SourceParser where
import Lexer
import PureSyntax
import SugarSyntax
import Control.Monad.Except
}
%name parseProg PROGRAM
%name parseExpr EXPR
%name parseComm COMMAND
%name parseLVal LVAL
%monad { ExceptT String IO }
%tokentype { Token }
%error { parseError }
%right IsEq
%right ConsPre
%right ConsInf
%right Hd Tl
%left SemiCo
%token
Dot { Token ( _, TkDot , _ ) }
OpenBrc { Token ( _, TkOpenBrc , _ ) }
ClosBrc { Token ( _, TkClosBrc , _ ) }
OpenCur { Token ( _, TkOpenCur , _ ) }
ClosCur { Token ( _, TkClosCur , _ ) }
OpenSqu { Token ( _, TkOpenSqu , _ ) }
ClosSqu { Token ( _, TkClosSqu , _ ) }
OpenAng { Token ( _, TkOpenAng , _ ) }
ClosAng { Token ( _, TkClosAng , _ ) }
Comma { Token ( _, TkComma , _ ) }
IsEq { Token ( _, TkIsEq , _ ) }
Assign { Token ( _, TkAssign , _ ) }
Nil { Token ( _, TkNil , _ ) }
SemiCo { Token ( _, TkSemiCo , _ ) }
Cons { Token ( _, TkCons , _ ) }
Hd { Token ( _, TkHd , _ ) }
Tl { Token ( _, TkTl , _ ) }
While { Token ( _, TkWhile , _ ) }
Switch { Token ( _, TkSwitch , _ ) }
Case { Token ( _, TkCase , _ ) }
Default { Token ( _, TkDefault , _ ) }
Colon { Token ( _, TkColon , _ ) }
If { Token ( _, TkIf , _ ) }
Else { Token ( _, TkElse , _ ) }
Read { Token ( _, TkRead , _ ) }
Write { Token ( _, TkWrite , _ ) }
True { Token ( _, TkTrue , _ ) }
False { Token ( _, TkFalse , _ ) }
AtAsgn { Token ( _, TkAtomAsgn , _ ) }
AtDoAsgn { Token ( _, TkAtomDoAsgn , _ ) }
AtWhile { Token ( _, TkAtomWhile , _ ) }
AtDoWhile { Token ( _, TkAtomDoWhile , _ ) }
AtIf { Token ( _, TkAtomIf , _ ) }
AtDoIf { Token ( _, TkAtomDoIf , _ ) }
AtVar { Token ( _, TkAtomVar , _ ) }
AtQuote { Token ( _, TkAtomQuote , _ ) }
AtHd { Token ( _, TkAtomHd , _ ) }
AtDoHd { Token ( _, TkAtomDoHd , _ ) }
AtTl { Token ( _, TkAtomTl , _ ) }
AtDoTl { Token ( _, TkAtomDoTl , _ ) }
AtCons { Token ( _, TkAtomCons , _ ) }
AtDoCons { Token ( _, TkAtomDoCons , _ ) }
Var { Token ( _, ITkVar _ , _ ) }
Int { Token ( _, ITkInt $$ , _ ) }
%%
PROGRAM :: { SuProgram }
PROGRAM : VAR Read VAR BLOCK Write VAR { SuProgram $1 $3 $4 $6 }
VAR :: { Name }
VAR : Var { Name (tkPath $1, tkVarName $1) }
EXPR :: { Expression }
EXPR : Cons EXPR EXPR { Cons $2 $3 }
| VAR { Var $1 }
| OpenBrc EXPR ClosBrc { $2 }
| Hd EXPR { Hd $2 }
| Tl EXPR { Tl $2 }
| EXPR IsEq EXPR { IsEq $1 $3 }
| EXPLIST { expFromHaskellList $1 }
| VAL { Lit $1 }
ATOM :: { ETree }
ATOM : AtAsgn { intToTree 2 }
| AtDoAsgn { intToTree 3 }
| AtWhile { intToTree 5 }
| AtDoWhile { intToTree 7 }
| AtIf { intToTree 11 }
| AtDoIf { intToTree 13 }
| AtVar { intToTree 17 }
| AtQuote { intToTree 19 }
| AtHd { intToTree 23 }
| AtDoHd { intToTree 29 }
| AtTl { intToTree 31 }
| AtDoTl { intToTree 37 }
| AtCons { intToTree 41 }
| AtDoCons { intToTree 43 }
EXPLIST :: { [Expression] }
EXPLIST : OpenSqu ClosSqu { [] }
| OpenSqu EXPR RESTEXPLIST { $2 : $3 }
RESTEXPLIST :: { [Expression] }
RESTEXPLIST : Comma EXPR RESTEXPLIST { $2 : $3 }
| ClosSqu { [] }
COMMAND :: { SuCommand }
COMMAND : VAR Assign EXPR
{ SuAssign (Info (tkPath $2, tkLineNo $2)) $1 $3 }
| VAR Assign OpenAng VAR ClosAng EXPR
{ Macro (Info (tkPath $2, tkLineNo $2)) $1 (nameName $4) $6 }
| While EXPR BLOCK
{ SuWhile (Info (tkPath $1, tkLineNo $1)) $2 $3 }
| If EXPR BLOCK Else BLOCK
{ SuIfElse (Info (tkPath $1, tkLineNo $1)) $2 $3 $5 }
| If EXPR BLOCK
{ SuIfElse (Info (tkPath $1, tkLineNo $1)) $2 $3 [] }
| Switch EXPR OpenCur SWITCHCONT
{ Switch (Info (tkPath $1, tkLineNo $1)) $2 (fst $4) (snd $4) }
BLOCK :: { SuBlock }
BLOCK : OpenCur ClosCur { [] }
| OpenCur CMDS ClosCur { $2 }
CMDS :: { SuBlock }
CMDS : COMMAND SemiCo CMDS { $1 : $3 }
| COMMAND { [$1] }
SWITCHCONT :: { ([(Expression, SuBlock)], SuBlock) }
SWITCHCONT : Case EXPR Colon CMDS SWITCHCONT { (($2, $4) : fst $5, snd $5) }
| ClosCur { ([] , [] ) }
| Default Colon CMDS ClosCur { ([] , $3 ) }
VAL :: { ETree }
VAL : Nil { ENil }
| OpenAng VAL Dot VAL ClosAng { ECons $2 $4 }
| Int { intToTree $1 }
| True { intToTree 1 }
| False { intToTree 0 }
| ATOM { $1 }
-- LVALs are VALs, but also with lists allowed. They are only used for command
-- line input, as adding lists to general VALs that occur within EXPs casues
-- ambiguity.
LVAL :: { ETree }
LVAL : Nil { ENil }
| OpenAng LVAL Dot LVAL ClosAng { ECons $2 $4 }
| Int { intToTree $1 }
| True { intToTree 1 }
| False { intToTree 0 }
| LVALLIST { treeFromHaskellList $1 }
| ATOM { $1 }
LVALLIST :: { [ETree] }
LVALLIST : OpenSqu ClosSqu { [] }
| OpenSqu LVAL RESTLVALLIST { $2 : $3 }
RESTLVALLIST :: { [ETree] }
RESTLVALLIST : Comma LVAL RESTLVALLIST { $2 : $3 }
| ClosSqu { [] }
{
parseError :: [Token] -> ExceptT String IO a
parseError [] = throwError "Parse error: reached end of file while parsing"
parseError (tok : rest) = throwError $ concat
[ "Parse error: "
, (prettyPrintToken tok)
, " in program/macro '"
, tkPath tok
, "', at line "
, (show (tkLineNo tok))
, ", char "
, (show (tkCharNo tok))
]
}