@@ -21,7 +21,7 @@ import qualified Data.Set as S
2121import qualified Data.HashSet as HS
2222import qualified Data.Map as M
2323import qualified Data.List as L
24−import Control.Applicative (liftA, (<*), (*>))
24+import Control.Applicative (liftA, (<*), (*>), (<*>), (<$>))
2525import Control.Monad.State
2626import System.Console.Haskeline
2727import System.IO
@@ -191,6 +191,14 @@ ungroupP = do
191191 rvaAttrName <- identifier
192192 return $ Ungroup (T.pack rvaAttrName)
193193
194+extendP :: Parser RelationalExpr
195+extendP = do
196+ reservedOp "extend"
197+ expr <- relExpr
198+ reservedOp ":"
199+ tupleExpr <- braces tupleExpressionP
200+ return $ Extend tupleExpr expr
201+
194202relOperators = [
195203 [Postfix projectOp],
196204 [Postfix renameP],
@@ -203,7 +211,7 @@ relOperators = [
203211 ]
204212
205213relExpr :: Parser RelationalExpr
206−relExpr = buildExpressionParser relOperators relTerm
214+relExpr = extendP <|> buildExpressionParser relOperators relTerm
207215
208216databaseExpr :: Parser DatabaseExpr
209217databaseExpr = insertP
@@ -500,7 +508,7 @@ interpretNO context tutdstring = case parseString tutdstring of
500508 Left err -> (Just err, context)
501509 Right parsed -> runState (evalContextExpr parsed) context
502510
503−-- for interpreter-specific operations
511+-- for interpreter-specific operations
504512interpretOps :: U.UUID -> DisconnectedTransaction -> TransactionGraph -> String -> (DisconnectedTransaction, TransactionGraph, TutorialDOperatorResult)
505513interpretOps newUUID trans@(DisconnectedTransaction _ context) transGraph instring = case parse interpreterOps "" instring of
506514 Left _ -> (trans, transGraph, NoActionResult)
@@ -588,3 +596,17 @@ intAtomP = do
588596displayTransactionGraph :: TransactionGraph -> String
589597displayTransactionGraph (TransactionGraph _ transSet) = L.intercalate "\n" $ S.foldr (\(Transaction tUUID pUUID _ ) acc -> acc ++ [show tUUID ++ " " ++ show pUUID]) [] transSet
590598-}
599+
600+multiTupleExpressionP :: Parser TupleExpr
601+multiTupleExpressionP = MultipleTupleExpr <$> (sepBy tupleExpressionP comma)
602+
603+tupleExpressionP :: Parser TupleExpr
604+tupleExpressionP = attributeTupleExpressionP
605+
606+attributeTupleExpressionP :: Parser TupleExpr
607+attributeTupleExpressionP = do
608+ newAttr <- identifier
609+ reservedOp ":="
610+ attr <- identifier
611+ return $ AttributeTupleExpr (T.pack newAttr) (T.pack attr)
612+