diff --git a/src/Kroha/Errors.hs b/src/Kroha/Errors.hs index 027427e..5903409 100644 --- a/src/Kroha/Errors.hs +++ b/src/Kroha/Errors.hs @@ -49,11 +49,6 @@ toErrorList = concatMap mapper mapper error = [error] -sNub :: Eq a => [a] -> [a] -sNub (a:b:tail) | a == b = sNub (b:tail) - | otherwise = a:sNub (b:tail) -sNub xs = xs - showErrors :: (NodeId -> Maybe (SourcePos, SourcePos)) -> Error -> String showErrors findRange = intercalate "\n" . fmap (uncurry showError) . process . toErrorList . pure where showError _ (JoinedError _) = undefined diff --git a/src/Kroha/Parser/Declarations.hs b/src/Kroha/Parser/Declarations.hs index fc6955b..5a1ca88 100644 --- a/src/Kroha/Parser/Declarations.hs +++ b/src/Kroha/Parser/Declarations.hs @@ -7,6 +7,7 @@ import Kroha.Syntax (Declaration(..), Program (Program)) import Text.Megaparsec import Data.Bifunctor (first) import Kroha.Parser.Statements (body, statement) +import Control.Monad (void) globalVariable w f = f <$> (w *> name) <*> typeSpecification <*> (symbol "=" *> literal) @@ -32,7 +33,9 @@ globals = recover (choice (fmap krP [constant, variable, manualDeclarations, fra skip = do someTill (satisfy (const True)) (const' <|> var' <|> manual' <|> frame') return (ManualFrame "" "'") -program = krP $ Program <$> (program' *> braces (many globals)) +program = krP $ Program <$> prog (many globals) <* endOfFile + where prog p = (program' *> (braces p <|> symbol ";" *> p)) <|> p + endOfFile = eof <|> void (symbol "=======" *> lexeme (some (noneOf "=") <* symbol "=======")) "end of file" parseProgram :: String -> String -> Either String (Program (SourcePos, SourcePos)) parseProgram name = first errorBundlePretty . runParser program name diff --git a/src/Kroha/Parser/Lexer.hs b/src/Kroha/Parser/Lexer.hs index 414887e..d6527f9 100644 --- a/src/Kroha/Parser/Lexer.hs +++ b/src/Kroha/Parser/Lexer.hs @@ -36,13 +36,16 @@ krP p = do around l r = between (symbol l) (symbol r) parens = around "(" ")" -angles = around "<" ">" braces = around "{" "}" +parensOpt p = parens p <|> p + name, name' :: Parser String name' = (:) <$> letterChar <*> many (alphaNumChar <|> char '_') name = lexeme (name' "identifier") +callName = around "<" ">" name <|> name + literal = IntegerLiteral <$> nat "integer literal" lvalue = (VariableLVal <$> name "variable name") <|> (RegisterLVal <$> lexeme (char '%' *> name') "register name") rvalue = (RLiteral <$> literal) <|> (AsRValue <$> lvalue) diff --git a/src/Kroha/Parser/Statements.hs b/src/Kroha/Parser/Statements.hs index a02492c..5756f26 100644 --- a/src/Kroha/Parser/Statements.hs +++ b/src/Kroha/Parser/Statements.hs @@ -8,9 +8,9 @@ import Text.Megaparsec import Data.Tuple.Extra (curry3) import Text.Megaparsec.Char (space1) -break = krP $ Break <$> (break' *> parens name) +break = krP $ Break <$> (break' *> parensOpt name) inline = krP (Inline <$> (symbol "!" *> many (noneOf "\n"))) <* space1 -call = krP $ Call <$> (call' *> angles name) <*> parens (rvalue `sepBy` symbol ",") +call = krP $ Call <$> (call' *> callName) <*> parens (rvalue `sepBy` symbol ",") register = krP $ VariableDeclaration <$> (RegisterVariable <$> (reg' *> name) <*> (symbol ":" *> (name "register name"))) variable = krP $ VariableDeclaration <$> (StackVariable <$> (var' *> name) <*> typeSpecification) @@ -30,7 +30,7 @@ ifStatement pStatement = krP $ p x s = x <$ symbol s cmpToken = p Equals "==" <|> p NotEquals "!=" <|> p Greater ">" <|> p Less "<" -loop ps = krP $ Loop <$> (loop' *> parens name) <*> body' ps +loop ps = krP $ Loop <$> (loop' *> parensOpt name) <*> body' ps statement = recover (choice ( fmap (<* end) [ inline, call, Kroha.Parser.Statements.break, diff --git a/test/Spec.hs b/test/Spec.hs index 2ee1412..1e42d83 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -12,6 +12,7 @@ cases = , "examples/nestedIfs" , "examples/loops" , "examples/semicolons" + , "examples/elseif" , "errors/scopeErrors" , "errors/typeErrors" ] diff --git a/test/examples/elseif.test.kr b/test/examples/elseif.test.kr new file mode 100644 index 0000000..99f0770 --- /dev/null +++ b/test/examples/elseif.test.kr @@ -0,0 +1,35 @@ +program { + frame sign { + reg x : bx + + if (x > 0, XGTZ) { + x = 2 + } + else if (x == 0, XEZ) { + x = 1 + } + else { + x = 0 + } + !dec bx + } +} +======= nasm ======= +section .text +sign: + cmp bx, 0 + jg XGTZ_begin + cmp bx, 0 + je XEZ_begin + mov bx, 0 + jmp XEZ_end + XEZ_begin: + mov bx, 1 + XEZ_end: + jmp XGTZ_end + XGTZ_begin: + mov bx, 2 + XGTZ_end: + dec bx +leave +ret diff --git a/test/examples/frameVariables.test.kr b/test/examples/frameVariables.test.kr index c09b253..6cf45c9 100644 --- a/test/examples/frameVariables.test.kr +++ b/test/examples/frameVariables.test.kr @@ -1,21 +1,19 @@ -program { - frame register { - reg x : ax - reg y : bx +frame register { + reg x : ax + reg y : bx - x = 5 - y = x - } + x = 5 + y = x +} - frame stackNreg { - var x : int16 - reg y : ax +frame stackNreg { + var x : int16 + reg y : ax - x = 5 - y = x - x = y - y = 6 - } + x = 5 + y = x + x = y + y = 6 } ======= nasm ======= @@ -34,4 +32,3 @@ stackNreg: mov ax, 6 leave ret - diff --git a/test/examples/functionCall.test.kr b/test/examples/functionCall.test.kr index 4f69ceb..9c13773 100644 --- a/test/examples/functionCall.test.kr +++ b/test/examples/functionCall.test.kr @@ -4,7 +4,8 @@ program { } frame callFunction { - call () + call() + call justFunc() !nop } } @@ -18,9 +19,10 @@ ret section .text callFunction: + call justFunc + add sp, 0 call justFunc add sp, 0 nop leave ret - diff --git a/test/examples/functionDeclaration.test.kr b/test/examples/functionDeclaration.test.kr index be28c48..1cbc98a 100644 --- a/test/examples/functionDeclaration.test.kr +++ b/test/examples/functionDeclaration.test.kr @@ -1,11 +1,9 @@ -program { - frame start { - !nop - } +frame start { + !nop +} - manual frame mf { - add ax, dx - } +manual frame mf { + add ax, dx } ======= nasm ======= @@ -18,5 +16,3 @@ ret section .text mf: add ax, dx - - diff --git a/test/examples/if.test.kr b/test/examples/if.test.kr index a16f672..aae3f98 100644 --- a/test/examples/if.test.kr +++ b/test/examples/if.test.kr @@ -1,27 +1,24 @@ -program { - frame if_eq { - reg x : ax - - if (x == 5, A) { - !inc ax - } - - !nop +frame if_eq { + reg x : ax + + if (x == 5, A) { + !inc ax } - frame if_comp { - reg x : ax - - if (x > 5, B) { - !add ax, 5 - } + !nop +} - if (x < 7, C) { - !sub ax, 7 - } +frame if_comp { + reg x : ax - !nop + if (x > 5, B) { + !add ax, 5 } + + if (x < 7, C) + !sub ax, 7 + + !nop } ======= nasm ======= @@ -49,9 +46,8 @@ if_comp: jl C_begin jmp C_end C_begin: - sub ax, 7 + sub ax, 7 C_end: nop leave ret - diff --git a/test/examples/ifelse.test.kr b/test/examples/ifelse.test.kr index fb05315..b739ed4 100644 --- a/test/examples/ifelse.test.kr +++ b/test/examples/ifelse.test.kr @@ -1,29 +1,25 @@ -program { - frame ifelse_eq { - reg x : ax - - if (x == 5, A) { - !dec ax - } - else { - !inc ax - } - - !nop +frame ifelse_eq { + reg x : ax + + if (x == 5, A) { + !dec ax + } + else { + !inc ax } - frame ifelse_comp { - reg x : ax + !nop +} - if (x < 5, B) { - !dec ax - } - else { - !inc ax - } +frame ifelse_comp { + reg x : ax - !nop - } + if (x < 5, B) + !dec ax + else + !inc ax + + !nop } ======= nasm ======= @@ -44,12 +40,11 @@ section .text ifelse_comp: cmp ax, 5 jl B_begin - inc ax + inc ax jmp B_end B_begin: - dec ax + dec ax B_end: nop leave ret - diff --git a/test/examples/loops.test.kr b/test/examples/loops.test.kr index 3143319..f0ef3ca 100644 --- a/test/examples/loops.test.kr +++ b/test/examples/loops.test.kr @@ -1,23 +1,29 @@ -program { - frame infLoop { - loop (IL) { - !inc ax - } +frame infLoop { + loop (IL) { + !inc ax } - frame main { - reg x : ax + loop IL2 + !inc ax +} + +frame main { + reg x : ax - loop (JL) { - !inc ax + loop JL { + !inc ax - if (x > 5, BL) { - break (JL) - } + if (x > 5, BL) { + break (JL) } + } - !nop + loop PL { + !xor ax, ax + break PL } + + !nop } ======= nasm ======= @@ -27,6 +33,10 @@ infLoop: inc ax jmp IL_begin IL_end: + IL2_begin: + inc ax + jmp IL2_begin + IL2_end: leave ret @@ -42,7 +52,11 @@ main: BL_end: jmp JL_begin JL_end: + PL_begin: + xor ax, ax + jmp PL_end + jmp PL_begin + PL_end: nop leave ret - diff --git a/test/examples/nestedIfs.test.kr b/test/examples/nestedIfs.test.kr index 40dca94..eb44850 100644 --- a/test/examples/nestedIfs.test.kr +++ b/test/examples/nestedIfs.test.kr @@ -1,38 +1,36 @@ -program { - frame plot { - reg x : ax - reg y : bx - reg r : dx +frame plot { + reg x : ax + reg y : bx + reg r : dx - if (x > 0, XP) { - if (y > 0, YP) { - r = 1 + if (x > 0, XP) { + if (y > 0, YP) { + r = 1 + } else { + if (y < 0, YP2) { + r = 4 } else { - if (y < 0, YP2) { - r = 4 - } else { - r = 20 - } + r = 20 } } - else { - if (x < 0, XP2) { - if (y > 0, YP3) { - r = 2 - } else { - if (y < 0, YP4) { - r = 3 - } else { - r = 10 - } - } + } + else { + if (x < 0, XP2) { + if (y > 0, YP3) { + r = 2 } else { - if (y == 0, O) { - r = 0 + if (y < 0, YP4) { + r = 3 } else { r = 10 - } + } } + } else { + if (y == 0, O) { + r = 0 + } else { + r = 10 + } } } } @@ -85,4 +83,3 @@ plot: XP_end: leave ret - diff --git a/test/examples/semicolons.test.kr b/test/examples/semicolons.test.kr index 8c45520..0edb356 100644 --- a/test/examples/semicolons.test.kr +++ b/test/examples/semicolons.test.kr @@ -5,11 +5,11 @@ program { y = x; x = y; - loop (L) { + loop L { if (x > y, C) { - break (L); + break L; } else { - break (L) + break L } } } diff --git a/test/examples/variableDeclarations.test.kr b/test/examples/variableDeclarations.test.kr index f7f5212..b7466dd 100644 --- a/test/examples/variableDeclarations.test.kr +++ b/test/examples/variableDeclarations.test.kr @@ -1,12 +1,12 @@ -program { - var a : int16 = 32 - var b : int8 = 1 - const c : int16 = 32 - const d : int8 = 1 +program; - manual var arr : &int8 { - times 64 db 0 - } +var a : int16 = 32 +var b : int8 = 1 +const c : int16 = 32 +const d : int8 = 1 + +manual var arr : &int8 { + times 64 db 0 } ======= nasm ======= @@ -23,7 +23,5 @@ section .rodata d: db 1 section .data -arr: - times 64 db 0 - - +arr: times 64 db 0 + \ No newline at end of file