packages feed

tiger-1.1: src/Tiger.hs

module Main where

import Prelude hiding (exp)
import UU.Parsing
import TigerScanner (scanFile)
import UU.Scanner.Token
import UU.Scanner.Position
import UU.Scanner.TokenParser
import TigerSem(sem_Program)
import TigerError(sem_Error)
import TigerAS
import TigerTypes
import System.Environment(getArgs)
import UU.Scanner.GenTokenSymbol
import UU.Scanner.GenTokenOrd

pBracksPos p = (,) <$> pOBrackPos <*> p <* pCBrack

ident :: Parser Token Ident
ident = uncurry Id <$> (pVaridPos <|> pConidPos)

integer :: Parser Token (Integer,Pos)
integer = (\(v,p) -> (read v,p) ) <$> pIntegerPos

string :: Parser Token (String,Pos)
string =  pStringPos
{-
Precedence of the operators (high to low):

* / 		-- left
+ -		-- left
>= <= = <> < >	-- non
&		-- left
|		-- left
:= 		-- right
-}



main = do args <- getArgs
          case args of
           [fn] -> parseFile fn
           _    -> putStrLn "usage: tiger <file>"

parseFile f = do text <- readFile f
                 putStrLn text
                 tokens <- scanFile  f
                 ast <- parseIO program tokens
                 --print ast
                 mapM (putStrLn.sem_Error)
                      (sem_Program ast)
                 return ()
{-
 where keywords = ["array", "if", "then", "else", "while", "for", "to", "do", "let", "in", "end", "of", "break", "nil", "function", "var", "type" ]
       keyops   = [".",":", "+", "-", "*", "/", "=", "<>", "<", "<=", ">", ">=", "&", "|", ":=" ]
       symbols  = ",;()[]{}"
       opchars  = ":+-*/=<>&.|"
-}
program = Program <$> exp


oper ops = case ops of
             [] -> error "empty operator list"
             [x] -> mkOp x
             _   -> foldr1 (<|>) (map mkOp ops)
  where mkOp x = Op x <$> pKeyPos x

operators = [ (["*", "/"                       ], LeftAssoc)
            , (["+", "-"                       ], LeftAssoc)
            , ([">=", "<=", "=", "<>", "<", ">"], NonAssoc )
            , (["&"                            ], LeftAssoc)
            , (["|"                            ], LeftAssoc)
            ]

expression = foldl f atom operators
 where f p (ops,assoc) = case assoc of
                          LeftAssoc  -> pChainl (oper ops) p
                          RightAssoc -> pChainr (oper ops) p
                          NonAssoc   -> p <??>  (oper ops <*> p)

data Assoc = LeftAssoc | RightAssoc | NonAssoc deriving Show

assignField = AssignField <$> ident <*  pKey "=" <*> exp

exp =  Assign <$> lvalue <*> pKeyPos ":=" <*> exp
   <|> expression

atom =  Nil <$> pKeyPos "nil"
    <|> uncurry IntLit <$> integer
    <|> uncurry StringLit <$> string
    <|> RecordVal <$> type_ident <*> pCurly (pListSep (pKey ",") assignField)
    <|> LValue <$> lvalue
    <|> Apply <$>ident <*> pParens (pListSep (pKey ",") exp)
    <|> pParens exps
    <|> Let   <$> pKeyPos "let" <*> decs
              <* pKey "in" <*> exps
              <* pKey "end"
    <|> ArrayVal  <$> type_ident <*> pBracks exp <* pKey "of" <*> exp
    <|> (\p e -> UnOp p "-" e) <$> pKeyPos "-" <*> exp
    <|> Break <$> pKeyPos "break"
  -- Control structures
    <|> If <$> pKeyPos "if" <*> exp
                            <*  pKey "then" <*> exp
                            <*> ((pKey "else" *> exp) `opt` Skip)
    <|> While <$> pKeyPos "while" <*> exp
              <*  pKey "do" <*> exp
    <|> For   <$> pKeyPos "for" <*> ident <* pKey ":=" <*> exp <* pKey "to" <*> exp
              <*  pKey "do" <*> exp

lvalue = (\i f -> f (Ident i)) <$> ident <*> subOrFields
  where subOrFields = (\xs x -> foldl (flip ($)) x xs) <$> pList subOrField
  	subOrField  =  (\p f e -> Dot p e f)   <$>  pKeyPos "." <*> ident
	  	   <|> (\(p,i) e -> Sub p e i) <$> pBracksPos exp

exps = f <$> pListSep (pKey ";") exp
 where f xs = case xs of
               []  -> Skip
               [x] -> x
               _   -> foldr1 Sequence xs

decs = pList declGroup

declGroup =  FunDecs  <$> pList1 funDec
         <|> TypeDecs <$> pList1 typeDec
         <|> varDec

typeDec = TypeDec <$> pKeyPos "type" <*> ident <* pKey "=" <*> ty
varDec  = VarDec  <$> pKeyPos "var" <*> ident <*> optType <* pKey ":=" <*> exp
funDec  = FunDec  <$> pKeyPos "function" <*> ident <*> pParens tyfields <*> optType <* pKey "=" <*> exp

optType = (Just <$ pKey ":" <*> type_ident) `opt` Nothing
-- Types
ty  =  Var <$> type_ident
   <|> Record <$> pCurly tyfields
   <|> Array <$ pKey "array" <* pKey "of" <*> type_ident

tyfields = pListSep (pKey ",") tyfield
 where tyfield = TypedVar <$> ident <* pKey ":" <*> type_ident

type_ident  = ident