diff --git a/Stage6/CodeGen.hs b/Stage6/CodeGen.hs new file mode 100644 index 0000000..48857c6 --- /dev/null +++ b/Stage6/CodeGen.hs @@ -0,0 +1,313 @@ +{-# OPTIONS_GHC -Wno-missing-fields #-} + +module CodeGen where + +import Data.List +import qualified Data.Map as Map +import LabelLink (replaceLabels) +import SymbolTable +import SyntaxTree +import XsmGen + +allRegs :: [String] +allRegs = ["R" ++ show i | i <- [0 .. 19]] + +-- | freeRegisters -> (register, remainingRegisters) +-- | Get a free register +getReg :: [String] -> (String, [String]) +getReg [] = error "Out of registers" +getReg (r : remainingRegs) = (r, remainingRegs) + +-- | freeRegisters -> usedRegisters +-- | Returns the list of used registers +getRegsUsed :: [String] -> [String] +getRegsUsed freeRegs = allRegs \\ freeRegs + +-- | resolves a symbol name and returns the address in a register +-- | symName -> reg -> globalSymbolT -> localSymbolT -> (code, sym) +symbolResolve :: String -> String -> GSymbolTable -> LSymbolTable -> String +symbolResolve name r gst lst = case Map.lookup name lst of + Just (_, lAddr) -> genMovXsm r "BP" ++ genArmcXsm '+' r (show lAddr) + Nothing -> genMovXsm r (show $ getSymbolAddress (gst Map.! name)) + +-- | varName -> resolver -> freeRegs -> GSymbolTable -> LSymbolTable -> (code, reg, remainingRegs) +-- | Returns code to resolve a variable value and stores the address in a register +genValResolveCode :: String -> VarResolve -> [String] -> GSymbolTable -> LSymbolTable -> (String, String, [String]) +genValResolveCode name Simple regs gst lst = (symCode ++ genMovXsm valReg (genMemAccXsm symReg), valReg, regs2) + where + (valReg, regs2) = getReg regs + (symReg, _) = getReg regs2 + symCode = symbolResolve name symReg gst lst +genValResolveCode name Deref regs gst lst = + ( symCode + ++ genMovXsm tempReg (genMemAccXsm symReg) + ++ genMovXsm valReg (genMemAccXsm tempReg), + valReg, + regs2 + ) + where + (valReg, regs2) = getReg regs + (symReg, regs3) = getReg regs2 + (tempReg, _) = getReg regs3 + symCode = symbolResolve name symReg gst lst +genValResolveCode name (Index i) regs gst lst = + ( symCode + ++ iCode + ++ genArmcXsm '+' iReg symReg + ++ genMovXsm valReg (genMemAccXsm iReg), + valReg, + regs2 + ) + where + (valReg, regs2) = getReg regs + (symReg, regs3) = getReg regs2 + symCode = symbolResolve name symReg gst lst + (iCode, iReg, _, _) = genCode Args {node = i, regsFree = regs3, gSymTable = gst, lSymTable = lst, labels = [], blockLabels = Nothing} +genValResolveCode name (Index2D i j) regs gst lst = + ( symCode + ++ iCode + ++ jCode + ++ genArmcXsm '*' iReg (show n) + ++ genArmcXsm '+' iReg jReg + ++ genArmcXsm '+' iReg symReg + ++ genMovXsm valReg (genMemAccXsm iReg), + valReg, + regs2 + ) + where + (valReg, regs2) = getReg regs + (symReg, regs3) = getReg regs2 + (Arr2 _ m n _) = gst Map.! name + symCode = symbolResolve name symReg gst lst + (iCode, iReg, regs4, _) = genCode Args {node = i, regsFree = regs3, gSymTable = gst, lSymTable = lst, labels = [], blockLabels = Nothing} + (jCode, jReg, _, _) = genCode Args {node = j, regsFree = regs4, gSymTable = gst, lSymTable = lst, labels = [], blockLabels = Nothing} + +-- | varName -> resolver -> freeRegs -> GSymbolTable -> LSymbolTable -> (code, reg, remainingRegs) +-- | Returns code to resolve a variable address and stores the address in a register +genAddrResolveCode :: String -> VarResolve -> [String] -> GSymbolTable -> LSymbolTable -> (String, String, [String]) +genAddrResolveCode name Simple regs gst lst = (symCode, symReg, regs2) + where + (symReg, regs2) = getReg regs + symCode = symbolResolve name symReg gst lst +genAddrResolveCode name Deref regs gst lst = + ( symCode ++ genMovXsm valReg (genMemAccXsm symReg), + valReg, + regs2 + ) + where + (valReg, regs2) = getReg regs + (symReg, regs3) = getReg regs2 + symCode = symbolResolve name symReg gst lst +genAddrResolveCode name (Index i) regs gst lst = + ( symCode + ++ iCode + ++ genArmcXsm '+' symReg iReg, + symReg, + regs2 + ) + where + (symReg, regs2) = getReg regs + (iCode, iReg, _, _) = genCode Args {node = i, regsFree = regs2, gSymTable = gst, lSymTable = lst} + symCode = symbolResolve name symReg gst lst +genAddrResolveCode name (Index2D i j) regs gst lst = + ( symCode + ++ iCode + ++ jCode + ++ genArmcXsm '*' iReg (show n) + ++ genArmcXsm '+' iReg jReg + ++ genArmcXsm '+' symReg iReg, + symReg, + regs2 + ) + where + (symReg, regs2) = getReg regs + (iCode, iReg, regs3, _) = genCode Args {node = i, regsFree = regs2, gSymTable = gst, lSymTable = lst, labels = [], blockLabels = Nothing} + symCode = symbolResolve name symReg gst lst + (Arr2 _ m n _) = gst Map.! name + (jCode, jReg, _, _) = genCode Args {node = j, regsFree = regs3, gSymTable = gst, lSymTable = lst, labels = [], blockLabels = Nothing} + +data CodeArgs = Args + { node :: SyntaxTree, + regsFree :: [String], + labels :: [String], + blockLabels :: Maybe (String, String), + gSymTable :: GSymbolTable, + lSymTable :: LSymbolTable + } + +-- | syntaxTree -> freeRegisters -> labels -> Maybe (startLabel, endLabel) -> (code, usedregister, remainingRegisters, remainingLabels) +-- | Generates code for the given syntax tree +genCode :: CodeArgs -> (String, String, [String], [String]) +genCode a@Args {node = (LeafValInt num)} = (genMovXsm r $show num, r, remainingRegs, labels) + where + (r, remainingRegs) = getReg regsFree + Args {regsFree = regsFree, labels = labels} = a +genCode a@Args {node = (LeafValStr val)} = (genMovXsm r val, r, remainingRegs, labels) + where + (r, remainingRegs) = getReg regsFree + Args {regsFree = regsFree, labels = labels} = a +genCode a@Args {node = (LeafVar var resolver)} = (code, r, rs, labels) + where + Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst} = a + (code, r, rs) = genValResolveCode var resolver regsFree gst lst +genCode a@Args {node = (LeafFn name params)} = + ( pushRegCode + ++ pushArgCode + ++ genStackXsm PUSH "R0" + ++ genCallXsm (accessLabel fnLabel) + ++ genStackXsm POP returnReg + ++ popArgCode + ++ popRegCode, + returnReg, + rs, + labels + ) + where + Args {regsFree = regsFree, labels = labels, gSymTable = gst} = a + usedRegs = getRegsUsed regsFree + pushRegCode = concatMap (genStackXsm PUSH) usedRegs + getArgCode p = let (pCode, pReg, _, _) = genCode a {node = p} in pCode ++ genStackXsm PUSH pReg + pushArgCode = concatMap getArgCode params + (Func _ _ fnLabel) = gst Map.! name + (returnReg, rs) = getReg regsFree + popArgCode = concat $ replicate (length params) $ genStackXsm POP (head rs) + popRegCode = concatMap (genStackXsm POP) (reverse usedRegs) +genCode a@Args {node = (NodeRef (LeafVar var resolver))} = (argCode, r, rem, labels) + where + Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst} = a + (argCode, r, rem) = genAddrResolveCode var resolver regsFree gst lst +genCode a@Args {node = (NodeArmc op l r)} = (lCode ++ rCode ++ genArmcXsm op lReg rReg, lReg, regRemaining, labels) + where + (lCode, lReg, regRemaining, _) = genCode a {node = l} + (rCode, rReg, _, _) = genCode a {node = r, regsFree = regRemaining} + Args {labels = labels} = a +genCode a@Args {node = (NodeBool op l r)} = (lCode ++ rCode ++ genBoolXsm op lReg rReg, lReg, regRemaining, labels) + where + (lCode, lReg, regRemaining, _) = genCode a {node = l} + (rCode, rReg, _, _) = genCode a {node = r, regsFree = regRemaining} + Args {labels = labels} = a +genCode a@Args {node = (NodeAssign (LeafVar var varResolver) r)} = (rCode ++ lCode ++ genMovXsm (genMemAccXsm lReg) rReg, "", regsFree, labels) + where + (rCode, rReg, regs2, _) = genCode a {node = r} + (lCode, lReg, _) = genAddrResolveCode var varResolver regs2 gst lst + Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst} = a +genCode a@Args {node = (NodeStmt "Write" arg)} = (argCode ++ genLibXsm "Write" libArgs (head regRemaining), "", regsFree, labels) + where + (argCode, argReg, regRemaining, _) = genCode a {node = arg} + libArgs = (ValInt $ -2, Reg argReg, None) + Args {regsFree = regsFree, labels = labels} = a +genCode a@Args {node = (NodeStmt "Read" arg)} = (argCode ++ genLibXsm "Read" libArgs (head regRem), "", regsFree, labels) + where + libArgs = (ValInt $ -1, Reg argReg, None) + (LeafVar var varResolver) = arg + (argCode, argReg, regRem) = genAddrResolveCode var varResolver regsFree gst lst + Args {regsFree = regsFree, labels = labels, gSymTable = gst, lSymTable = lst} = a +genCode a@Args {node = (NodeIf cond exec)} = + ( condCode ++ genJmpZXsm condReg endLabel ++ blockCode ++ genLabelXsm endLabel, + "", + regsFree, + remainingLabels + ) + where + endLabel : labels2 = labels + (condCode, condReg, _, _) = genCode a {node = cond} + (blockCode, _, _, remainingLabels) = genCode a {node = exec, labels = labels2} + Args {regsFree = regsFree, labels = labels} = a +genCode a@Args {node = (NodeIfElse cond bl1 bl2)} = + ( condCode ++ genJmpZXsm condReg elseLabel ++ bl1Code ++ genJmpXsm endLabel + ++ genLabelXsm elseLabel + ++ bl2Code + ++ genLabelXsm endLabel, + "", + regsFree, + remainingLabels + ) + where + elseLabel : labels2 = labels + endLabel : labels3 = labels2 + (condCode, condReg, _, _) = genCode a {node = cond} + (bl1Code, _, _, labels5) = genCode a {node = bl1, labels = labels3} + (bl2Code, _, _, remainingLabels) = genCode a {node = bl2, labels = labels5} + Args {regsFree = regsFree, labels = labels} = a +genCode a@Args {node = (NodeWhile cond exec)} = + ( genLabelXsm label ++ condCode ++ genJmpZXsm condReg endLabel ++ blockCode + ++ genJmpXsm label + ++ genLabelXsm endLabel, + "", + regsFree, + remainingLabels + ) + where + label : labels2 = labels + endLabel : labels3 = labels2 + (condCode, condReg, _, _) = genCode a {node = cond} + (blockCode, _, _, remainingLabels) = genCode a {node = exec, labels = labels3, blockLabels = Just (label, endLabel)} + Args {regsFree = regsFree, labels = labels} = a +genCode Args {node = NodeBreak, regsFree = fr, labels = lb, blockLabels = bl} = (code, "", fr, lb) + where + code = case bl of + Nothing -> "" + Just (_, el) -> genJmpXsm el +genCode Args {node = NodeCont, regsFree = fr, labels = lb, blockLabels = bl} = (code, "", fr, lb) + where + code = case bl of + Nothing -> "" + Just (sl, _) -> genJmpXsm sl +genCode a@Args {node = (NodeConn l r)} = (lCode ++ rCode, rReg, regsFree, remainingLabels) + where + (lCode, _, _, labels2) = genCode a {node = l} + (rCode, rReg, _, remainingLabels) = genCode a {node = r, labels = labels2} + Args {regsFree = regsFree} = a +genCode a@Args {node = (NodeReturn e)} = (eCode, eReg, regsFree, labels) + where + (eCode, eReg, rs, _) = genCode a {node = e} + Args {regsFree = regsFree, labels = labels} = a +genCode a = error $ "Invalid Node : " ++ show (node a) + +type FDef = (String, String, [String], LSymbolTable, SyntaxTree) + +-- Generates code for a function +-- FDef -> GSymbolTable -> labels -> (remainingLabels, code) +genFnCode :: FDef -> GSymbolTable -> [String] -> ([String], String) +genFnCode (_, name, params, lSym, ast) gSym labels = + ( remainingLabels, + genLabelXsm label + ++ genStackXsm PUSH "BP" + ++ genMovXsm "BP" "SP" + ++ genArmcXsm '+' "BP" "1" + ++ lVarAllocCode + ++ astCode + ++ genArmcXsm '-' "BP" "3" + ++ genMovXsm (genMemAccXsm "BP") resultReg + ++ lVarRelCode + ++ genStackXsm POP "BP" + ++ genRetXsm + ) + where + (Func _ _ label) = gSym Map.! name + lVarCount = Map.size lSym - length params + lVarAllocCode = concat $ replicate lVarCount (genStackXsm PUSH "R0") + (astCode, resultReg, _, remainingLabels) = + genCode + Args + { node = ast, + regsFree = allRegs, + labels = labels, + blockLabels = Nothing, + gSymTable = gSym, + lSymTable = lSym + } + lVarRelCode = concat $ replicate lVarCount (genStackXsm POP "R0") + +-- GSymbolTable -> sp -> fDecls -> mainBlock -> code +codeGen :: GSymbolTable -> Int -> [FDef] -> (LSymbolTable, SyntaxTree) -> String +codeGen gTable sp fDecls main = header ++ code + where + header = unlines $ map show [0, 2056, 0, 0, 0, 0, 0, 0] + (labelsRem, codeList) = mapAccumL (\a b -> genFnCode b gTable a) ["L" ++ show i | i <- [0, 1 ..]] fDecls + (mainLSym, mainAst) = main + (_, mainCode) = genFnCode ("int", "main", [], mainLSym, mainAst) gTable labelsRem + (initCode, _, _, _) = genCode Args {node = LeafFn "main" [], regsFree = allRegs, gSymTable = gTable} + labelledCode = genMovXsm "SP" (show sp) ++ initCode ++ "INT 10\n" ++ concat codeList ++ mainCode + -- code = labelledCode + code = replaceLabels labelledCode diff --git a/Stage6/Compiler.hs b/Stage6/Compiler.hs new file mode 100644 index 0000000..a686d94 --- /dev/null +++ b/Stage6/Compiler.hs @@ -0,0 +1,29 @@ +module Main where + +-- import CodeGen (codeGen) +import Parser (parseTokens) +import SymbolTable +import SyntaxTree +import System.Environment (getArgs) +import System.IO (IOMode (ReadMode, WriteMode), hClose, hGetContents, hPutStr, openFile) +import Tokens (scanTokens) + +createOutputFile :: String -> IO () +createOutputFile code = do + outputFile <- openFile "out.xsm" WriteMode + hPutStr outputFile code + hClose outputFile + +main :: IO () +main = do + args <- getArgs + inputFile <- openFile (head args) ReadMode + fileContents <- hGetContents inputFile + let (tTable, gTable, sp, fDecl, main) = parseTokens (scanTokens fileContents) + print gTable + print tTable + -- print fDecl + let (_, mainAst) = main in putStr $ prettyPrint mainAst + -- let code = codeGen gTable sp fDecl main + -- createOutputFile code + hClose inputFile diff --git a/Stage6/LabelLink.x b/Stage6/LabelLink.x new file mode 100644 index 0000000..6f92b2f --- /dev/null +++ b/Stage6/LabelLink.x @@ -0,0 +1,78 @@ +{ +module LabelLink (replaceLabels) where +import Data.Either (fromRight) +import qualified Data.Map as Map +} + +%wrapper "monadUserState" + +@label = [A-Za-z][0-9A-Za-z]* + +tokens :- + \".*\" { onGlob } + @label ":" { onLabel } + "<" @label ">" { onLabelAccess } + .|[\n] { onGlob } + +{ + +type AlexUserState = (String, Map.Map String Int) + +alexEOF = return () + +alexInitUserState :: AlexUserState +alexInitUserState = ("", Map.empty) + +getUserState :: Alex AlexUserState +getUserState = Alex $ \s -> Right (s,alex_ust s) + +modifyUserState :: (AlexUserState -> AlexUserState) -> Alex () +modifyUserState f = Alex $ \s -> Right (s { alex_ust = (f $ alex_ust s) },()) + +runAlexScan :: String -> Either String AlexUserState +runAlexScan s = runAlex s $ alexMonadScan >> getUserState + +alexRescan input map = case f (AlexState { + alex_bytes = [], + alex_pos = alexStartPos, + alex_inp = input, + alex_chr = '\n', + alex_scd = 0, + alex_ust = ("", map) +}) of + Left msg -> error "Linking Failed" + Right ( _, (newCode, _) ) -> newCode + where + Alex f = alexMonadScan >> getUserState + + +onLabel :: AlexAction() +onLabel ((AlexPn _ line _), _, _, s) len = modifyUserState (\(code, labelMap) -> (code, Map.insert labelName addr labelMap)) >> alexMonadScan + where + labelName = take (len-1) s + addr = 2056 + 2 *(line-1) + +onLabelAccess :: AlexAction() +onLabelAccess (_, _, _, s) len = modifyUserState (replaceLabel old) >> alexMonadScan + where + old = take len s + replaceLabel :: String -> AlexUserState -> AlexUserState + replaceLabel label (code, labelMap) = (code ++ new, labelMap) + where + key = init $ tail label + new = case (Map.lookup key labelMap) of + Nothing -> label + Just addr -> show addr + +onGlob :: AlexAction() +onGlob (_, _, _, s) len = modifyUserState (\(code, labelMap) -> (code ++ new, labelMap)) >> alexMonadScan + where + new = take len s + +replaceLabels::String->String +replaceLabels code = replacedCode + where + (codeNew , map) = fromRight (error "Linking failed") (runAlexScan code) + replacedCode = alexRescan codeNew map + +} \ No newline at end of file diff --git a/Stage6/Makefile b/Stage6/Makefile new file mode 100644 index 0000000..530d5ad --- /dev/null +++ b/Stage6/Makefile @@ -0,0 +1,17 @@ +all: Compiler + +Tokens.hs : Tokens.x + alex Tokens.x + +Parser.hs : Parser.y + happy Parser.y + +LabelLink.hs : LabelLink.x + alex LabelLink.x + +Compiler : Tokens.hs Parser.hs ParserState.hs Compiler.hs SyntaxTree.hs SymbolTable.hs LabelLink.hs XsmGen.hs + ghc --make Compiler -outputdir=__intermediate__ + +clean: + rm -rf Compiler Parser.hs Tokens.hs LabelLink.hs __intermediate__ + diff --git a/Stage6/Parser.info b/Stage6/Parser.info new file mode 100644 index 0000000..820a92b --- /dev/null +++ b/Stage6/Parser.info @@ -0,0 +1,2605 @@ +----------------------------------------------------------------------------- +Info file generated by Happy Version 1.20.0 from Parser.y +----------------------------------------------------------------------------- + + +rule 33 is unused +rule 34 is unused +rule 35 is unused +rule 36 is unused +rule 37 is unused +rule 38 is unused +rule 39 is unused + +terminal NULL is unused + +----------------------------------------------------------------------------- +Grammar +----------------------------------------------------------------------------- + %start_parse -> Program (0) + Program -> TypeDefBlock GDeclBlock MainBlock (1) + TypeDefBlock -> TYPE TypeDefList ENDTYPE (2) + TypeDefBlock -> TYPE ENDTYPE (3) + TypeDefBlock -> (4) + TypeDefList -> TypeDefList TypeDef (5) + TypeDefList -> TypeDef (6) + TypeDef -> id '{' FieldDeclList '}' (7) + FieldDeclList -> FieldDeclList FieldDecl (8) + FieldDeclList -> FieldDecl (9) + FieldDecl -> Type BaseVar ';' (10) + Type -> INT (11) + Type -> STR (12) + Type -> id (13) + GDeclBlock -> DECL GDeclList ENDDECL (14) + GDeclBlock -> DECL ENDDECL (15) + GDeclBlock -> (16) + GDeclList -> GDeclList GDecl (17) + GDeclList -> GDecl (18) + GDecl -> Type GVarList ';' (19) + GVarList -> GVarList ',' GDec (20) + GVarList -> GDec (21) + GDec -> BaseVar (22) + GDec -> id '(' ParamList ')' (23) + GDec -> '*' id '(' ParamList ')' (24) + GDec -> id '[' int ']' (25) + GDec -> id '[' int ']' '[' int ']' (26) + BaseVar -> id (27) + BaseVar -> '*' id (28) + ParamList -> ParamList ',' Param (29) + ParamList -> Param (30) + ParamList -> (31) + Param -> Type BaseVar (32) + FDefBlock -> FDefBlock FDef (33) + FDefBlock -> FDef (34) + FDefBlock -> (35) + FDef -> FType FName '(' ParamList ')' '{' LDeclBlock Routine '}' (36) + FType -> Type (37) + FType -> Type '*' (38) + FName -> id (39) + LDeclBlock -> DECL LDeclList ENDDECL (40) + LDeclBlock -> DECL ENDDECL (41) + LDeclBlock -> (42) + LDeclList -> LDeclList LDecl (43) + LDeclList -> LDecl (44) + LDecl -> Type LVarList ';' (45) + LVarList -> LVarList ',' BaseVar (46) + LVarList -> BaseVar (47) + Routine -> BEGIN Slist Retstmt END (48) + Routine -> BEGIN Retstmt END (49) + Retstmt -> RETURN RVal ';' (50) + RVal -> Variable (51) + RVal -> FnCall (52) + RVal -> String (53) + RVal -> E2 (54) + RVal -> '&' Variable (55) + Slist -> Slist Stmt (56) + Slist -> Stmt (57) + Stmt -> READ '(' Variable ')' ';' (58) + Stmt -> Variable '=' RVal ';' (59) + Stmt -> WRITE '(' RVal ')' ';' (60) + Stmt -> IF '(' B ')' THEN Slist ENDIF ';' (61) + Stmt -> IF '(' B ')' THEN Slist ELSE Slist ENDIF ';' (62) + Stmt -> WHILE '(' B ')' DO Slist ENDWHILE ';' (63) + Stmt -> BREAK ';' (64) + Stmt -> CONTINUE ';' (65) + Stmt -> FnCall ';' (66) + E2 -> E '+' E (67) + E2 -> E '-' E (68) + E2 -> E '*' E (69) + E2 -> E '/' E (70) + E2 -> E '%' E (71) + E2 -> '(' E2 ')' (72) + E2 -> int (73) + E -> E2 (74) + E -> FnCall (75) + E -> Variable (76) + FnCall -> id '(' ArgList ')' (77) + ArgList -> ArgList ',' RVal (78) + ArgList -> RVal (79) + ArgList -> (80) + B -> E '<' E (81) + B -> E '>' E (82) + B -> E '<=' E (83) + B -> E '>=' E (84) + B -> E '!=' E (85) + B -> E '==' E (86) + Variable -> id (87) + Variable -> id '[' E ']' (88) + Variable -> id '[' E ']' '[' E ']' (89) + Variable -> '*' id (90) + Variable -> DotField (91) + DotField -> DotField '.' id (92) + DotField -> id '.' id (93) + String -> str (94) + MainBlock -> INT Main '(' ')' '{' LDeclBlock Routine '}' (95) + Main -> MAIN (96) + +----------------------------------------------------------------------------- +Terminals +----------------------------------------------------------------------------- + int { TokenIntVal $$ } + str { TokenStrVal $$ } + id { TokenVar $$ } + '+' { TokenPlus } + '-' { TokenMinus } + '*' { TokenTimes } + '/' { TokenDiv } + '%' { TokenMod } + '(' { TokenLParen } + ')' { TokenRParen } + '[' { TokenLBox } + ']' { TokenRBox } + '{' { TokenLCurly } + '}' { TokenRCurly } + '&' { TokenAddr } + '=' { TokenAssign } + '<' { TokenLt } + '>' { TokenGt } + '<=' { TokenLtE } + '>=' { TokenGtE } + '!=' { TokenNE } + '==' { TokenEq } + '.' { TokenDot } + BEGIN { TokenBegin } + END { TokenEnd } + READ { TokenRead } + WRITE { TokenWrite } + IF { TokenIf } + THEN { TokenThen } + ELSE { TokenElse } + ENDIF { TokenEndif } + WHILE { TokenWhile } + DO { TokenDo } + ENDWHILE { TokenEndwhile } + BREAK { TokenBreak } + CONTINUE { TokenCont } + INT { TokenInt } + STR { TokenStr } + DECL { TokenDecl } + ENDDECL { TokenEndDecl } + TYPE { TokenType } + ENDTYPE { TokenEndType } + MAIN { TokenMain } + RETURN { TokenReturn } + NULL { TokenNull } + ',' { TokenComma } + ';' { TokenStmtEnd } + +----------------------------------------------------------------------------- +Non-terminals +----------------------------------------------------------------------------- + %start_parse rule 0 + Program rule 1 + TypeDefBlock rules 2, 3, 4 + TypeDefList rules 5, 6 + TypeDef rule 7 + FieldDeclList rules 8, 9 + FieldDecl rule 10 + Type rules 11, 12, 13 + GDeclBlock rules 14, 15, 16 + GDeclList rules 17, 18 + GDecl rule 19 + GVarList rules 20, 21 + GDec rules 22, 23, 24, 25, 26 + BaseVar rules 27, 28 + ParamList rules 29, 30, 31 + Param rule 32 + FDefBlock rules 33, 34, 35 + FDef rule 36 + FType rules 37, 38 + FName rule 39 + LDeclBlock rules 40, 41, 42 + LDeclList rules 43, 44 + LDecl rule 45 + LVarList rules 46, 47 + Routine rules 48, 49 + Retstmt rule 50 + RVal rules 51, 52, 53, 54, 55 + Slist rules 56, 57 + Stmt rules 58, 59, 60, 61, 62, 63, 64, 65, 66 + E2 rules 67, 68, 69, 70, 71, 72, 73 + E rules 74, 75, 76 + FnCall rule 77 + ArgList rules 78, 79, 80 + B rules 81, 82, 83, 84, 85, 86 + Variable rules 87, 88, 89, 90, 91 + DotField rules 92, 93 + String rule 94 + MainBlock rule 95 + Main rule 96 + +----------------------------------------------------------------------------- +States +----------------------------------------------------------------------------- +State 0 + + %start_parse -> . Program (rule 0) + + INT reduce using rule 4 + DECL reduce using rule 4 + TYPE shift, and enter state 3 + + Program goto state 4 + TypeDefBlock goto state 2 + +State 1 + + Program -> . TypeDefBlock GDeclBlock MainBlock (rule 1) + + TYPE shift, and enter state 3 + + TypeDefBlock goto state 2 + +State 2 + + Program -> TypeDefBlock . GDeclBlock MainBlock (rule 1) + + INT reduce using rule 16 + DECL shift, and enter state 10 + + GDeclBlock goto state 9 + +State 3 + + TypeDefBlock -> TYPE . TypeDefList ENDTYPE (rule 2) + TypeDefBlock -> TYPE . ENDTYPE (rule 3) + + id shift, and enter state 7 + ENDTYPE shift, and enter state 8 + + TypeDefList goto state 5 + TypeDef goto state 6 + +State 4 + + %start_parse -> Program . (rule 0) + + %eof accept + + +State 5 + + TypeDefBlock -> TYPE TypeDefList . ENDTYPE (rule 2) + TypeDefList -> TypeDefList . TypeDef (rule 5) + + id shift, and enter state 7 + ENDTYPE shift, and enter state 22 + + TypeDef goto state 21 + +State 6 + + TypeDefList -> TypeDef . (rule 6) + + id reduce using rule 6 + ENDTYPE reduce using rule 6 + + +State 7 + + TypeDef -> id . '{' FieldDeclList '}' (rule 7) + + '{' shift, and enter state 20 + + +State 8 + + TypeDefBlock -> TYPE ENDTYPE . (rule 3) + + INT reduce using rule 3 + DECL reduce using rule 3 + + +State 9 + + Program -> TypeDefBlock GDeclBlock . MainBlock (rule 1) + + INT shift, and enter state 19 + + MainBlock goto state 18 + +State 10 + + GDeclBlock -> DECL . GDeclList ENDDECL (rule 14) + GDeclBlock -> DECL . ENDDECL (rule 15) + + id shift, and enter state 14 + INT shift, and enter state 15 + STR shift, and enter state 16 + ENDDECL shift, and enter state 17 + + Type goto state 11 + GDeclList goto state 12 + GDecl goto state 13 + +State 11 + + GDecl -> Type . GVarList ';' (rule 19) + + id shift, and enter state 33 + '*' shift, and enter state 34 + + GVarList goto state 30 + GDec goto state 31 + BaseVar goto state 32 + +State 12 + + GDeclBlock -> DECL GDeclList . ENDDECL (rule 14) + GDeclList -> GDeclList . GDecl (rule 17) + + id shift, and enter state 14 + INT shift, and enter state 15 + STR shift, and enter state 16 + ENDDECL shift, and enter state 29 + + Type goto state 11 + GDecl goto state 28 + +State 13 + + GDeclList -> GDecl . (rule 18) + + id reduce using rule 18 + INT reduce using rule 18 + STR reduce using rule 18 + ENDDECL reduce using rule 18 + + +State 14 + + Type -> id . (rule 13) + + id reduce using rule 13 + '*' reduce using rule 13 + + +State 15 + + Type -> INT . (rule 11) + + id reduce using rule 11 + '*' reduce using rule 11 + + +State 16 + + Type -> STR . (rule 12) + + id reduce using rule 12 + '*' reduce using rule 12 + + +State 17 + + GDeclBlock -> DECL ENDDECL . (rule 15) + + INT reduce using rule 15 + + +State 18 + + Program -> TypeDefBlock GDeclBlock MainBlock . (rule 1) + + %eof reduce using rule 1 + + +State 19 + + MainBlock -> INT . Main '(' ')' '{' LDeclBlock Routine '}' (rule 95) + + MAIN shift, and enter state 27 + + Main goto state 26 + +State 20 + + TypeDef -> id '{' . FieldDeclList '}' (rule 7) + + id shift, and enter state 14 + INT shift, and enter state 15 + STR shift, and enter state 16 + + FieldDeclList goto state 23 + FieldDecl goto state 24 + Type goto state 25 + +State 21 + + TypeDefList -> TypeDefList TypeDef . (rule 5) + + id reduce using rule 5 + ENDTYPE reduce using rule 5 + + +State 22 + + TypeDefBlock -> TYPE TypeDefList ENDTYPE . (rule 2) + + INT reduce using rule 2 + DECL reduce using rule 2 + + +State 23 + + TypeDef -> id '{' FieldDeclList . '}' (rule 7) + FieldDeclList -> FieldDeclList . FieldDecl (rule 8) + + id shift, and enter state 14 + '}' shift, and enter state 45 + INT shift, and enter state 15 + STR shift, and enter state 16 + + FieldDecl goto state 44 + Type goto state 25 + +State 24 + + FieldDeclList -> FieldDecl . (rule 9) + + id reduce using rule 9 + '}' reduce using rule 9 + INT reduce using rule 9 + STR reduce using rule 9 + + +State 25 + + FieldDecl -> Type . BaseVar ';' (rule 10) + + id shift, and enter state 42 + '*' shift, and enter state 43 + + BaseVar goto state 41 + +State 26 + + MainBlock -> INT Main . '(' ')' '{' LDeclBlock Routine '}' (rule 95) + + '(' shift, and enter state 40 + + +State 27 + + Main -> MAIN . (rule 96) + + '(' reduce using rule 96 + + +State 28 + + GDeclList -> GDeclList GDecl . (rule 17) + + id reduce using rule 17 + INT reduce using rule 17 + STR reduce using rule 17 + ENDDECL reduce using rule 17 + + +State 29 + + GDeclBlock -> DECL GDeclList ENDDECL . (rule 14) + + INT reduce using rule 14 + + +State 30 + + GDecl -> Type GVarList . ';' (rule 19) + GVarList -> GVarList . ',' GDec (rule 20) + + ',' shift, and enter state 38 + ';' shift, and enter state 39 + + +State 31 + + GVarList -> GDec . (rule 21) + + ',' reduce using rule 21 + ';' reduce using rule 21 + + +State 32 + + GDec -> BaseVar . (rule 22) + + ',' reduce using rule 22 + ';' reduce using rule 22 + + +State 33 + + GDec -> id . '(' ParamList ')' (rule 23) + GDec -> id . '[' int ']' (rule 25) + GDec -> id . '[' int ']' '[' int ']' (rule 26) + BaseVar -> id . (rule 27) + + '(' shift, and enter state 36 + '[' shift, and enter state 37 + ',' reduce using rule 27 + ';' reduce using rule 27 + + +State 34 + + GDec -> '*' . id '(' ParamList ')' (rule 24) + BaseVar -> '*' . id (rule 28) + + id shift, and enter state 35 + + +State 35 + + GDec -> '*' id . '(' ParamList ')' (rule 24) + BaseVar -> '*' id . (rule 28) + + '(' shift, and enter state 54 + ',' reduce using rule 28 + ';' reduce using rule 28 + + +State 36 + + GDec -> id '(' . ParamList ')' (rule 23) + + id shift, and enter state 14 + ')' reduce using rule 31 + INT shift, and enter state 15 + STR shift, and enter state 16 + ',' reduce using rule 31 + + Type goto state 51 + ParamList goto state 52 + Param goto state 53 + +State 37 + + GDec -> id '[' . int ']' (rule 25) + GDec -> id '[' . int ']' '[' int ']' (rule 26) + + int shift, and enter state 50 + + +State 38 + + GVarList -> GVarList ',' . GDec (rule 20) + + id shift, and enter state 33 + '*' shift, and enter state 34 + + GDec goto state 49 + BaseVar goto state 32 + +State 39 + + GDecl -> Type GVarList ';' . (rule 19) + + id reduce using rule 19 + INT reduce using rule 19 + STR reduce using rule 19 + ENDDECL reduce using rule 19 + + +State 40 + + MainBlock -> INT Main '(' . ')' '{' LDeclBlock Routine '}' (rule 95) + + ')' shift, and enter state 48 + + +State 41 + + FieldDecl -> Type BaseVar . ';' (rule 10) + + ';' shift, and enter state 47 + + +State 42 + + BaseVar -> id . (rule 27) + + ')' reduce using rule 27 + ',' reduce using rule 27 + ';' reduce using rule 27 + + +State 43 + + BaseVar -> '*' . id (rule 28) + + id shift, and enter state 46 + + +State 44 + + FieldDeclList -> FieldDeclList FieldDecl . (rule 8) + + id reduce using rule 8 + '}' reduce using rule 8 + INT reduce using rule 8 + STR reduce using rule 8 + + +State 45 + + TypeDef -> id '{' FieldDeclList '}' . (rule 7) + + id reduce using rule 7 + ENDTYPE reduce using rule 7 + + +State 46 + + BaseVar -> '*' id . (rule 28) + + ')' reduce using rule 28 + ',' reduce using rule 28 + ';' reduce using rule 28 + + +State 47 + + FieldDecl -> Type BaseVar ';' . (rule 10) + + id reduce using rule 10 + '}' reduce using rule 10 + INT reduce using rule 10 + STR reduce using rule 10 + + +State 48 + + MainBlock -> INT Main '(' ')' . '{' LDeclBlock Routine '}' (rule 95) + + '{' shift, and enter state 60 + + +State 49 + + GVarList -> GVarList ',' GDec . (rule 20) + + ',' reduce using rule 20 + ';' reduce using rule 20 + + +State 50 + + GDec -> id '[' int . ']' (rule 25) + GDec -> id '[' int . ']' '[' int ']' (rule 26) + + ']' shift, and enter state 59 + + +State 51 + + Param -> Type . BaseVar (rule 32) + + id shift, and enter state 42 + '*' shift, and enter state 43 + + BaseVar goto state 58 + +State 52 + + GDec -> id '(' ParamList . ')' (rule 23) + ParamList -> ParamList . ',' Param (rule 29) + + ')' shift, and enter state 56 + ',' shift, and enter state 57 + + +State 53 + + ParamList -> Param . (rule 30) + + ')' reduce using rule 30 + ',' reduce using rule 30 + + +State 54 + + GDec -> '*' id '(' . ParamList ')' (rule 24) + + id shift, and enter state 14 + ')' reduce using rule 31 + INT shift, and enter state 15 + STR shift, and enter state 16 + ',' reduce using rule 31 + + Type goto state 51 + ParamList goto state 55 + Param goto state 53 + +State 55 + + GDec -> '*' id '(' ParamList . ')' (rule 24) + ParamList -> ParamList . ',' Param (rule 29) + + ')' shift, and enter state 65 + ',' shift, and enter state 57 + + +State 56 + + GDec -> id '(' ParamList ')' . (rule 23) + + ',' reduce using rule 23 + ';' reduce using rule 23 + + +State 57 + + ParamList -> ParamList ',' . Param (rule 29) + + id shift, and enter state 14 + INT shift, and enter state 15 + STR shift, and enter state 16 + + Type goto state 51 + Param goto state 64 + +State 58 + + Param -> Type BaseVar . (rule 32) + + ')' reduce using rule 32 + ',' reduce using rule 32 + + +State 59 + + GDec -> id '[' int ']' . (rule 25) + GDec -> id '[' int ']' . '[' int ']' (rule 26) + + '[' shift, and enter state 63 + ',' reduce using rule 25 + ';' reduce using rule 25 + + +State 60 + + MainBlock -> INT Main '(' ')' '{' . LDeclBlock Routine '}' (rule 95) + + BEGIN reduce using rule 42 + DECL shift, and enter state 62 + + LDeclBlock goto state 61 + +State 61 + + MainBlock -> INT Main '(' ')' '{' LDeclBlock . Routine '}' (rule 95) + + BEGIN shift, and enter state 72 + + Routine goto state 71 + +State 62 + + LDeclBlock -> DECL . LDeclList ENDDECL (rule 40) + LDeclBlock -> DECL . ENDDECL (rule 41) + + id shift, and enter state 14 + INT shift, and enter state 15 + STR shift, and enter state 16 + ENDDECL shift, and enter state 70 + + Type goto state 67 + LDeclList goto state 68 + LDecl goto state 69 + +State 63 + + GDec -> id '[' int ']' '[' . int ']' (rule 26) + + int shift, and enter state 66 + + +State 64 + + ParamList -> ParamList ',' Param . (rule 29) + + ')' reduce using rule 29 + ',' reduce using rule 29 + + +State 65 + + GDec -> '*' id '(' ParamList ')' . (rule 24) + + ',' reduce using rule 24 + ';' reduce using rule 24 + + +State 66 + + GDec -> id '[' int ']' '[' int . ']' (rule 26) + + ']' shift, and enter state 93 + + +State 67 + + LDecl -> Type . LVarList ';' (rule 45) + + id shift, and enter state 42 + '*' shift, and enter state 43 + + BaseVar goto state 91 + LVarList goto state 92 + +State 68 + + LDeclBlock -> DECL LDeclList . ENDDECL (rule 40) + LDeclList -> LDeclList . LDecl (rule 43) + + id shift, and enter state 14 + INT shift, and enter state 15 + STR shift, and enter state 16 + ENDDECL shift, and enter state 90 + + Type goto state 67 + LDecl goto state 89 + +State 69 + + LDeclList -> LDecl . (rule 44) + + id reduce using rule 44 + INT reduce using rule 44 + STR reduce using rule 44 + ENDDECL reduce using rule 44 + + +State 70 + + LDeclBlock -> DECL ENDDECL . (rule 41) + + BEGIN reduce using rule 41 + + +State 71 + + MainBlock -> INT Main '(' ')' '{' LDeclBlock Routine . '}' (rule 95) + + '}' shift, and enter state 88 + + +State 72 + + Routine -> BEGIN . Slist Retstmt END (rule 48) + Routine -> BEGIN . Retstmt END (rule 49) + + id shift, and enter state 79 + '*' shift, and enter state 80 + READ shift, and enter state 81 + WRITE shift, and enter state 82 + IF shift, and enter state 83 + WHILE shift, and enter state 84 + BREAK shift, and enter state 85 + CONTINUE shift, and enter state 86 + RETURN shift, and enter state 87 + + Retstmt goto state 73 + Slist goto state 74 + Stmt goto state 75 + FnCall goto state 76 + Variable goto state 77 + DotField goto state 78 + +State 73 + + Routine -> BEGIN Retstmt . END (rule 49) + + END shift, and enter state 121 + + +State 74 + + Routine -> BEGIN Slist . Retstmt END (rule 48) + Slist -> Slist . Stmt (rule 56) + + id shift, and enter state 79 + '*' shift, and enter state 80 + READ shift, and enter state 81 + WRITE shift, and enter state 82 + IF shift, and enter state 83 + WHILE shift, and enter state 84 + BREAK shift, and enter state 85 + CONTINUE shift, and enter state 86 + RETURN shift, and enter state 87 + + Retstmt goto state 119 + Stmt goto state 120 + FnCall goto state 76 + Variable goto state 77 + DotField goto state 78 + +State 75 + + Slist -> Stmt . (rule 57) + + id reduce using rule 57 + '*' reduce using rule 57 + READ reduce using rule 57 + WRITE reduce using rule 57 + IF reduce using rule 57 + ELSE reduce using rule 57 + ENDIF reduce using rule 57 + WHILE reduce using rule 57 + ENDWHILE reduce using rule 57 + BREAK reduce using rule 57 + CONTINUE reduce using rule 57 + RETURN reduce using rule 57 + + +State 76 + + Stmt -> FnCall . ';' (rule 66) + + ';' shift, and enter state 118 + + +State 77 + + Stmt -> Variable . '=' RVal ';' (rule 59) + + '=' shift, and enter state 117 + + +State 78 + + Variable -> DotField . (rule 91) + DotField -> DotField . '.' id (rule 92) + + '+' reduce using rule 91 + '-' reduce using rule 91 + '*' reduce using rule 91 + '/' reduce using rule 91 + '%' reduce using rule 91 + ')' reduce using rule 91 + ']' reduce using rule 91 + '=' reduce using rule 91 + '<' reduce using rule 91 + '>' reduce using rule 91 + '<=' reduce using rule 91 + '>=' reduce using rule 91 + '!=' reduce using rule 91 + '==' reduce using rule 91 + '.' shift, and enter state 116 + ',' reduce using rule 91 + ';' reduce using rule 91 + + +State 79 + + FnCall -> id . '(' ArgList ')' (rule 77) + Variable -> id . (rule 87) + Variable -> id . '[' E ']' (rule 88) + Variable -> id . '[' E ']' '[' E ']' (rule 89) + DotField -> id . '.' id (rule 93) + + '+' reduce using rule 87 + '-' reduce using rule 87 + '*' reduce using rule 87 + '/' reduce using rule 87 + '%' reduce using rule 87 + '(' shift, and enter state 113 + ')' reduce using rule 87 + '[' shift, and enter state 114 + ']' reduce using rule 87 + '=' reduce using rule 87 + '<' reduce using rule 87 + '>' reduce using rule 87 + '<=' reduce using rule 87 + '>=' reduce using rule 87 + '!=' reduce using rule 87 + '==' reduce using rule 87 + '.' shift, and enter state 115 + ',' reduce using rule 87 + ';' reduce using rule 87 + + +State 80 + + Variable -> '*' . id (rule 90) + + id shift, and enter state 112 + + +State 81 + + Stmt -> READ . '(' Variable ')' ';' (rule 58) + + '(' shift, and enter state 111 + + +State 82 + + Stmt -> WRITE . '(' RVal ')' ';' (rule 60) + + '(' shift, and enter state 110 + + +State 83 + + Stmt -> IF . '(' B ')' THEN Slist ENDIF ';' (rule 61) + Stmt -> IF . '(' B ')' THEN Slist ELSE Slist ENDIF ';' (rule 62) + + '(' shift, and enter state 109 + + +State 84 + + Stmt -> WHILE . '(' B ')' DO Slist ENDWHILE ';' (rule 63) + + '(' shift, and enter state 108 + + +State 85 + + Stmt -> BREAK . ';' (rule 64) + + ';' shift, and enter state 107 + + +State 86 + + Stmt -> CONTINUE . ';' (rule 65) + + ';' shift, and enter state 106 + + +State 87 + + Retstmt -> RETURN . RVal ';' (rule 50) + + int shift, and enter state 102 + str shift, and enter state 103 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + '&' shift, and enter state 105 + + RVal goto state 96 + E2 goto state 97 + E goto state 98 + FnCall goto state 99 + Variable goto state 100 + DotField goto state 78 + String goto state 101 + +State 88 + + MainBlock -> INT Main '(' ')' '{' LDeclBlock Routine '}' . (rule 95) + + %eof reduce using rule 95 + + +State 89 + + LDeclList -> LDeclList LDecl . (rule 43) + + id reduce using rule 43 + INT reduce using rule 43 + STR reduce using rule 43 + ENDDECL reduce using rule 43 + + +State 90 + + LDeclBlock -> DECL LDeclList ENDDECL . (rule 40) + + BEGIN reduce using rule 40 + + +State 91 + + LVarList -> BaseVar . (rule 47) + + ',' reduce using rule 47 + ';' reduce using rule 47 + + +State 92 + + LDecl -> Type LVarList . ';' (rule 45) + LVarList -> LVarList . ',' BaseVar (rule 46) + + ',' shift, and enter state 94 + ';' shift, and enter state 95 + + +State 93 + + GDec -> id '[' int ']' '[' int ']' . (rule 26) + + ',' reduce using rule 26 + ';' reduce using rule 26 + + +State 94 + + LVarList -> LVarList ',' . BaseVar (rule 46) + + id shift, and enter state 42 + '*' shift, and enter state 43 + + BaseVar goto state 146 + +State 95 + + LDecl -> Type LVarList ';' . (rule 45) + + id reduce using rule 45 + INT reduce using rule 45 + STR reduce using rule 45 + ENDDECL reduce using rule 45 + + +State 96 + + Retstmt -> RETURN RVal . ';' (rule 50) + + ';' shift, and enter state 145 + + +State 97 + + RVal -> E2 . (rule 54) + E -> E2 . (rule 74) + + '+' reduce using rule 74 + '-' reduce using rule 74 + '*' reduce using rule 74 + '/' reduce using rule 74 + '%' reduce using rule 74 + ')' reduce using rule 54 + ',' reduce using rule 54 + ';' reduce using rule 54 + + +State 98 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + + '+' shift, and enter state 140 + '-' shift, and enter state 141 + '*' shift, and enter state 142 + '/' shift, and enter state 143 + '%' shift, and enter state 144 + + +State 99 + + RVal -> FnCall . (rule 52) + E -> FnCall . (rule 75) + + '+' reduce using rule 75 + '-' reduce using rule 75 + '*' reduce using rule 75 + '/' reduce using rule 75 + '%' reduce using rule 75 + ')' reduce using rule 52 + ',' reduce using rule 52 + ';' reduce using rule 52 + + +State 100 + + RVal -> Variable . (rule 51) + E -> Variable . (rule 76) + + '+' reduce using rule 76 + '-' reduce using rule 76 + '*' reduce using rule 76 + '/' reduce using rule 76 + '%' reduce using rule 76 + ')' reduce using rule 51 + ',' reduce using rule 51 + ';' reduce using rule 51 + + +State 101 + + RVal -> String . (rule 53) + + ')' reduce using rule 53 + ',' reduce using rule 53 + ';' reduce using rule 53 + + +State 102 + + E2 -> int . (rule 73) + + '+' reduce using rule 73 + '-' reduce using rule 73 + '*' reduce using rule 73 + '/' reduce using rule 73 + '%' reduce using rule 73 + ')' reduce using rule 73 + ']' reduce using rule 73 + '<' reduce using rule 73 + '>' reduce using rule 73 + '<=' reduce using rule 73 + '>=' reduce using rule 73 + '!=' reduce using rule 73 + '==' reduce using rule 73 + ',' reduce using rule 73 + ';' reduce using rule 73 + + +State 103 + + String -> str . (rule 94) + + ')' reduce using rule 94 + ',' reduce using rule 94 + ';' reduce using rule 94 + + +State 104 + + E2 -> '(' . E2 ')' (rule 72) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 139 + E goto state 98 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 105 + + RVal -> '&' . Variable (rule 55) + + id shift, and enter state 133 + '*' shift, and enter state 80 + + Variable goto state 138 + DotField goto state 78 + +State 106 + + Stmt -> CONTINUE ';' . (rule 65) + + id reduce using rule 65 + '*' reduce using rule 65 + READ reduce using rule 65 + WRITE reduce using rule 65 + IF reduce using rule 65 + ELSE reduce using rule 65 + ENDIF reduce using rule 65 + WHILE reduce using rule 65 + ENDWHILE reduce using rule 65 + BREAK reduce using rule 65 + CONTINUE reduce using rule 65 + RETURN reduce using rule 65 + + +State 107 + + Stmt -> BREAK ';' . (rule 64) + + id reduce using rule 64 + '*' reduce using rule 64 + READ reduce using rule 64 + WRITE reduce using rule 64 + IF reduce using rule 64 + ELSE reduce using rule 64 + ENDIF reduce using rule 64 + WHILE reduce using rule 64 + ENDWHILE reduce using rule 64 + BREAK reduce using rule 64 + CONTINUE reduce using rule 64 + RETURN reduce using rule 64 + + +State 108 + + Stmt -> WHILE '(' . B ')' DO Slist ENDWHILE ';' (rule 63) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 135 + FnCall goto state 128 + B goto state 137 + Variable goto state 129 + DotField goto state 78 + +State 109 + + Stmt -> IF '(' . B ')' THEN Slist ENDIF ';' (rule 61) + Stmt -> IF '(' . B ')' THEN Slist ELSE Slist ENDIF ';' (rule 62) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 135 + FnCall goto state 128 + B goto state 136 + Variable goto state 129 + DotField goto state 78 + +State 110 + + Stmt -> WRITE '(' . RVal ')' ';' (rule 60) + + int shift, and enter state 102 + str shift, and enter state 103 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + '&' shift, and enter state 105 + + RVal goto state 134 + E2 goto state 97 + E goto state 98 + FnCall goto state 99 + Variable goto state 100 + DotField goto state 78 + String goto state 101 + +State 111 + + Stmt -> READ '(' . Variable ')' ';' (rule 58) + + id shift, and enter state 133 + '*' shift, and enter state 80 + + Variable goto state 132 + DotField goto state 78 + +State 112 + + Variable -> '*' id . (rule 90) + + '+' reduce using rule 90 + '-' reduce using rule 90 + '*' reduce using rule 90 + '/' reduce using rule 90 + '%' reduce using rule 90 + ')' reduce using rule 90 + ']' reduce using rule 90 + '=' reduce using rule 90 + '<' reduce using rule 90 + '>' reduce using rule 90 + '<=' reduce using rule 90 + '>=' reduce using rule 90 + '!=' reduce using rule 90 + '==' reduce using rule 90 + ',' reduce using rule 90 + ';' reduce using rule 90 + + +State 113 + + FnCall -> id '(' . ArgList ')' (rule 77) + + int shift, and enter state 102 + str shift, and enter state 103 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + ')' reduce using rule 80 + '&' shift, and enter state 105 + ',' reduce using rule 80 + + RVal goto state 130 + E2 goto state 97 + E goto state 98 + FnCall goto state 99 + ArgList goto state 131 + Variable goto state 100 + DotField goto state 78 + String goto state 101 + +State 114 + + Variable -> id '[' . E ']' (rule 88) + Variable -> id '[' . E ']' '[' E ']' (rule 89) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 127 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 115 + + DotField -> id '.' . id (rule 93) + + id shift, and enter state 125 + + +State 116 + + DotField -> DotField '.' . id (rule 92) + + id shift, and enter state 124 + + +State 117 + + Stmt -> Variable '=' . RVal ';' (rule 59) + + int shift, and enter state 102 + str shift, and enter state 103 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + '&' shift, and enter state 105 + + RVal goto state 123 + E2 goto state 97 + E goto state 98 + FnCall goto state 99 + Variable goto state 100 + DotField goto state 78 + String goto state 101 + +State 118 + + Stmt -> FnCall ';' . (rule 66) + + id reduce using rule 66 + '*' reduce using rule 66 + READ reduce using rule 66 + WRITE reduce using rule 66 + IF reduce using rule 66 + ELSE reduce using rule 66 + ENDIF reduce using rule 66 + WHILE reduce using rule 66 + ENDWHILE reduce using rule 66 + BREAK reduce using rule 66 + CONTINUE reduce using rule 66 + RETURN reduce using rule 66 + + +State 119 + + Routine -> BEGIN Slist Retstmt . END (rule 48) + + END shift, and enter state 122 + + +State 120 + + Slist -> Slist Stmt . (rule 56) + + id reduce using rule 56 + '*' reduce using rule 56 + READ reduce using rule 56 + WRITE reduce using rule 56 + IF reduce using rule 56 + ELSE reduce using rule 56 + ENDIF reduce using rule 56 + WHILE reduce using rule 56 + ENDWHILE reduce using rule 56 + BREAK reduce using rule 56 + CONTINUE reduce using rule 56 + RETURN reduce using rule 56 + + +State 121 + + Routine -> BEGIN Retstmt END . (rule 49) + + '}' reduce using rule 49 + + +State 122 + + Routine -> BEGIN Slist Retstmt END . (rule 48) + + '}' reduce using rule 48 + + +State 123 + + Stmt -> Variable '=' RVal . ';' (rule 59) + + ';' shift, and enter state 166 + + +State 124 + + DotField -> DotField '.' id . (rule 92) + + '+' reduce using rule 92 + '-' reduce using rule 92 + '*' reduce using rule 92 + '/' reduce using rule 92 + '%' reduce using rule 92 + ')' reduce using rule 92 + ']' reduce using rule 92 + '=' reduce using rule 92 + '<' reduce using rule 92 + '>' reduce using rule 92 + '<=' reduce using rule 92 + '>=' reduce using rule 92 + '!=' reduce using rule 92 + '==' reduce using rule 92 + '.' reduce using rule 92 + ',' reduce using rule 92 + ';' reduce using rule 92 + + +State 125 + + DotField -> id '.' id . (rule 93) + + '+' reduce using rule 93 + '-' reduce using rule 93 + '*' reduce using rule 93 + '/' reduce using rule 93 + '%' reduce using rule 93 + ')' reduce using rule 93 + ']' reduce using rule 93 + '=' reduce using rule 93 + '<' reduce using rule 93 + '>' reduce using rule 93 + '<=' reduce using rule 93 + '>=' reduce using rule 93 + '!=' reduce using rule 93 + '==' reduce using rule 93 + '.' reduce using rule 93 + ',' reduce using rule 93 + ';' reduce using rule 93 + + +State 126 + + E -> E2 . (rule 74) + + '+' reduce using rule 74 + '-' reduce using rule 74 + '*' reduce using rule 74 + '/' reduce using rule 74 + '%' reduce using rule 74 + ')' reduce using rule 74 + ']' reduce using rule 74 + '<' reduce using rule 74 + '>' reduce using rule 74 + '<=' reduce using rule 74 + '>=' reduce using rule 74 + '!=' reduce using rule 74 + '==' reduce using rule 74 + ',' reduce using rule 74 + ';' reduce using rule 74 + + +State 127 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + Variable -> id '[' E . ']' (rule 88) + Variable -> id '[' E . ']' '[' E ']' (rule 89) + + '+' shift, and enter state 140 + '-' shift, and enter state 141 + '*' shift, and enter state 142 + '/' shift, and enter state 143 + '%' shift, and enter state 144 + ']' shift, and enter state 165 + + +State 128 + + E -> FnCall . (rule 75) + + '+' reduce using rule 75 + '-' reduce using rule 75 + '*' reduce using rule 75 + '/' reduce using rule 75 + '%' reduce using rule 75 + ')' reduce using rule 75 + ']' reduce using rule 75 + '<' reduce using rule 75 + '>' reduce using rule 75 + '<=' reduce using rule 75 + '>=' reduce using rule 75 + '!=' reduce using rule 75 + '==' reduce using rule 75 + ',' reduce using rule 75 + ';' reduce using rule 75 + + +State 129 + + E -> Variable . (rule 76) + + '+' reduce using rule 76 + '-' reduce using rule 76 + '*' reduce using rule 76 + '/' reduce using rule 76 + '%' reduce using rule 76 + ')' reduce using rule 76 + ']' reduce using rule 76 + '<' reduce using rule 76 + '>' reduce using rule 76 + '<=' reduce using rule 76 + '>=' reduce using rule 76 + '!=' reduce using rule 76 + '==' reduce using rule 76 + ',' reduce using rule 76 + ';' reduce using rule 76 + + +State 130 + + ArgList -> RVal . (rule 79) + + ')' reduce using rule 79 + ',' reduce using rule 79 + + +State 131 + + FnCall -> id '(' ArgList . ')' (rule 77) + ArgList -> ArgList . ',' RVal (rule 78) + + ')' shift, and enter state 163 + ',' shift, and enter state 164 + + +State 132 + + Stmt -> READ '(' Variable . ')' ';' (rule 58) + + ')' shift, and enter state 162 + + +State 133 + + Variable -> id . (rule 87) + Variable -> id . '[' E ']' (rule 88) + Variable -> id . '[' E ']' '[' E ']' (rule 89) + DotField -> id . '.' id (rule 93) + + ')' reduce using rule 87 + '[' shift, and enter state 114 + '.' shift, and enter state 115 + ',' reduce using rule 87 + ';' reduce using rule 87 + + +State 134 + + Stmt -> WRITE '(' RVal . ')' ';' (rule 60) + + ')' shift, and enter state 161 + + +State 135 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + B -> E . '<' E (rule 81) + B -> E . '>' E (rule 82) + B -> E . '<=' E (rule 83) + B -> E . '>=' E (rule 84) + B -> E . '!=' E (rule 85) + B -> E . '==' E (rule 86) + + '+' shift, and enter state 140 + '-' shift, and enter state 141 + '*' shift, and enter state 142 + '/' shift, and enter state 143 + '%' shift, and enter state 144 + '<' shift, and enter state 155 + '>' shift, and enter state 156 + '<=' shift, and enter state 157 + '>=' shift, and enter state 158 + '!=' shift, and enter state 159 + '==' shift, and enter state 160 + + +State 136 + + Stmt -> IF '(' B . ')' THEN Slist ENDIF ';' (rule 61) + Stmt -> IF '(' B . ')' THEN Slist ELSE Slist ENDIF ';' (rule 62) + + ')' shift, and enter state 154 + + +State 137 + + Stmt -> WHILE '(' B . ')' DO Slist ENDWHILE ';' (rule 63) + + ')' shift, and enter state 153 + + +State 138 + + RVal -> '&' Variable . (rule 55) + + ')' reduce using rule 55 + ',' reduce using rule 55 + ';' reduce using rule 55 + + +State 139 + + E2 -> '(' E2 . ')' (rule 72) + E -> E2 . (rule 74) + + '+' reduce using rule 74 + '-' reduce using rule 74 + '*' reduce using rule 74 + '/' reduce using rule 74 + '%' reduce using rule 74 + ')' shift, and enter state 152 + + +State 140 + + E2 -> E '+' . E (rule 67) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 151 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 141 + + E2 -> E '-' . E (rule 68) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 150 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 142 + + E2 -> E '*' . E (rule 69) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 149 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 143 + + E2 -> E '/' . E (rule 70) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 148 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 144 + + E2 -> E '%' . E (rule 71) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 147 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 145 + + Retstmt -> RETURN RVal ';' . (rule 50) + + END reduce using rule 50 + + +State 146 + + LVarList -> LVarList ',' BaseVar . (rule 46) + + ',' reduce using rule 46 + ';' reduce using rule 46 + + +State 147 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + E2 -> E '%' E . (rule 71) + + '+' reduce using rule 71 + '-' reduce using rule 71 + '*' reduce using rule 71 + '/' reduce using rule 71 + '%' reduce using rule 71 + ')' reduce using rule 71 + ']' reduce using rule 71 + '<' reduce using rule 71 + '>' reduce using rule 71 + '<=' reduce using rule 71 + '>=' reduce using rule 71 + '!=' reduce using rule 71 + '==' reduce using rule 71 + ',' reduce using rule 71 + ';' reduce using rule 71 + + +State 148 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E '/' E . (rule 70) + E2 -> E . '%' E (rule 71) + + '+' reduce using rule 70 + '-' reduce using rule 70 + '*' reduce using rule 70 + '/' reduce using rule 70 + '%' reduce using rule 70 + ')' reduce using rule 70 + ']' reduce using rule 70 + '<' reduce using rule 70 + '>' reduce using rule 70 + '<=' reduce using rule 70 + '>=' reduce using rule 70 + '!=' reduce using rule 70 + '==' reduce using rule 70 + ',' reduce using rule 70 + ';' reduce using rule 70 + + +State 149 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E '*' E . (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + + '+' reduce using rule 69 + '-' reduce using rule 69 + '*' reduce using rule 69 + '/' reduce using rule 69 + '%' reduce using rule 69 + ')' reduce using rule 69 + ']' reduce using rule 69 + '<' reduce using rule 69 + '>' reduce using rule 69 + '<=' reduce using rule 69 + '>=' reduce using rule 69 + '!=' reduce using rule 69 + '==' reduce using rule 69 + ',' reduce using rule 69 + ';' reduce using rule 69 + + +State 150 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E '-' E . (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + + '+' reduce using rule 68 + '-' reduce using rule 68 + '*' shift, and enter state 142 + '/' shift, and enter state 143 + '%' shift, and enter state 144 + ')' reduce using rule 68 + ']' reduce using rule 68 + '<' reduce using rule 68 + '>' reduce using rule 68 + '<=' reduce using rule 68 + '>=' reduce using rule 68 + '!=' reduce using rule 68 + '==' reduce using rule 68 + ',' reduce using rule 68 + ';' reduce using rule 68 + + +State 151 + + E2 -> E . '+' E (rule 67) + E2 -> E '+' E . (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + + '+' reduce using rule 67 + '-' reduce using rule 67 + '*' shift, and enter state 142 + '/' shift, and enter state 143 + '%' shift, and enter state 144 + ')' reduce using rule 67 + ']' reduce using rule 67 + '<' reduce using rule 67 + '>' reduce using rule 67 + '<=' reduce using rule 67 + '>=' reduce using rule 67 + '!=' reduce using rule 67 + '==' reduce using rule 67 + ',' reduce using rule 67 + ';' reduce using rule 67 + + +State 152 + + E2 -> '(' E2 ')' . (rule 72) + + '+' reduce using rule 72 + '-' reduce using rule 72 + '*' reduce using rule 72 + '/' reduce using rule 72 + '%' reduce using rule 72 + ')' reduce using rule 72 + ']' reduce using rule 72 + '<' reduce using rule 72 + '>' reduce using rule 72 + '<=' reduce using rule 72 + '>=' reduce using rule 72 + '!=' reduce using rule 72 + '==' reduce using rule 72 + ',' reduce using rule 72 + ';' reduce using rule 72 + + +State 153 + + Stmt -> WHILE '(' B ')' . DO Slist ENDWHILE ';' (rule 63) + + DO shift, and enter state 178 + + +State 154 + + Stmt -> IF '(' B ')' . THEN Slist ENDIF ';' (rule 61) + Stmt -> IF '(' B ')' . THEN Slist ELSE Slist ENDIF ';' (rule 62) + + THEN shift, and enter state 177 + + +State 155 + + B -> E '<' . E (rule 81) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 176 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 156 + + B -> E '>' . E (rule 82) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 175 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 157 + + B -> E '<=' . E (rule 83) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 174 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 158 + + B -> E '>=' . E (rule 84) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 173 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 159 + + B -> E '!=' . E (rule 85) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 172 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 160 + + B -> E '==' . E (rule 86) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 171 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 161 + + Stmt -> WRITE '(' RVal ')' . ';' (rule 60) + + ';' shift, and enter state 170 + + +State 162 + + Stmt -> READ '(' Variable ')' . ';' (rule 58) + + ';' shift, and enter state 169 + + +State 163 + + FnCall -> id '(' ArgList ')' . (rule 77) + + '+' reduce using rule 77 + '-' reduce using rule 77 + '*' reduce using rule 77 + '/' reduce using rule 77 + '%' reduce using rule 77 + ')' reduce using rule 77 + ']' reduce using rule 77 + '<' reduce using rule 77 + '>' reduce using rule 77 + '<=' reduce using rule 77 + '>=' reduce using rule 77 + '!=' reduce using rule 77 + '==' reduce using rule 77 + ',' reduce using rule 77 + ';' reduce using rule 77 + + +State 164 + + ArgList -> ArgList ',' . RVal (rule 78) + + int shift, and enter state 102 + str shift, and enter state 103 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + '&' shift, and enter state 105 + + RVal goto state 168 + E2 goto state 97 + E goto state 98 + FnCall goto state 99 + Variable goto state 100 + DotField goto state 78 + String goto state 101 + +State 165 + + Variable -> id '[' E ']' . (rule 88) + Variable -> id '[' E ']' . '[' E ']' (rule 89) + + '+' reduce using rule 88 + '-' reduce using rule 88 + '*' reduce using rule 88 + '/' reduce using rule 88 + '%' reduce using rule 88 + ')' reduce using rule 88 + '[' shift, and enter state 167 + ']' reduce using rule 88 + '=' reduce using rule 88 + '<' reduce using rule 88 + '>' reduce using rule 88 + '<=' reduce using rule 88 + '>=' reduce using rule 88 + '!=' reduce using rule 88 + '==' reduce using rule 88 + ',' reduce using rule 88 + ';' reduce using rule 88 + + +State 166 + + Stmt -> Variable '=' RVal ';' . (rule 59) + + id reduce using rule 59 + '*' reduce using rule 59 + READ reduce using rule 59 + WRITE reduce using rule 59 + IF reduce using rule 59 + ELSE reduce using rule 59 + ENDIF reduce using rule 59 + WHILE reduce using rule 59 + ENDWHILE reduce using rule 59 + BREAK reduce using rule 59 + CONTINUE reduce using rule 59 + RETURN reduce using rule 59 + + +State 167 + + Variable -> id '[' E ']' '[' . E ']' (rule 89) + + int shift, and enter state 102 + id shift, and enter state 79 + '*' shift, and enter state 80 + '(' shift, and enter state 104 + + E2 goto state 126 + E goto state 181 + FnCall goto state 128 + Variable goto state 129 + DotField goto state 78 + +State 168 + + ArgList -> ArgList ',' RVal . (rule 78) + + ')' reduce using rule 78 + ',' reduce using rule 78 + + +State 169 + + Stmt -> READ '(' Variable ')' ';' . (rule 58) + + id reduce using rule 58 + '*' reduce using rule 58 + READ reduce using rule 58 + WRITE reduce using rule 58 + IF reduce using rule 58 + ELSE reduce using rule 58 + ENDIF reduce using rule 58 + WHILE reduce using rule 58 + ENDWHILE reduce using rule 58 + BREAK reduce using rule 58 + CONTINUE reduce using rule 58 + RETURN reduce using rule 58 + + +State 170 + + Stmt -> WRITE '(' RVal ')' ';' . (rule 60) + + id reduce using rule 60 + '*' reduce using rule 60 + READ reduce using rule 60 + WRITE reduce using rule 60 + IF reduce using rule 60 + ELSE reduce using rule 60 + ENDIF reduce using rule 60 + WHILE reduce using rule 60 + ENDWHILE reduce using rule 60 + BREAK reduce using rule 60 + CONTINUE reduce using rule 60 + RETURN reduce using rule 60 + + +State 171 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + B -> E '==' E . (rule 86) + + '+' shift, and enter state 140 + '-' shift, and enter state 141 + '*' shift, and enter state 142 + '/' shift, and enter state 143 + '%' shift, and enter state 144 + ')' reduce using rule 86 + + +State 172 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + B -> E '!=' E . (rule 85) + + '+' shift, and enter state 140 + '-' shift, and enter state 141 + '*' shift, and enter state 142 + '/' shift, and enter state 143 + '%' shift, and enter state 144 + ')' reduce using rule 85 + + +State 173 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + B -> E '>=' E . (rule 84) + + '+' shift, and enter state 140 + '-' shift, and enter state 141 + '*' shift, and enter state 142 + '/' shift, and enter state 143 + '%' shift, and enter state 144 + ')' reduce using rule 84 + + +State 174 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + B -> E '<=' E . (rule 83) + + '+' shift, and enter state 140 + '-' shift, and enter state 141 + '*' shift, and enter state 142 + '/' shift, and enter state 143 + '%' shift, and enter state 144 + ')' reduce using rule 83 + + +State 175 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + B -> E '>' E . (rule 82) + + '+' shift, and enter state 140 + '-' shift, and enter state 141 + '*' shift, and enter state 142 + '/' shift, and enter state 143 + '%' shift, and enter state 144 + ')' reduce using rule 82 + + +State 176 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + B -> E '<' E . (rule 81) + + '+' shift, and enter state 140 + '-' shift, and enter state 141 + '*' shift, and enter state 142 + '/' shift, and enter state 143 + '%' shift, and enter state 144 + ')' reduce using rule 81 + + +State 177 + + Stmt -> IF '(' B ')' THEN . Slist ENDIF ';' (rule 61) + Stmt -> IF '(' B ')' THEN . Slist ELSE Slist ENDIF ';' (rule 62) + + id shift, and enter state 79 + '*' shift, and enter state 80 + READ shift, and enter state 81 + WRITE shift, and enter state 82 + IF shift, and enter state 83 + WHILE shift, and enter state 84 + BREAK shift, and enter state 85 + CONTINUE shift, and enter state 86 + + Slist goto state 180 + Stmt goto state 75 + FnCall goto state 76 + Variable goto state 77 + DotField goto state 78 + +State 178 + + Stmt -> WHILE '(' B ')' DO . Slist ENDWHILE ';' (rule 63) + + id shift, and enter state 79 + '*' shift, and enter state 80 + READ shift, and enter state 81 + WRITE shift, and enter state 82 + IF shift, and enter state 83 + WHILE shift, and enter state 84 + BREAK shift, and enter state 85 + CONTINUE shift, and enter state 86 + + Slist goto state 179 + Stmt goto state 75 + FnCall goto state 76 + Variable goto state 77 + DotField goto state 78 + +State 179 + + Slist -> Slist . Stmt (rule 56) + Stmt -> WHILE '(' B ')' DO Slist . ENDWHILE ';' (rule 63) + + id shift, and enter state 79 + '*' shift, and enter state 80 + READ shift, and enter state 81 + WRITE shift, and enter state 82 + IF shift, and enter state 83 + WHILE shift, and enter state 84 + ENDWHILE shift, and enter state 185 + BREAK shift, and enter state 85 + CONTINUE shift, and enter state 86 + + Stmt goto state 120 + FnCall goto state 76 + Variable goto state 77 + DotField goto state 78 + +State 180 + + Slist -> Slist . Stmt (rule 56) + Stmt -> IF '(' B ')' THEN Slist . ENDIF ';' (rule 61) + Stmt -> IF '(' B ')' THEN Slist . ELSE Slist ENDIF ';' (rule 62) + + id shift, and enter state 79 + '*' shift, and enter state 80 + READ shift, and enter state 81 + WRITE shift, and enter state 82 + IF shift, and enter state 83 + ELSE shift, and enter state 183 + ENDIF shift, and enter state 184 + WHILE shift, and enter state 84 + BREAK shift, and enter state 85 + CONTINUE shift, and enter state 86 + + Stmt goto state 120 + FnCall goto state 76 + Variable goto state 77 + DotField goto state 78 + +State 181 + + E2 -> E . '+' E (rule 67) + E2 -> E . '-' E (rule 68) + E2 -> E . '*' E (rule 69) + E2 -> E . '/' E (rule 70) + E2 -> E . '%' E (rule 71) + Variable -> id '[' E ']' '[' E . ']' (rule 89) + + '+' shift, and enter state 140 + '-' shift, and enter state 141 + '*' shift, and enter state 142 + '/' shift, and enter state 143 + '%' shift, and enter state 144 + ']' shift, and enter state 182 + + +State 182 + + Variable -> id '[' E ']' '[' E ']' . (rule 89) + + '+' reduce using rule 89 + '-' reduce using rule 89 + '*' reduce using rule 89 + '/' reduce using rule 89 + '%' reduce using rule 89 + ')' reduce using rule 89 + ']' reduce using rule 89 + '=' reduce using rule 89 + '<' reduce using rule 89 + '>' reduce using rule 89 + '<=' reduce using rule 89 + '>=' reduce using rule 89 + '!=' reduce using rule 89 + '==' reduce using rule 89 + ',' reduce using rule 89 + ';' reduce using rule 89 + + +State 183 + + Stmt -> IF '(' B ')' THEN Slist ELSE . Slist ENDIF ';' (rule 62) + + id shift, and enter state 79 + '*' shift, and enter state 80 + READ shift, and enter state 81 + WRITE shift, and enter state 82 + IF shift, and enter state 83 + WHILE shift, and enter state 84 + BREAK shift, and enter state 85 + CONTINUE shift, and enter state 86 + + Slist goto state 188 + Stmt goto state 75 + FnCall goto state 76 + Variable goto state 77 + DotField goto state 78 + +State 184 + + Stmt -> IF '(' B ')' THEN Slist ENDIF . ';' (rule 61) + + ';' shift, and enter state 187 + + +State 185 + + Stmt -> WHILE '(' B ')' DO Slist ENDWHILE . ';' (rule 63) + + ';' shift, and enter state 186 + + +State 186 + + Stmt -> WHILE '(' B ')' DO Slist ENDWHILE ';' . (rule 63) + + id reduce using rule 63 + '*' reduce using rule 63 + READ reduce using rule 63 + WRITE reduce using rule 63 + IF reduce using rule 63 + ELSE reduce using rule 63 + ENDIF reduce using rule 63 + WHILE reduce using rule 63 + ENDWHILE reduce using rule 63 + BREAK reduce using rule 63 + CONTINUE reduce using rule 63 + RETURN reduce using rule 63 + + +State 187 + + Stmt -> IF '(' B ')' THEN Slist ENDIF ';' . (rule 61) + + id reduce using rule 61 + '*' reduce using rule 61 + READ reduce using rule 61 + WRITE reduce using rule 61 + IF reduce using rule 61 + ELSE reduce using rule 61 + ENDIF reduce using rule 61 + WHILE reduce using rule 61 + ENDWHILE reduce using rule 61 + BREAK reduce using rule 61 + CONTINUE reduce using rule 61 + RETURN reduce using rule 61 + + +State 188 + + Slist -> Slist . Stmt (rule 56) + Stmt -> IF '(' B ')' THEN Slist ELSE Slist . ENDIF ';' (rule 62) + + id shift, and enter state 79 + '*' shift, and enter state 80 + READ shift, and enter state 81 + WRITE shift, and enter state 82 + IF shift, and enter state 83 + ENDIF shift, and enter state 189 + WHILE shift, and enter state 84 + BREAK shift, and enter state 85 + CONTINUE shift, and enter state 86 + + Stmt goto state 120 + FnCall goto state 76 + Variable goto state 77 + DotField goto state 78 + +State 189 + + Stmt -> IF '(' B ')' THEN Slist ELSE Slist ENDIF . ';' (rule 62) + + ';' shift, and enter state 190 + + +State 190 + + Stmt -> IF '(' B ')' THEN Slist ELSE Slist ENDIF ';' . (rule 62) + + id reduce using rule 62 + '*' reduce using rule 62 + READ reduce using rule 62 + WRITE reduce using rule 62 + IF reduce using rule 62 + ELSE reduce using rule 62 + ENDIF reduce using rule 62 + WHILE reduce using rule 62 + ENDWHILE reduce using rule 62 + BREAK reduce using rule 62 + CONTINUE reduce using rule 62 + RETURN reduce using rule 62 + + +----------------------------------------------------------------------------- +Grammar Totals +----------------------------------------------------------------------------- +Number of rules: 97 +Number of terminals: 47 +Number of non-terminals: 39 +Number of states: 191 diff --git a/Stage6/Parser.y b/Stage6/Parser.y new file mode 100644 index 0000000..f574352 --- /dev/null +++ b/Stage6/Parser.y @@ -0,0 +1,226 @@ +{ +module Parser(parseTokens) where +import Tokens +import Control.Monad.State +import ParserState +import qualified Data.Map as Map +import SymbolTable +import SyntaxTree +} + +%name parse +%tokentype { Token } +%error { parseError } +%monad { State ParserState } + +%token + int { TokenIntVal $$ } + str { TokenStrVal $$ } + id { TokenVar $$ } + '+' { TokenPlus } + '-' { TokenMinus } + '*' { TokenTimes } + '/' { TokenDiv } + '%' { TokenMod } + '(' { TokenLParen } + ')' { TokenRParen } + '[' { TokenLBox } + ']' { TokenRBox } + '{' { TokenLCurly } + '}' { TokenRCurly } + '&' { TokenAddr } + '=' { TokenAssign } + '<' { TokenLt } + '>' { TokenGt } + '<=' { TokenLtE } + '>=' { TokenGtE } + '!=' { TokenNE } + '==' { TokenEq } + '.' { TokenDot } + BEGIN { TokenBegin } + END { TokenEnd } + READ { TokenRead } + WRITE { TokenWrite } + IF { TokenIf } + THEN { TokenThen } + ELSE { TokenElse } + ENDIF { TokenEndif } + WHILE { TokenWhile } + DO { TokenDo } + ENDWHILE { TokenEndwhile } + BREAK { TokenBreak } + CONTINUE { TokenCont } + INT { TokenInt } + STR { TokenStr } + DECL { TokenDecl } + ENDDECL { TokenEndDecl } + TYPE { TokenType } + ENDTYPE { TokenEndType } + MAIN { TokenMain } + RETURN { TokenReturn } + NULL { TokenNull } + ',' { TokenComma } + ';' { TokenStmtEnd } + +%nonassoc '==' '!=' '>' '<' '>=' '<=' +%left '+' '-' +%left '*' '/' '%' + +%% + +Program : TypeDefBlock GDeclBlock FDefBlock MainBlock { ($2, $3, $4) } + | TypeDefBlock GDeclBlock MainBlock { ($2, [], $3) } + +{- TYPE DEFINITIONS GRAMMAR -} +TypeDefBlock : TYPE TypeDefList ENDTYPE {% saveTypeTable $2 } + | TYPE ENDTYPE {% saveTypeTable [] } + | {- empty -} {% saveTypeTable [] } + +TypeDefList : TypeDefList TypeDef { $1 ++ [$2] } + | TypeDef { [$1] } + +TypeDef : id '{' FieldDeclList '}' { ($1, $3) } + +FieldDeclList : FieldDeclList FieldDecl { $1 ++ [$2] } + | FieldDecl { [$1] } + +FieldDecl : Type BaseVar ';' { ($1, $2) } + +Type : INT { "int" } + | STR { "str" } + | id { $1 } + +{- GLOBAL DECLARATIONS GRAMMAR -} + +GDeclBlock : DECL GDeclList ENDDECL {% saveGTable $2 } + | DECL ENDDECL { 4096 } + | {- empty -} { 4096 } + +GDeclList : GDeclList GDecl { $1 ++ [$2] } + | GDecl { [$1] } + +GDecl : Type GVarList ';' { ($1, $2) } + +GVarList : GVarList ',' GDec { $1 ++ [$3] } + | GDec { [$1] } + +GDec: BaseVar { $1 } + | id '(' ParamList ')' { F $1 $3 } + | '*' id '(' ParamList ')' { PF $2 $4 } + | id '[' int ']' { A $1 $3 } + | id '['int']' '['int']' { A2 $1 $3 $6 } + +BaseVar : id { U $1 } + | '*' id { P $2 } + +ParamList : ParamList ',' Param { $1 ++ [$3] } + | Param { [$1] } + | {- empty -} { [] } + +Param : Type BaseVar { ($1, $2) } + +{- FUNCTION DEFINITION GRAMMAR -} + +FDefBlock : FDefBlock FDef { $1 ++ [$2] } + | FDef { [$1] } + +FDef : FType FName '(' ParamList ')' '{' LDeclBlock Routine '}' {% fnTypeCheck ($1, $2, $4, $7, $8) } +FType: Type { $1 } + | Type'*' { $1 ++ "*" } +FName: id {% saveCurFn $1 } + + +LDeclBlock : DECL LDeclList ENDDECL {% saveLTable $2 } + | DECL ENDDECL {% saveLTable [] } + | {- empty -} {% saveLTable [] } + +LDeclList : LDeclList LDecl { $1 ++ [$2] } + | LDecl { [$1] } + +LDecl : Type LVarList ';' { ($1, $2) } + +LVarList : LVarList ',' BaseVar { $1 ++ [$3] } + | BaseVar { [$1] } + +Routine : BEGIN Slist Retstmt END { NodeConn $2 $3 } + | BEGIN Retstmt END { $2 } + +Retstmt : RETURN RVal ';' {% let (t, v) = $2 in (retTypeCheck t >> return (NodeReturn v)) } + +RVal : Variable {% varType $1 >>= \t -> return (t, $1) } + | FnCall {% fnType $1 >>= \t -> return (t, $1) } + | String { ("str", $1) } + | E2 { ("int", $1) } + | '&' Variable {% varType $2 >>= \t -> return (t++"*", NodeRef $2) } + +Slist : Slist Stmt { NodeConn $1 $2 } + | Stmt { $1 } + +Stmt : READ '(' Variable ')' ';' { NodeStmt "Read" $3 } + | Variable '=' RVal ';' {% let (t, v) = $3 in (assignTypeCheck $1 t >> return (NodeAssign $1 v)) } + | WRITE '(' RVal ')' ';' { let (t, v) = $3 in NodeStmt "Write" v } + | IF '(' B ')' THEN Slist ENDIF ';' { NodeIf $3 $6 } + | IF '(' B ')' THEN Slist ELSE Slist ENDIF ';' { NodeIfElse $3 $6 $8 } + | WHILE '(' B ')' DO Slist ENDWHILE ';' { NodeWhile $3 $6 } + | BREAK ';' { NodeBreak } + | CONTINUE ';' { NodeCont } + | FnCall ';' { $1 } + +E2 : E '+' E { NodeArmc '+' $1 $3 } + | E '-' E { NodeArmc '-' $1 $3 } + | E '*' E { NodeArmc '*' $1 $3 } + | E '/' E { NodeArmc '/' $1 $3 } + | E '%' E { NodeArmc '%' $1 $3 } + | '(' E2 ')' { $2 } + | int { LeafValInt $1 } + +E : E2 { $1 } + | FnCall {% intCheck $1 } + | Variable {% intCheck $1 } + +FnCall: id '(' ArgList ')' {% fnCallTypeCheck $1 $3 >>= \p -> return (LeafFn $1 p)} + +ArgList : ArgList ',' RVal { $1 ++ [$3] } + | RVal { [$1] } + | {- empty -} { [] } + +B : E '<' E { NodeBool "<" $1 $3 } + | E '>' E { NodeBool ">" $1 $3 } + | E '<=' E { NodeBool "<=" $1 $3 } + | E '>=' E { NodeBool ">=" $1 $3 } + | E '!=' E { NodeBool "!=" $1 $3 } + | E '==' E { NodeBool "==" $1 $3 } + +Variable : id {% symCheck (isUnit) $1 >> return (LeafVar $1 Simple) } + | id '[' E ']' {% symCheck (isArr) $1 >> return (LeafVar $1 (Index $3)) } + | id '['E']' '['E']' {% symCheck (isArr2) $1 >> return (LeafVar $1 (Index2D $3 $6)) } + | '*' id {% symCheck (isPtr) $2 >> return (LeafVar $2 Deref) } + | DotField {% let n:d = $1 in (dotSymCheck n d >> return(LeafVar n (Dot d))) } + +DotField : DotField '.' id { $1 ++ [$3] } + | id '.' id { [$1, $3] } + +String : str { LeafValStr $1 } + + +{- MAIN FUNCTION GRAMMAR -} + +MainBlock : INT Main '(' ')' '{' LDeclBlock Routine '}' { ($6, $7) } +Main: MAIN {% saveMainFn } + +{ + +parseError t = error $ "Parse error: " ++ show t + +parseTokens tokenStream = (tTable, gSymFull, sp, fDecl, main) + where + ((sp, fDecl, main), (tTable, gSymTable, _, _)) = runState (parse tokenStream) startState + gSymFull = Map.insertWith (error "Main function declared twice") "main" (Func "int" [] "main") gSymTable + +type Program = + ( Int, + [FDef], + (LSymbolTable, SyntaxTree) + ) + +} \ No newline at end of file diff --git a/Stage6/ParserState.hs b/Stage6/ParserState.hs new file mode 100644 index 0000000..378c85e --- /dev/null +++ b/Stage6/ParserState.hs @@ -0,0 +1,147 @@ +{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-} + +{-# HLINT ignore "Use when" #-} +module ParserState where + +import Control.Monad.State (MonadState (get, put), State, void) +import Data.Bifunctor (second) +import qualified Data.Map as Map +import SymbolTable +import SyntaxTree +import TypeTable + +-- Global Symbol Table, Current Function, Local Symbol Table +type ParserState = (TypeTable, GSymbolTable, Symbol, GSymbolTable) + +-- Unit "" 0 is a temp junk value +startState = (Map.empty, Map.empty, Unit "" 0, Map.empty) + +-- STATE UPDATE FUNCTIONS + +-- | Saves and type checks the type table +saveTypeTable :: [(String, [(String, SymbolBase)])] -> State ParserState () +saveTypeTable tlist = do + (_, s1, s2, s3) <- get + let baseToTuple (t, v) = case v of + U n -> (t, n) + P n -> (t ++ "*", n) + _ -> error "Not a valid type child" + let tList = map (second (map baseToTuple)) tlist + let tTable = genTypeTable tList + put (tTable, s1, s2, s3) + return () + +-- | Saves global symbol table and returns stack pointer +saveGTable :: [(String, [SymbolBase])] -> State ParserState Int +saveGTable decls = do + (tt, _, start1, start2) <- get + let (gSymTable, spInc) = genGSymbolTable decls + let gSymTableV = verifyGSymTable gSymTable tt + put (tt, gSymTableV, start1, start2) + -- stack pointer should be pointing to the last used location + return $ spInc - 1 + +-- | Saves and returns local symbol table +saveLTable :: [(String, [SymbolBase])] -> State ParserState LSymbolTable +saveLTable decls = do + (tt, gSymTable, cFn, _) <- get + let (Func _ args _) = cFn + lSymTable = genLSymbolTable decls + argSymTable = genArgSymbolTable args + localSymbols = Map.unionWith (error "Args and local variables have same name") lSymTable argSymTable + lSymG = Map.map (uncurry Unit) localSymbols + mergedSymTable = Map.union lSymG gSymTable + put (tt, gSymTable, cFn, mergedSymTable) + return $ verifyLSymTable localSymbols tt + +-- | Saves current function as symbol +saveCurFn :: String -> State ParserState String +saveCurFn name = do + (tt, gSymTable, _, lSymTable) <- get + let curFn = + ( case Map.lookup name gSymTable of + Just f -> f + Nothing -> error $ "Function " ++ name ++ " not declared." + ) + put (tt, gSymTable, curFn, lSymTable) + return name + +saveMainFn :: State ParserState String +saveMainFn = do + (tt, gSymTable, _, lSymTable) <- get + let curFn = Func "int" [] "" + put (tt, gSymTable, curFn, lSymTable) + return "main" + +-- TYPE CHECK FUNCTIONS + +type FDef = (String, String, [String], LSymbolTable, SyntaxTree) + +-- Typechecks and returns given fn defn with modified params +fnTypeCheck :: (String, String, [(String, SymbolBase)], LSymbolTable, SyntaxTree) -> State ParserState FDef +fnTypeCheck (t, name, params, lSym, tree) = do + (_, _, cFn, _) <- get + let (Func td pd _) = cFn + paramToTuple (t, v) = case v of + U n -> (t, n) + P n -> (t ++ "*", n) + _ -> error "Not a valid param" + let pc = map paramToTuple params + let params2 = map snd pc + if t == td && pc == pd + then return (t, name, params2, lSym, tree) + else error "Function definition does not match declaration" + +-- Typechecks and returns given fn defn with modified params +fnCallTypeCheck :: String -> [(String, SyntaxTree)] -> State ParserState [SyntaxTree] +fnCallTypeCheck name params = do + (_, gSymT, _, _) <- get + case Map.lookup name gSymT of + Just (Func _ p2 _) -> + if map fst params == map fst p2 + then return (map snd params) + else error $ "Function call doesnt match definition: " ++ name ++ show (map fst params) ++ show () + _ -> error $ "Function call is invalid: " ++ name + +retTypeCheck :: String -> State ParserState () +retTypeCheck t = do + (_, _, cFn, _) <- get + let (Func td _ _) = cFn + if t == td then return () else error $ "Function returns " ++ t ++ " instead of " ++ td + +assignTypeCheck :: SyntaxTree -> String -> State ParserState () +assignTypeCheck n tc = do + t <- varType n + if t == tc then return () else error $ "Cannot assign " ++ tc ++ " to " ++ t + +dotSymCheck :: String -> [String] -> State ParserState () +dotSymCheck symName dots = do + (tTable, _, _, symTab) <- get + case Map.lookup symName symTab of + Just s -> + if resolveDotType tTable (getSymbolType s) dots == "" + then error "" + else return () + Nothing -> error $ "Variable does not exist : " ++ symName + +intCheck :: SyntaxTree -> State ParserState SyntaxTree +intCheck n = do + (_, _, _, symTab) <- get + if isInteger symTab n then return n else error $ "Integer value was expected on right side of assignment: " ++ show n + +symCheck :: (Symbol -> Bool) -> String -> State ParserState () +symCheck isSym n = do + (_, _, _, symTab) <- get + case Map.lookup n symTab of + Just s -> if isSym s then return () else error $ "Illegal variable access for " ++ n + Nothing -> error $ "Variable does not exist : " ++ n + +varType :: SyntaxTree -> State ParserState String +varType n = do + (tt, _, _, symTab) <- get + return $ getVarType symTab tt n + +fnType :: SyntaxTree -> State ParserState String +fnType n = do + (_, _, _, symTab) <- get + return $ getFnType symTab n diff --git a/Stage6/SymbolTable.hs b/Stage6/SymbolTable.hs new file mode 100644 index 0000000..cd4e9a0 --- /dev/null +++ b/Stage6/SymbolTable.hs @@ -0,0 +1,110 @@ +{-# LANGUAGE ScopedTypeVariables #-} + +module SymbolTable where + +import Data.List +import qualified Data.Map as Map + +-- | Type used in the Grammar file for making the variable list +data SymbolBase + = U String + | A String Int + | A2 String Int Int + | P String + | F String [(String, SymbolBase)] + | PF String [(String, SymbolBase)] + deriving (Show, Eq) + +data Symbol + = Unit String Int -- Type, Addr + | Arr String Int Int -- Type, Size, Addr + | Arr2 String Int Int Int -- Type, Size1, Size2, Addr + | Func String [(String, String)] String -- Type, Params, Label + deriving (Show) + +type GSymbolTable = Map.Map String Symbol + +type LSymbolTable = Map.Map String (String, Int) -- Name -> (Type, Local Addr) + +-- | Returns the type of a given symbol +getSymbolType :: Symbol -> String +getSymbolType (Unit t _) = t +getSymbolType (Arr t _ _) = t +getSymbolType (Arr2 t _ _ _) = t +getSymbolType (Func t _ _) = t + +isUnit :: Symbol -> Bool +isUnit Unit {} = True +isUnit _ = False + +isPtr :: Symbol -> Bool +isPtr (Unit t _) = last t == '*' +isPtr _ = False + +isArr :: Symbol -> Bool +isArr Arr {} = True +isArr _ = False + +isArr2 :: Symbol -> Bool +isArr2 Arr2 {} = True +isArr2 _ = False + +getSymbolAddress :: Symbol -> Int +getSymbolAddress (Unit _ a) = a +getSymbolAddress (Arr _ _ a) = a +getSymbolAddress (Arr2 _ _ _ a) = a +getSymbolAddress _ = error "No address for function" + +-- | Base declarations -> typetable -> startAddress -> mapFunction -> errorMsg -> (SymbolTable, Size) +symbolTableHelper :: forall tVal. [(String, [SymbolBase])] -> Int -> (String -> SymbolBase -> Int -> (String, tVal)) -> String -> (Map.Map String tVal, Int) +symbolTableHelper decls sa toTableEntry eMsg = (Map.fromListWith (error eMsg) symList, size) + where + getBaseSize :: SymbolBase -> String -> Int + getBaseSize b t = case b of + U _ -> 1 + A _ n -> n + A2 _ n1 n2 -> n1 * n2 + P _ -> 1 + _ -> 0 + + getLineSyms :: Int -> (String, [SymbolBase]) -> (Int, [(String, tVal)]) + getLineSyms addrInit (t, vars) = mapAccumL (\a b -> (a + getBaseSize b t, toTableEntry t b a)) addrInit vars + + (size, symList) = let (s, l) = mapAccumL getLineSyms sa decls in (s, concat l) + +-- | Array of decls ("type": [SymbolBase]) -> (GSymbolTable, size) +genGSymbolTable :: [(String, [SymbolBase])] -> (GSymbolTable, Int) +genGSymbolTable decls = symbolTableHelper decls 4096 toTableEntry eMsg + where + paramToTuple (t, v) = case v of + U n -> (t, n) + P n -> (t ++ "*", n) + _ -> error "Not a valid param" + toTableEntry t v a = case v of + U name -> (name, Unit t a) + A name s -> (name, Arr t s a) + A2 name s1 s2 -> (name, Arr2 t s1 s2 a) + P name -> (name, Unit (t ++ "*") a) + F name params -> (name, Func t (map paramToTuple params) name) + PF name params -> (name, Func (t ++ "*") (map paramToTuple params) name) + eMsg = "Non-unique global declaration" + +-- | Array of decls ("type": [unit/ptr]) -> LSymbolTable +genLSymbolTable :: [(String, [SymbolBase])] -> LSymbolTable +genLSymbolTable decls = fst $ symbolTableHelper decls 0 toTableEntry eMsg + where + toTableEntry t v a = case v of + U n -> (n, (t, a)) + P n -> (n, (t ++ "*", a)) + _ -> error "Local variables can only be pointers or simple" + eMsg = "Non-unique local variable declaration" + +-- | The args will have space BP - 4 and upwards +-- | [(type, name)] -> symboltable +genArgSymbolTable :: [(String, String)] -> LSymbolTable +genArgSymbolTable args = Map.fromListWith nameError symbolList + where + startAddr = -3 - length args + -- (_, symbolList) = mapAccumL (\a ((t, n), s) -> (a + s, (n, (t, a)))) startAddr $ zip args argSizes + symbolList = [(n, (t, i)) | ((t, n), i) <- zip args [startAddr ..]] + nameError = error "Non-unique argument declaration" \ No newline at end of file diff --git a/Stage6/SyntaxTree.hs b/Stage6/SyntaxTree.hs new file mode 100644 index 0000000..4c9e45f --- /dev/null +++ b/Stage6/SyntaxTree.hs @@ -0,0 +1,69 @@ +module SyntaxTree (SyntaxTree (..), VarResolve (..), prettyPrint, isInteger, getVarType, getFnType) where + +import qualified Data.Map as Map +import Data.Tree (Tree (Node), drawTree) +import SymbolTable +import TypeTable + +data VarResolve + = Simple + | Deref + | Index SyntaxTree + | Index2D SyntaxTree SyntaxTree + | Dot [String] + deriving (Show) + +data SyntaxTree + = LeafVar String VarResolve + | LeafFn String [SyntaxTree] + | LeafValInt Int + | LeafValStr String + | NodeStmt String SyntaxTree + | NodeArmc Char SyntaxTree SyntaxTree + | NodeBool String SyntaxTree SyntaxTree + | NodeAssign SyntaxTree SyntaxTree + | NodeConn SyntaxTree SyntaxTree + | NodeIf SyntaxTree SyntaxTree + | NodeIfElse SyntaxTree SyntaxTree SyntaxTree + | NodeWhile SyntaxTree SyntaxTree + | NodeRef SyntaxTree + | NodeBreak + | NodeCont + | NodeReturn SyntaxTree + deriving (Show) + +-- | Returns if a given constructor evaluates to an integer value +isInteger :: GSymbolTable -> SyntaxTree -> Bool +isInteger st (LeafVar var Deref) = getSymbolType (st Map.! var) == "int*" +isInteger st (LeafVar var _) = getSymbolType (st Map.! var) == "int" +isInteger st (LeafFn name _) = getSymbolType (st Map.! name) == "int" +isInteger _ LeafValInt {} = True +isInteger _ NodeArmc {} = True +isInteger _ _ = False + +getVarType :: GSymbolTable -> TypeTable -> SyntaxTree -> String +getVarType st _ (LeafVar var Deref) = init $ getSymbolType (st Map.! var) -- Remove "*" from the end +getVarType st tt (LeafVar var (Dot dotList)) = resolveDotType tt (getSymbolType (st Map.! var)) dotList +getVarType st _ (LeafVar var _) = getSymbolType (st Map.! var) +getVarType _ _ _ = error "Not a variable" + +getFnType :: GSymbolTable -> SyntaxTree -> String +getFnType st (LeafFn name _) = getSymbolType (st Map.! name) +getFnType _ _ = error "Not a function" + +toDataTree :: SyntaxTree -> Tree String +toDataTree t = case t of + NodeStmt c s -> Node c [toDataTree s] + NodeArmc c l r -> Node ("Arithmetic " ++ [c]) [toDataTree l, toDataTree r] + NodeBool c l r -> Node ("Boolean " ++ c) [toDataTree l, toDataTree r] + NodeConn l r -> Node "NodeConn" [toDataTree l, toDataTree r] + NodeAssign l r -> Node "Assign" [toDataTree l, toDataTree r] + NodeIf cond bl -> Node "If" [toDataTree cond, toDataTree bl] + NodeIfElse cond bl1 bl2 -> Node "If Else" [toDataTree cond, toDataTree bl1, toDataTree bl2] + NodeWhile cond bl -> Node "While" [toDataTree cond, toDataTree bl] + NodeBreak -> Node "Break" [] + NodeCont -> Node "Continue" [] + _ -> Node (show t) [] + +prettyPrint :: SyntaxTree -> String +prettyPrint t = drawTree $ toDataTree t \ No newline at end of file diff --git a/Stage6/Tokens.x b/Stage6/Tokens.x new file mode 100644 index 0000000..5652e8f --- /dev/null +++ b/Stage6/Tokens.x @@ -0,0 +1,115 @@ +{ +module Tokens where +} + +%wrapper "basic" + +@integer = [0-9]+ +@varName = [a-zA-Z_][a-zA-Z_0-9]* +@string = \"(\\.|[^\"\\])*\" + +tokens :- + + $white+ ; + @integer { \s -> TokenIntVal (read s) } + @string { \s -> TokenStrVal s } + \+ { \_ -> TokenPlus } + \- { \_ -> TokenMinus } + \* { \_ -> TokenTimes } + \/ { \_ -> TokenDiv } + \% { \_ -> TokenMod } + \( { \_ -> TokenLParen } + \) { \_ -> TokenRParen } + \= { \_ -> TokenAssign } + \< { \_ -> TokenLt } + \> { \_ -> TokenGt } + \<\= { \_ -> TokenLtE } + \>\= { \_ -> TokenGtE } + \!\= { \_ -> TokenNE } + \=\= { \_ -> TokenEq } + \. { \_ -> TokenDot } + begin { \_ -> TokenBegin } + end { \_ -> TokenEnd } + read { \_ -> TokenRead } + write { \_ -> TokenWrite } + if { \_ -> TokenIf } + then { \_ -> TokenThen } + else { \_ -> TokenElse } + endif { \_ -> TokenEndif } + while { \_ -> TokenWhile } + do { \_ -> TokenDo } + break { \_ -> TokenBreak } + continue { \_ -> TokenCont } + endwhile { \_ -> TokenEndwhile } + decl { \_ -> TokenDecl } + enddecl { \_ -> TokenEndDecl } + int { \_ -> TokenInt } + str { \_ -> TokenStr } + main { \_ -> TokenMain } + return { \_ -> TokenReturn } + type { \_ -> TokenType } + endtype { \_ -> TokenEndType } + NULL { \_ -> TokenNull } + @varName { \s -> TokenVar s } + \[ { \_ -> TokenLBox } + \] { \_ -> TokenRBox } + \{ { \_ -> TokenLCurly } + \} { \_ -> TokenRCurly } + \& { \_ -> TokenAddr } + \, { \_ -> TokenComma } + \; { \_ -> TokenStmtEnd } + +{ + +data Token = TokenIntVal Int + | TokenStrVal String + | TokenVar String + | TokenPlus + | TokenMinus + | TokenTimes + | TokenDiv + | TokenMod + | TokenLt + | TokenLtE + | TokenGt + | TokenGtE + | TokenEq + | TokenNE + | TokenLParen + | TokenRParen + | TokenAssign + | TokenBegin + | TokenEnd + | TokenRead + | TokenWrite + | TokenIf + | TokenThen + | TokenElse + | TokenEndif + | TokenWhile + | TokenDo + | TokenBreak + | TokenCont + | TokenEndwhile + | TokenStmtEnd + | TokenDecl + | TokenEndDecl + | TokenInt + | TokenStr + | TokenLBox + | TokenRBox + | TokenLCurly + | TokenRCurly + | TokenAddr + | TokenMain + | TokenReturn + | TokenComma + | TokenDot + | TokenType + | TokenEndType + | TokenNull + deriving (Show) + +scanTokens = alexScanTokens + +} \ No newline at end of file diff --git a/Stage6/TypeTable.hs b/Stage6/TypeTable.hs new file mode 100644 index 0000000..b581cf3 --- /dev/null +++ b/Stage6/TypeTable.hs @@ -0,0 +1,63 @@ +module TypeTable where + +import Data.List +import qualified Data.Map as Map +import SymbolTable + +type Field = (String, String) -- TypeName, VarName + +type TypeTable = Map.Map String [Field] -- Name -> TypeInfo + +-- | Check if a list of dot access is valid on a given type +-- | TypeTable -> startType -> [DotList] -> String +resolveDotType :: TypeTable -> String -> [String] -> String +resolveDotType tTable = foldl' childType + where + childType :: String -> String -> String + childType pType cName = case find ((cName ==) . snd) (tTable Map.! pType) of + Just (tName, _) -> tName + Nothing -> error $ "Type " ++ pType ++ " does not contain child " ++ cName + +-- | Returns the size of a given type string +getTypeSize :: TypeTable -> String -> Int +getTypeSize tTable tName = length $ tTable Map.! tName + +-- | Checks if a given array of types all fit into the type table +areValidTypes :: TypeTable -> [String] -> Bool +areValidTypes tTable = all tCheck + where + tCheck t = case Map.lookup t tTable of + Just _ -> True + Nothing -> error $ "Type '" ++ t ++ "' not recognized." + +-- | Generates and type-checks a type table with passed definitions +genTypeTable :: [(String, [Field])] -> TypeTable +genTypeTable tList = + if isValid + then tTable + else error "This error shouldn't be thrown #1" + where + tTable = Map.fromListWith nameError $ ("int", []) : ("str", []) : tList + nameError = error "Non-unique type name" + fieldsVerify :: [Field] -> Bool + fieldsVerify fields = areValidTypes tTable $ map fst fields + isValid = all (fieldsVerify . snd) tList + +-- Verifies if the passed global symbol table has valid types +verifyGSymTable :: GSymbolTable -> TypeTable -> GSymbolTable +verifyGSymTable gTable tTable = + if isValid + then gTable + else error "This error shouldn't be thrown #2" + where + symbolTypes = map getSymbolType $ Map.elems gTable + isValid = areValidTypes tTable symbolTypes + +verifyLSymTable :: LSymbolTable -> TypeTable -> LSymbolTable +verifyLSymTable lTable tTable = + if isValid + then lTable + else error "This error shouldn't be thrown #3" + where + symbolTypes = map fst $ Map.elems lTable + isValid = areValidTypes tTable symbolTypes \ No newline at end of file diff --git a/Stage6/XsmGen.hs b/Stage6/XsmGen.hs new file mode 100644 index 0000000..7a1fa4f --- /dev/null +++ b/Stage6/XsmGen.hs @@ -0,0 +1,97 @@ +module XsmGen where + +-- | operator -> leftRegister -> rightRegister -> xsmInstruction +-- | Generates XSM instruction for a specified arithmetic operation +genArmcXsm :: Char -> String -> String -> String +genArmcXsm op lr rr = cmd ++ " " ++ lr ++ ", " ++ rr ++ "\n" + where + cmd = case op of + '+' -> "ADD" + '-' -> "SUB" + '*' -> "MUL" + '/' -> "DIV" + '%' -> "MOD" + _ -> error "Invalid Arithmetic Operator" + +-- | operator -> leftRegister -> rightRegister -> xsmInstruction +-- | Generates XSM instruction for a specified boolean operation +genBoolXsm :: String -> String -> String -> String +genBoolXsm op lr rr = cmd ++ " " ++ lr ++ ", " ++ rr ++ "\n" + where + cmd = case op of + "<" -> "LT" + ">" -> "GT" + "<=" -> "LE" + ">=" -> "GE" + "==" -> "EQ" + "!=" -> "NE" + _ -> error "Invalid Boolean Operator" + +-- | Destination -> Source -> Instruction +-- | Returns a MOV instruction from specified values +genMovXsm :: String -> String -> String +genMovXsm dest source = "MOV " ++ dest ++ ", " ++ source ++ "\n" + +-- | Surrounds a given string in [] for memory access +genMemAccXsm :: String -> String +genMemAccXsm v = "[" ++ v ++ "]" + +-- Appends : to the end defining a label +genLabelXsm :: String -> String +genLabelXsm l = l ++ ":" + +-- Surrounds label with < > +accessLabel :: String -> String +accessLabel l = "<" ++ l ++ ">" + +-- | Register -> Label -> Instruction +-- | Returns a JZ instruction to the specified label with value in reg +genJmpZXsm :: String -> String -> String +genJmpZXsm r l = "JZ " ++ r ++ ", " ++ accessLabel l ++ "\n" + +-- | Label -> Instruction +-- | Returns a JMP instruction to the specified label +genJmpXsm :: String -> String +genJmpXsm l = "JMP " ++ accessLabel l ++ "\n" + +data StackOpType = PUSH | POP deriving (Show) + +-- | Generates XSM for stack operations +genStackXsm :: StackOpType -> String -> String +genStackXsm opType reg = show opType ++ " " ++ reg ++ "\n" + +-- Generates a call instruction +genCallXsm :: String -> String +genCallXsm lbl = "CALL " ++ lbl ++ "\n" + +-- Generates a RET instruction +genRetXsm :: String +genRetXsm = "RET\n" + +data LibCallArg = ValInt Int | ValString String | Reg String | None + +-- | Function Code -> (3 arguments) -> tempRegister -> Code +-- | Generates library call XSM +genLibXsm :: String -> (LibCallArg, LibCallArg, LibCallArg) -> String -> String +genLibXsm fnCode (a1, a2, a3) tempReg = + evalCodeFn ++ genStackXsm PUSH cReg + ++ (evalCode1 ++ genStackXsm PUSH arg1) + ++ (evalCode2 ++ genStackXsm PUSH arg2) + ++ (evalCode3 ++ genStackXsm PUSH arg3) + ++ genStackXsm PUSH "R0" + ++ genCallXsm "0" + ++ genStackXsm POP tempReg + ++ genStackXsm POP tempReg + ++ genStackXsm POP tempReg + ++ genStackXsm POP tempReg + ++ genStackXsm POP tempReg + where + (evalCode1, arg1) = evalArg a1 tempReg + (evalCode2, arg2) = evalArg a2 tempReg + (evalCode3, arg3) = evalArg a3 tempReg + (evalCodeFn, cReg) = evalArg (ValString fnCode) tempReg + evalArg argType tempReg = case argType of + (ValInt val) -> (genMovXsm tempReg $show val, tempReg) + (ValString val) -> (genMovXsm tempReg $show val, tempReg) + (Reg r) -> ("", r) + None -> ("", "R0") diff --git a/Stage6/test.expl b/Stage6/test.expl new file mode 100644 index 0000000..139d0e9 --- /dev/null +++ b/Stage6/test.expl @@ -0,0 +1,25 @@ +type + List + { + int data; + List next; + } +endtype + +decl + List head; + int a[5]; +enddecl + +int main() +{ + decl + int length, x; + List p, q; + enddecl + + begin + write(p.next.next.next.data); + return 1; + end +}