packages feed

atuin-0.1.1: src/Parser.y

{ -- -*-Haskell-*-
{-# OPTIONS_GHC -fglasgow-exts #-}

module Parser where

import Char
import Turtle
import Lexer

}

%name mkparse Program

%tokentype { Token }
%monad { P } { thenP } { returnP }
%lexer { lexer } { TokenEOF }

%token 
      name            { TokenName $$ }
      string          { TokenString $$ }
      char            { TokenChar $$ }
      int             { TokenInt $$ }
      bool            { TokenBool $$ }
      col             { TokenMkCol $$ }
      let             { TokenLet }
      in              { TokenIn }
      if              { TokenIf }
      then            { TokenThen }
      else            { TokenElse }
      repeat          { TokenRepeat }
      '('             { TokenOB }
      ')'             { TokenCB }
      '{'             { TokenOCB }
      '}'             { TokenCCB }
      '['             { TokenOSB }
      ']'             { TokenCSB }
      '+'             { TokenPlus }
      '-'             { TokenMinus }
      '*'             { TokenTimes }
      '/'             { TokenDivide }
      '='             { TokenEquals }
      eq              { TokenEQ }
      le              { TokenLE }
      ge              { TokenGE }
      '<'             { TokenLT }
      '>'             { TokenGT }
      ';'             { TokenSemi }
      ','             { TokenComma }
      eval            { TokenEval }
      forward         { TokenFD }
      right           { TokenRight }
      left            { TokenLeft }
      colour          { TokenColour }
      penup           { TokenPenUp }
      pendown         { TokenPenDown }

%nonassoc NONE
%left eq 
%left ';'
%left '<' '>' le ge 
%left '+' '-' 
%left '*' '/' 
%left NEG

%%

Program :: { [(Id, Function)] }
Program : Function { [$1] }
        | Function Program { $1:$2 }

Function :: { (Id, Function) }
Function : name '(' Vars ')' Block { ($1, ($3, $5)) }

Vars :: { [Id] }
Vars : { [] }
     | name { [$1] }
     | name ',' Vars { $1:$3 }

TurtleProg :: { Turtle }
TurtleProg : Turtle { $1 }
           | Turtle TurtleProg { Seq $1 $2 }
           | name '=' Expr TurtleProg { Let $1 $3 $4 }

Block :: { Turtle }
Block : '{' TurtleProg '}' { $2 }
      | Turtle { $1 }

Turtle :: { Turtle }
Turtle : name '(' ExprList ')' { Call $1 $3 }
       | if Expr Block ElseBlock
               { If $2 $3 $4 }
       | eval Expr { Eval $2 }
       | repeat Expr Block { Repeat $2 $3 }
       | forward Expr { Turtle (Fd $2) }
       | right Expr { Turtle (Rt $2) }
       | left Expr { Turtle (Lt $2) }
       | colour Expr { Turtle (Colour $2) }
       | penup { Turtle PenUp }
       | pendown { Turtle PenDown }

ElseBlock :: { Turtle }
ElseBlock : { Pass }
          | else Block { $2 }

ExprList :: { [Exp] }
ExprList : Expr { [$1] }
         | Expr ',' ExprList { $1:$3 }

Expr :: { Exp }
Expr : name { Var $1 }
     | Constant { Const $1 }
     | '-' Expr %prec NEG { Infix Minus (Const (MkInt 0)) $2 }
     | Expr '+' Expr { Infix Plus $1 $3 }
     | Expr '-' Expr { Infix Minus $1 $3 }
     | Expr '*' Expr { Infix Times $1 $3 }
     | Expr '/' Expr { Infix Divide $1 $3 }
     | Expr eq Expr  { Infix Eq $1 $3 }
     | Expr '<' Expr { Infix Turtle.LT $1 $3 }
     | Expr '>' Expr { Infix Turtle.GT $1 $3 }
     | Expr le Expr  { Infix LE $1 $3 }
     | Expr ge Expr  { Infix GE $1 $3 }
     | '(' Expr ')'  { $2 }
     | '{' TurtleProg '}' { Block $2 }

Constant :: { Const }
Constant : int    { MkInt $1 }
         | string { MkString $1 }
         | char   { MkChar $1 }
         | bool   { MkBool $1 }
         | col    { MkCol $1 }

Line :: { LineNumber }
     : {- empty -}      {% getLineNo }

File :: { String } 
     : {- empty -} %prec NONE  {% getFileName }

{

parse :: String -> FilePath -> Result [(Id, Function)]
parse s fn = mkparse s fn 1

parseFile :: FilePath -> IO (Result [(Id, Function)])
parseFile fn = do s <- readFile fn
                  let x = parse s fn
                  return x

}