packages feed

data-structure-inferrer-1.0: Il/Parser.y

{
{-# OPTIONS_GHC -w #-}
module Il.Parser where

import Il.Lexer
import Il.AST
import Defs.Common

import Prelude
}

%name parse funlist

%tokentype { Token }
%error     { parseError }

%token
	And             { (_,TkAnd)	}
	Assign          { (_,TkAssign) 	}
	Comma           { (_,TkComma)  	}
	Dec		{ (_,TkDec) 	}
	Div           	{ (_,TkDiv) 	}
	Ds		{ (_,TkDs)	}
	DsElem		{ (_,TkDsElem)	}
	Else		{ (_,TkElse)   	}
	Equals          { (_,TkEquals) 	}
	TFalse		{ (_,TkFalse)	}
	For		{ (_,TkFor)	}
	GEqual		{ (_,TkGEqual)	}
	Greater		{ (_,TkGreater)	}
	If		{ (_,TkIf)     	}
	Inc		{ (_,TkInc) 	}
	Int		{ (_,TkInt $$) 	}
	LCParen         { (_,TkLCParen)	}
	LSParen		{ (_,TkLSParen) }
	LEqual		{ (_,TkLEqual)	}
	LParen          { (_,TkLParen) 	}
	Less		{ (_,TkLess)	}
	Minus		{ (_,TkMinus)  	}
	Mul           	{ (_,TkMul) 	}
	Name		{ (_,TkName $$)	}
	Newline		{ (_,TkNewline) }
	Not		{ (_,TkNot)     }
	Null		{ (_,TkNull)	}
	Or              { (_,TkOr)   	}
	Plus            { (_,TkPlus)  	}
	RCParen         { (_,TkRCParen) }
	RSParen		{ (_,TkRSParen) }
	Return		{ (_,TkReturn)	}
	RParen          { (_,TkRParen) 	}
	Semicolon       { (_,TkSemicolon)}
	Then		{ (_,TkThen) 	}
	TTrue		{ (_,TkTrue)	}
	TInt		{ (_,TkTInt)	}
	TBool		{ (_,TkTBool)	}
	TVoid		{ (_,TkTVoid)	}
	While		{ (_,TkWhile)	}

%left Else RParen
%nonassoc Not
%nonassoc Assign
%left And Or
%nonassoc Less Greater GEqual LEqual Equals
%left Plus Minus
%left Mul Div
%nonassoc Inc Dec
%nonassoc Newline
%%

funlist :: { [Function] }
funlist:	fundef funlist			{ $1:$2 }
funlist:	fundef Newline funlist		{ $1:$3 }
		| 				{ [] }

fundef :: { Function }
fundef:		type Name LParen argdef RParen block		{ Function (F $2) $1 $4 $6 }
		| type Name LParen argdef RParen Newline block	{ Function (F $2) $1 $4 $7 }

argdef :: { [(VariableName, Type)] }
argdef:		nvtype Name Comma argdef	{ (V $2, $1):$4 }
      		| nvtype Name			{ [(V $2, $1)] }
		| 				{ [] }

type :: { Type }
type:		TVoid				{ TVoid }
    		| nvtype			{ $1 }

nvtype :: { Type }
nvtype:		TInt				{ TInt }
    		| TBool				{ TBool }
		| Ds				{ Ds }
		| DsElem			{ DsElem }
		| LSParen trecordintern RSParen { TRec $2 }

trecordintern :: { [(Name, Type)] }
trecordintern:	trecordpair Comma trecordintern { $1 : $3 }
	     	| trecordpair 			{ [$1] }

trecordpair :: { (Name, Type) }
trecordpair:	nvtype Name 			{ ($2, $1) }

expr :: { Term }
expr:		Name Assign valexpr							{ Assign (V $1) $3 }
		| nvtype Name Assign valexpr						{ InitAssign (V $2) $4 $1 }
		| nvtype Name								{ VarInit (V $2) $1 }
		| block									{ $1 }
		| If valexpr Then expr Else expr 					{ If $2 $4 $6 }
		| If valexpr Newline Then expr Newline Else expr 			{ If $2 $5 $8 }
		| For LParen expr Semicolon valexpr Semicolon expr RParen expr 		{ While $5 (Block [$3, $7, $9]) }
		| For LParen expr Semicolon valexpr Semicolon expr RParen Newline expr 	{ While $5 (Block [$3, $7, $10]) }
		| While LParen valexpr RParen expr					{ While $3 $5 }
		| While LParen valexpr RParen Newline expr				{ While $3 $6 }
		| Return valexpr							{ Return $2 }
		| shexpr								{ $1 }

shexpr :: { Term }
shexpr:		Inc Name				{ Inc (V $2) }
		| Name Inc				{ Inc (V $1) }
		| Dec Name				{ Dec (V $2) }
		| Name Dec				{ Dec (V $1) }
		| Name LParen commaseparatedlist RParen { Funcall (F $1) $3 }

valexpr :: { Term }
valexpr:	Name					{ Var (V $1) }
    		| Null					{ Int 0 }
    		| Int					{ Int $1 }
		| TFalse				{ Int 0 }
		| TTrue					{ Int 1 }
		| Not valexpr				{ Not $2 }
		| valexpr And valexpr			{ And $1 $3 }
		| valexpr Or valexpr			{ Or $1 $3 }
		| valexpr Plus valexpr			{ Sum $1 $3 }
		| valexpr Minus valexpr			{ Sub $1 $3 }
		| valexpr Mul valexpr			{ Mul $1 $3 }
		| valexpr Div valexpr			{ Div $1 $3 }
		| valexpr Equals valexpr		{ Eq $1 $3 }
		| valexpr LEqual valexpr		{ Leq $1 $3 }
		| valexpr GEqual valexpr		{ Geq $1 $3 }
		| valexpr Greater valexpr		{ Gt $1 $3 }
		| valexpr Less valexpr			{ Lt $1 $3 }
		| LParen valexpr RParen			{ $2 }
		| record				{ $1 }
		| shexpr				{ $1 }

record :: { Term }
record:		LSParen RSParen 			{ Record [] }
      		| LSParen recordintern RSParen		{ Record $2 }

recordintern :: { [(Name, Term)] }
recordintern: 	recordpair Comma recordintern		{ $1 : $3 }
	    	| recordpair				{ [$1] }


recordpair :: { (Name, Term) }
recordpair:	Name Assign valexpr			{ ($1, $3) }

block :: { Term }
block:		LCParen Newline exprlist RCParen	{ Block $3 }
		| LCParen exprlist RCParen		{ Block $2 }
     		| LCParen RCParen			{ Block [] }
     		| LCParen Newline RCParen		{ Block [] }

exprlist :: { [Term] }
exprlist:	block exprlist				{ $1:$2 } 
		| expr Newline exprlist			{ $1:$3 }
		| expr Newline				{ [$1] }
		| expr 					{ [$1] }

commaseparatedlist :: { [Term] }
commaseparatedlist: 	valexpr Comma commaseparatedlist { $1:$3 }
		  	| valexpr			 { [$1] }
		  	| 				 { [] }
{

parseError :: [Token] -> a
parseError (((line,col),t):xs) = error $ "Parse error at line " ++ (show line) ++ ", column " ++ (show col)
parseError [] = error "Parse error at the end"

}