diff options
-rw-r--r-- | projects/10/JackParser.hs | 129 |
1 files changed, 77 insertions, 52 deletions
diff --git a/projects/10/JackParser.hs b/projects/10/JackParser.hs index e2962a7..a2418c0 100644 --- a/projects/10/JackParser.hs +++ b/projects/10/JackParser.hs @@ -12,22 +12,25 @@ data JClassVarDec = JClassVarDec JClassVarScope JTypeAndId deriving (Show, Eq) data JSubroutineDec = JSubroutineDec JSubroutineHeader JSubroutineBody deriving (Show, Eq) data JSubroutineHeader = JSubroutineHeader JSubroutineType JTypeAndId [JTypeAndId] deriving (Show, Eq) data JSubroutineBody = JSubroutineBody [JTypeAndId] [JStatement] deriving (Show, Eq) -data JStatement = JLetStatment JLeftVarId JExpression +data JStatement = JLetStatment JVarId JExpression | JIfStatement JExpression [JStatement] (Maybe [JStatement]) | JWhileStatment JExpression [JStatement] | JDoStatement JSubroutineCall | JReturnStatement (Maybe JExpression) deriving (Show, Eq) -data JExpression = JExpression JTerm [(JBOp, JTerm)] deriving (Show, Eq) -- JBOp can only be one of +-*/&|<>= -data JTerm = JIntConst Int +--data JExpression = JExpression JTerm [(JBOp, JTerm)] deriving (Show, Eq) -- JBOp can only be one of +-*/&|<>= +data JExpression = JIntConst Int | JStrConst [Char] | JKeywordConst [Char] -- can only be true, false, null or this - | JTermVarId JLeftVarId - | JTermCall JSubroutineCall - | JTermExp JExpression - | JUnaryOpTerm JUOp JTerm -- JOp can only be - or ~ here + | JExpVar JVarId + | JExpCall JSubroutineCall + | JExpUna JUOp JExpression -- JOp can only be - or ~ here + | JExpBin JExpression [(JBOp, JExpression)] + -- | JTermVarId JLeftVarId + -- | JTermCall JSubroutineCall + -- | JTermExp JExpression deriving (Show, Eq) -data JLeftVarId = JLeftVarId JIdentifier (Maybe JExpression) deriving (Show, Eq) +data JVarId = JVarId JIdentifier (Maybe JExpression) deriving (Show, Eq) data JSubroutineCall = JSubroutineCall JIdentifier (Maybe JIdentifier) [JExpression] deriving (Show, Eq) type JBOp = Char type JUOp = Char @@ -44,8 +47,8 @@ type JackParser = Parsec [Char] () binaryOpChars = "+-*/&|<>=" unaryOpChars = "-~" keywordConstStrs = ["true", "false", "null", "this"] -typeStrs' = ["int", "char", "boolean"] -typeStrs = typeStrs' ++ ["void"] +primTypeStrs = ["int", "char", "boolean"] +primTypeStrs' = primTypeStrs ++ ["void"] classVarScopeStrs = ["static", "field"] subroutineTypeStrs = ["constructor", "function", "method"] alphaUnderscore = ['a' .. 'z'] ++ ['A' .. 'Z'] ++ ['_'] @@ -64,22 +67,36 @@ jClass = do string "class" >> many1 space id <- jIdentifier many space >> char '{' - classVarDecs <- sepBy jClassVarDecs (many space) - subroutineDecs <- sepBy jSubroutineDec (many space) + --classVarDecs <- sepBy jClassVarDecs (many space) + classVarDecs <- many $ try (many space >> jClassVarDecs) + --subroutineDecs <- sepBy jSubroutineDec (many space) + subroutineDecs <- many $ try (many space >> jSubroutineDec) many space >> char '}' return $ JClass id (mconcat classVarDecs) subroutineDecs +jClassType :: JackParser [Char] +jClassType = do + x <- oneOf ['A' .. 'Z'] + xs <- many $ oneOf alphaNumUnderscore + return $ x:xs + jBOp :: JackParser JBOp jBOp = oneOf binaryOpChars jUOp :: JackParser JUOp jUOp = oneOf unaryOpChars +jPrimType :: JackParser JType +jPrimType = choice $ string <$> primTypeStrs + jType :: JackParser JType -jType = choice $ string <$> typeStrs +jType = choice [jPrimType, jClassType] + +jPrimType' :: JackParser JType +jPrimType' = choice $ string <$> primTypeStrs' jType' :: JackParser JType -jType' = choice $ string <$> typeStrs' +jType' = choice [jPrimType', jClassType] jClassVarScope :: JackParser JClassVarScope jClassVarScope = choice $ string <$> classVarScopeStrs @@ -94,7 +111,7 @@ jIdentifier = do return $ x:xs jClassVarDecs :: JackParser [JClassVarDec] -jClassVarDecs = try $ do +jClassVarDecs = do scope <- jClassVarScope many1 space typeAndIds <- jTypeAndIds @@ -114,7 +131,7 @@ jTypeAndId p = do jTypeAndIds :: JackParser [JTypeAndId] jTypeAndIds = do - type_ <- jType' + type_ <- jType many1 space ids <- sepBy jIdentifier (many space >> char ',' >> many space) return $ (\x -> (type_, x)) <$> ids @@ -122,7 +139,7 @@ jTypeAndIds = do jParameters :: JackParser [JTypeAndId] jParameters = do char '(' >> many space - params <- sepBy (jTypeAndId jType') (many space >> char ',' >> many space) + params <- sepBy (jTypeAndId jType) (try $ many space >> char ',' >> many space) many space >> char ')' return params @@ -130,58 +147,58 @@ jSubroutineHeader :: JackParser JSubroutineHeader jSubroutineHeader = do subtype <- jSubroutineType many1 space - typeAndId <- jTypeAndId jType + typeAndId <- jTypeAndId jType' params <- jParameters return $ JSubroutineHeader subtype typeAndId params -jTerm :: JackParser JTerm -jTerm = choice [jIntConst, jStrConst, jKeywordConst, jTermVarId, jTermCall, jTermExp, jUnaryOpTerm, jTermInBraces] +jExpression :: JackParser JExpression +jExpression = jExpBin <|> jTerm + +jTerm :: JackParser JExpression +jTerm = choice [jIntConst, jStrConst, jKeywordConst, jExpCall, jExpVar, jExpUna, jExpInBraces] -jIntConst :: JackParser JTerm +jIntConst :: JackParser JExpression jIntConst = JIntConst <$> (read <$> many1 digit) -jStrConst :: JackParser JTerm +jStrConst :: JackParser JExpression jStrConst = JStrConst <$> between (char '"') (char '"') (many $ noneOf "\"") -jKeywordConst :: JackParser JTerm +jKeywordConst :: JackParser JExpression jKeywordConst = JKeywordConst <$> (choice $ string <$> keywordConstStrs) -jTermVarId :: JackParser JTerm -jTermVarId = JTermVarId <$> jLeftVarId +jExpVar :: JackParser JExpression +jExpVar = JExpVar <$> jVarId -jLeftVarId :: JackParser JLeftVarId -jLeftVarId = do +jVarId :: JackParser JVarId +jVarId = do id <- jIdentifier maybeArray <- optionMaybe $ try (char '[' >> jExpression <* char ']') - return $ JLeftVarId id maybeArray - -jTermCall :: JackParser JTerm -jTermCall = JTermCall <$> jSubroutineCall + return $ JVarId id maybeArray -jTermExp :: JackParser JTerm -jTermExp = JTermExp <$> jExpression +jExpCall :: JackParser JExpression +jExpCall = JExpCall <$> jSubroutineCall -jUnaryOpTerm :: JackParser JTerm -jUnaryOpTerm = do +jExpUna :: JackParser JExpression +jExpUna = do op <- oneOf unaryOpChars many space - term <- jTerm - return $ JUnaryOpTerm op term + x <- jTerm + return $ JExpUna op x -jTermInBraces :: JackParser JTerm -jTermInBraces = between (char '(') (char ')') jTerm +jExpInBraces :: JackParser JExpression +jExpInBraces = between (char '(') (char ')') jExpression -- expressions like a + () is not allowed -jExpression :: JackParser JExpression -jExpression = do +jExpBin :: JackParser JExpression +jExpBin = try $ do x <- jTerm - xs <- many jOpAndTerm - return $ JExpression x xs + xs <- many1 jOpAndTerm + return $ JExpBin x xs -jOpAndTerm :: JackParser (JBOp, JTerm) +jOpAndTerm :: JackParser (JBOp, JExpression) jOpAndTerm = do op <- many space >> jBOp - term <- many space >> jTerm - return (op, term) + x <- many space >> jTerm + return (op, x) jSubroutineDec :: JackParser JSubroutineDec jSubroutineDec = do @@ -192,9 +209,9 @@ jSubroutineDec = do jSubroutineBody :: JackParser JSubroutineBody jSubroutineBody = do - char '{' >> many space - varDecs <- sepBy jVarDecs (many space) - stmts <- sepBy jStatement (many space) + char '{' + varDecs <- many $ try (many space >> jVarDecs) + stmts <- many $ try (many space >> jStatement) many space >> char '}' return $ JSubroutineBody (mconcat varDecs) stmts @@ -204,7 +221,7 @@ jStatement = choice [jLetStatement, jIfStatement, jWhileStatement, jDoStatement, jLetStatement :: JackParser JStatement jLetStatement = do string "let" >> many1 space - leftVarId <- jLeftVarId + leftVarId <- jVarId many space >> char '=' >> many space exp <- jExpression many space >> char ';' @@ -248,10 +265,18 @@ jReturnStatement = do return $ JReturnStatement res jSubroutineCall :: JackParser JSubroutineCall -jSubroutineCall = do +jSubroutineCall = try $ do callee <- jIdentifier method <- optionMaybe $ try (char '.' >> jIdentifier) + args <- emptyArgs <|> someArgs + return $ JSubroutineCall callee method args + +emptyArgs :: JackParser [JExpression] +emptyArgs = return [] <* (try $ char '(' >> many space >> char ')') + +someArgs :: JackParser [JExpression] +someArgs = do char '(' >> many space exps <- sepBy jExpression (many space >> char ',' >> many space) many space >> char ')' - return $ JSubroutineCall callee method exps + return exps |