diff --git a/Interpreter.hs b/Interpreter.hs index 6c4d9a6f1d114a65e218126c628c0953eec0a606..b33e9d84f63baa8ee922d192f052822ca37bf05e 100644 --- a/Interpreter.hs +++ b/Interpreter.hs @@ -16,7 +16,8 @@ main = do args <- getArgs case args of (srcname:_) -> interpret srcname - _ -> interpret "solutions/pr2.cql" + --_ -> interpret "solutions/pr3.cql" + _ -> interpret "sampleprogram.txt" interpret :: FilePath -> IO () -- the main function, takes in file name, prints out result diff --git a/Lexer.x b/Lexer.x index 7dc070ef9d206945f2fae21371c245601a54b3e0..e25b36b18d0868b4d2dbd4bdde75f0c217a151d1 100644 --- a/Lexer.x +++ b/Lexer.x @@ -21,6 +21,10 @@ isEmpty {\p s -> TokenIsEmpty p } filter {\p s -> TokenFilter p } true {\p s -> TokenTrue p } false {\p s -> TokenFalse p } +let {\p s -> TokenLet p } +if {\p s -> TokenIf p } +else {\p s -> TokenElse p } +then {\p s -> TokenThen p } \.in {\p s -> TokenInSet p } \.out {\p s -> TokenOutSet p } \[ {\p s -> TokenLeftSqBracket p } @@ -28,7 +32,8 @@ false {\p s -> TokenFalse p } "->" {\p s -> TokenArrow p } "==" {\p s -> TokenisEqual p } "/=" {\p s -> TokenisNotEqual p } -"+" {\p s -> TokenPlus p } +"+" {\p s -> TokenPlus p } +\= {\p s -> TokenEqual p } \( {\p s -> TokenLeftBracket p } \) {\p s -> TokenRightBracket p } \: {\p s -> TokenCol p } @@ -37,11 +42,11 @@ false {\p s -> TokenFalse p } \, {\p s -> TokenComma p } \. {\p s -> TokenFullStop p } x {\p s -> TokenXProduct p } -xx {\p s -> TokenXXProduct p } +xx {\p s -> TokenXXProduct p } map {\p s -> TokenMap p } $lower [$lower $digit \_ \']* {\p s -> TokenVarName p s } $upper[$alpha]* {\p s -> TokenSetName p s } ---$posDigit$digit* {\p s -> TokenPosNat p (read s) } +--$posDigit$digit* {\p s -> TokenPosNat p (read s) } $digit+ {\p s -> TokenNat p (read s) } \"[$alpha $digit]+\" {\p s -> TokenString p (init.tail $ s) } @@ -50,11 +55,11 @@ $digit+ {\p s -> TokenNat p (read s) } --token type: data Token = TokenFilter AlexPosn | - TokenIsEmpty AlexPosn | - TokenContains AlexPosn | + TokenIsEmpty AlexPosn | + TokenContains AlexPosn | TokenSetName AlexPosn String | TokenNat AlexPosn Int | - TokenPosNat AlexPosn Int | + TokenPosNat AlexPosn Int | TokenVarName AlexPosn String | TokenTrue AlexPosn | TokenFalse AlexPosn | @@ -64,19 +69,24 @@ data Token = TokenArrow AlexPosn | TokenisEqual AlexPosn | TokenisNotEqual AlexPosn | - TokenPlus AlexPosn | + TokenPlus AlexPosn | TokenLeftBracket AlexPosn | TokenRightBracket AlexPosn | TokenSemiCol AlexPosn | - TokenCol AlexPosn | + TokenCol AlexPosn | TokenLambda AlexPosn | TokenComma AlexPosn | TokenFullStop AlexPosn | TokenInSet AlexPosn | TokenXProduct AlexPosn | - TokenXXProduct AlexPosn | + TokenXXProduct AlexPosn | TokenOutSet AlexPosn | - TokenMap AlexPosn + TokenMap AlexPosn | + TokenLet AlexPosn | + TokenIf AlexPosn | + TokenElse AlexPosn | + TokenThen AlexPosn | + TokenEqual AlexPosn deriving (Eq, Show) @@ -111,5 +121,9 @@ pos token = case token of (TokenXXProduct p ) -> p (TokenOutSet p ) -> p (TokenMap p) -> p - + (TokenLet p) -> p + (TokenElse p) -> p + (TokenIf p) -> p + (TokenThen p) -> p + (TokenEqual p) -> p } \ No newline at end of file diff --git a/Parser.y b/Parser.y index 426d5e870e774728af224dd86330c2cb9402ed8d..6bbeaab5fc2f09d09b620241bd22e51d4e78fa5a 100644 --- a/Parser.y +++ b/Parser.y @@ -9,7 +9,6 @@ import CSV %tokentype {Token} %error {parseError} ---\\map(\r -> r[1,2,3]) %token filter { TokenFilter _ } @@ -17,7 +16,7 @@ import CSV out { TokenOutSet _ } SetName { TokenSetName _ $$ } Nat { TokenNat _ $$ } - PosNat { TokenPosNat _ $$ } + PosNat { TokenPosNat _ $$ } VarName { TokenVarName _ $$ } true { TokenTrue _ } false { TokenFalse _ } @@ -44,16 +43,21 @@ import CSV contains { TokenContains _ } -- isSubstring { TokenIsSubstring _ } isEmpty { TokenIsEmpty _ } + let { TokenLet _} + if { TokenIf _} + else { TokenElse _} + then { TokenThen _} + '=' { TokenEqual _} %right "->" %left "/=" "==" ';' -%right '+' +%nonassoc '(' %% Prog : in SetDecls out SetFuncCalls {($2,$4)} -SetDecl : SetName':'PosNat {$1} +SetDecl : SetName':'Nat {$1} SetDecls : SetDecl {[$1]} | SetDecls','SetDecl {$3:$1} @@ -64,35 +68,38 @@ SetNames : SetName {[$1]} VarNames : VarName {[$1]} | VarName ',' VarNames {$1:$3} -SetFuncCalls : SetFuncCall';' {[$1]} - | SetFuncCall';' SetFuncCalls {$1:$3} +SetFuncCalls : SetFuncCall';' {[$1]} + | SetFuncCall';' SetFuncCalls {$1:$3} -SetFuncCall : filter '['SetName']' '('Func')' {FuncCall (PredefFunc Filter) [Var $3] [$6]} - | filter '('Func')' {FuncCall (PredefFunc Filter) [] [$3]} - --| map '['SetName']' '('Func')' {FuncCall (PredefFunc Map) [Var $3] [$6]} - | map '('Func')' {FuncCall (PredefFunc Map) [] [$3]} +SetFuncCall : filter '['SetName']' '('Expr')' {FuncCall (PredefFunc Filter) [Var $3] [$6]} + | filter '('Expr')' {FuncCall (PredefFunc Filter) [] [$3]} + --| map '['SetName']' '('Expr')' {FuncCall (PredefFunc Map) [Var $3] [$6]} + | map '('Expr')' {FuncCall (PredefFunc Map) [] [$3]} | SetName x SetName {FuncCall (PredefFunc XProduct) (map Var [$1, $3]) []} - -Func : '\\' '(' VarNames ')' "->" Expr { FuncDef [] $3 $6 } - - -Expr : Expr "==" Expr {FuncCall (PredefFunc IsEqual) [] [$1, $3]} - | Expr'['Nat']' {FuncCall (PredefFunc RecordIndex) [] [$1, Types.Int $3]} - | Expr'['Nat','Nats']' {FuncCall (PredefFunc RecordSelect) [] ($1:(map Types.Int ($3:$5))) } - | Function'('Exprs')' {FuncCall $1 [] $3} - | Str {Types.String $ stripWhitespace $1} - | VarName {Var $1} - | Record {$1} - | true {Boolean True} - | false {Boolean False} + | let VarName '=' Expr {Let $2 $4} + + + +Expr : Expr "==" Expr {FuncCall (PredefFunc IsEqual) [] [$1, $3]} + | Expr'['Nat']' {FuncCall (PredefFunc RecordIndex) [] [$1, Types.Int $3]} + | Expr'['Nat','Nats']' {FuncCall (PredefFunc RecordSelect) [] ($1:(map Types.Int ($3:$5))) } + | Function'('Exprs')' {FuncCall $1 [] $3} + | '\\' '(' VarNames ')' "->" Expr { FuncDef [] $3 $6 } + | if Expr then Expr else Expr {If $2 $4 $6} + | Str {Types.String $ stripWhitespace $1} + | VarName {Var $1} + | Record {$1} + | true {Boolean True} + | false {Boolean False} + | '(' Expr ')' {$2} --TODO brackets Function : PredefFunc {PredefFunc $1} | VarName { Var $1} PredefFunc : isEmpty {IsEmpty} --- | isSubstring {IsSubstring} | contains {Contains} + | isEmpty {IsEmpty} -- | zip {Zip} -- | Map -- | Mapr @@ -107,6 +114,7 @@ Nats : Nat {[$1]} | Nat ',' Nats {$1:$3} { + parseError :: [Token] -> a parseError tokens = error $ "Parse error: " ++ (show.pos.head) tokens diff --git a/Types.hs b/Types.hs index 83952e084e618344e7afd444f49ffd530c8b7de3..020b79cd7d3c53fd0a900bd9202bc8e1360e8c97 100644 --- a/Types.hs +++ b/Types.hs @@ -12,6 +12,8 @@ data PredefFunc = XProduct | XXProduct | IsEqual | IsNotEqual | Plus --operators | RecordIndex -- [] operator | RecordSelect | IsEmpty | NotEmpty | Contains -- string functions + | And + | Or deriving (Show, Eq) @@ -24,7 +26,6 @@ data PredefFunc = XProduct | XXProduct | IsEqual | IsNotEqual | Plus --operators data Expr = Control Expr [Expr] -- result of last computation, sequence of instructions | FuncCall {func::Expr, inputSets::[Expr], args::[Expr]} -- args: function to call, input sets, extra argument. Applicable for all kinds of functions: the set functions e.g. filter, map or simple functions or even the operators e.g. ==, /= ! We don't define separate expr for each operator - | FuncDef {inputSetNames::[SymbolName], argsNames::[SymbolName], body::Expr} -- function definition | If Expr Expr Expr | Set [Expr] diff --git a/sampleprogram.txt b/sampleprogram.txt index 25021ecea2a8e47b355fd3e9fd1d7d07293e7a6e..6e4db43ce75394cfcfea7a333c0e74911ea91083 100644 --- a/sampleprogram.txt +++ b/sampleprogram.txt @@ -1,5 +1,6 @@ .in -SampleSet +SampleSet:4 .out -filter (\(r) -> r[0] == "hello") \ No newline at end of file +let f = \(r) -> r[1] == "hello"; +filter[SampleSet](f); \ No newline at end of file