From 6d39110794ff643932f52d8274630f450caebc89 Mon Sep 17 00:00:00 2001 From: Marvin Schlegel Date: Wed, 1 May 2024 21:40:35 +0200 Subject: [PATCH 01/12] lexer implement comments --- Test/TestLexer.hs | 12 ++++++++---- src/Parser/Lexer.x | 7 +++---- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Test/TestLexer.hs b/Test/TestLexer.hs index 6e09005..94046da 100644 --- a/Test/TestLexer.hs +++ b/Test/TestLexer.hs @@ -4,14 +4,18 @@ import Test.HUnit import Parser.Lexer -testCommentSomething = TestCase $ assertEqual "scan /*Something*/" [Comment "/*Something*/"] $ alexScanTokens "/*Something*/" -testEmptyComment = TestCase $ assertEqual "scan /*x*/" [Comment "/**/"] $ alexScanTokens "/**/" -testLineComment = TestCase $ assertEqual "scan // comment" [Comment "// comment"] $ alexScanTokens "// comment" +emptyTokenList :: [Token] +emptyTokenList = [] +testCommentSomething = TestCase $ assertEqual "scan '/*Something*/'" emptyTokenList $ alexScanTokens "/*Something*/" +testEmptyComment = TestCase $ assertEqual "scan '/*x*/'" emptyTokenList $ alexScanTokens "/**/" +testLineComment = TestCase $ assertEqual "scan '// comment'" emptyTokenList $ alexScanTokens "// comment" +testLineCommentEnds = TestCase $ assertEqual "scan '// com\\n'" emptyTokenList $ alexScanTokens "// com\n" tests = TestList [ TestLabel "TestCommentSomething" testCommentSomething, TestLabel "TestEmptyComment" testEmptyComment, - TestLabel "TestLineComment" testLineComment + TestLabel "TestLineComment" testLineComment, + TestLabel "TestLineCommentEnds" testLineCommentEnds ] \ No newline at end of file diff --git a/src/Parser/Lexer.x b/src/Parser/Lexer.x index 2cfa338..d5a472f 100644 --- a/src/Parser/Lexer.x +++ b/src/Parser/Lexer.x @@ -10,15 +10,14 @@ $alphanum = [a-zA-Z0-9] tokens :- $white ; - "/*"(.|\n)*"*/" { \s -> Comment s } - "//".* {\s -> Comment s} + "/*"(.|\n)*"*/" ; + "//".* ; { data Token - = Comment String - | Different + = Different deriving(Eq,Show) } \ No newline at end of file From b8e566a2a0d5ea4ab02cf71924f6d023e551add6 Mon Sep 17 00:00:00 2001 From: Marvin Schlegel Date: Wed, 1 May 2024 22:16:12 +0200 Subject: [PATCH 02/12] lexer implement identifiers --- Test/TestLexer.hs | 9 +++++++-- src/Parser/Lexer.x | 6 ++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Test/TestLexer.hs b/Test/TestLexer.hs index 94046da..848cb4d 100644 --- a/Test/TestLexer.hs +++ b/Test/TestLexer.hs @@ -11,11 +11,16 @@ testEmptyComment = TestCase $ assertEqual "scan '/*x*/'" emptyTokenList $ alex testLineComment = TestCase $ assertEqual "scan '// comment'" emptyTokenList $ alexScanTokens "// comment" testLineCommentEnds = TestCase $ assertEqual "scan '// com\\n'" emptyTokenList $ alexScanTokens "// com\n" - +testIdentifier = TestCase $ assertEqual "scan 'identifier'" [Identifier "identifier"] $ alexScanTokens "identifier" +testShortIdentifier = TestCase $ assertEqual "scan 'i'" [Identifier "i"] $ alexScanTokens "i" +testIdentifierWithNumber = TestCase $ assertEqual "scan 'i2'" [Identifier "i2"] $ alexScanTokens "i2" tests = TestList [ TestLabel "TestCommentSomething" testCommentSomething, TestLabel "TestEmptyComment" testEmptyComment, TestLabel "TestLineComment" testLineComment, - TestLabel "TestLineCommentEnds" testLineCommentEnds + TestLabel "TestLineCommentEnds" testLineCommentEnds, + TestLabel "TestIdentifier" testIdentifier, + TestLabel "TestShortIdentifier" testShortIdentifier, + TestLabel "TestIdentifierWithNumber" testIdentifierWithNumber ] \ No newline at end of file diff --git a/src/Parser/Lexer.x b/src/Parser/Lexer.x index d5a472f..d500674 100644 --- a/src/Parser/Lexer.x +++ b/src/Parser/Lexer.x @@ -7,17 +7,19 @@ $digit = 0-9 $alpha = [a-zA-Z] $alphanum = [a-zA-Z0-9] +$JavaLetter = [A-Za-z\_\$] +$JavaLetterOrDigit = [A-Za-z\_\$0-9] tokens :- $white ; "/*"(.|\n)*"*/" ; "//".* ; - + $JavaLetter$JavaLetterOrDigit* { \s -> Identifier s } { data Token - = Different + = Identifier String deriving(Eq,Show) } \ No newline at end of file From 5d49da69a6b1d4392f60f8822deaa92e31b51a00 Mon Sep 17 00:00:00 2001 From: Marvin Schlegel Date: Wed, 1 May 2024 22:41:06 +0200 Subject: [PATCH 03/12] lexer implement keywords --- Test/TestLexer.hs | 7 ++- src/Parser/Lexer.x | 104 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 108 insertions(+), 3 deletions(-) diff --git a/Test/TestLexer.hs b/Test/TestLexer.hs index 848cb4d..ddd55c9 100644 --- a/Test/TestLexer.hs +++ b/Test/TestLexer.hs @@ -15,6 +15,9 @@ testIdentifier = TestCase $ assertEqual "scan 'identifier'" [Identifier "identif testShortIdentifier = TestCase $ assertEqual "scan 'i'" [Identifier "i"] $ alexScanTokens "i" testIdentifierWithNumber = TestCase $ assertEqual "scan 'i2'" [Identifier "i2"] $ alexScanTokens "i2" +testKeywordBreak = TestCase $ assertEqual "scan 'break'" [BREAK] $ alexScanTokens "break" +testKeywordInt = TestCase $ assertEqual "scan 'int'" [INT] $ alexScanTokens "int" + tests = TestList [ TestLabel "TestCommentSomething" testCommentSomething, TestLabel "TestEmptyComment" testEmptyComment, @@ -22,5 +25,7 @@ tests = TestList [ TestLabel "TestLineCommentEnds" testLineCommentEnds, TestLabel "TestIdentifier" testIdentifier, TestLabel "TestShortIdentifier" testShortIdentifier, - TestLabel "TestIdentifierWithNumber" testIdentifierWithNumber + TestLabel "TestIdentifierWithNumber" testIdentifierWithNumber, + TestLabel "TestKeywordBreak" testKeywordBreak, + TestLabel "TestKeywordInt" testKeywordInt ] \ No newline at end of file diff --git a/src/Parser/Lexer.x b/src/Parser/Lexer.x index d500674..d961036 100644 --- a/src/Parser/Lexer.x +++ b/src/Parser/Lexer.x @@ -14,12 +14,112 @@ tokens :- $white ; "/*"(.|\n)*"*/" ; "//".* ; + -- keywords + "abstract" { \_ -> ABSTRACT } + "assert" { \_ -> BOOLEAN } + "boolean" { \_ -> BOOLEAN} + "break" { \_ -> BREAK} + "byte" { \_ -> BYTE} + "case" { \_ -> CASE} + "catch" { \_ -> CATCH} + "char" { \_ -> CHAR} + "class" { \_ -> CLASS} + "const" { \_ -> CONST} + "continue" { \_ -> CONTINUE} + "default" { \_ -> DEFAULT} + "do" { \_ -> DO} + "double" { \_ -> DOUBLE} + "else" { \_ -> ELSE} + "enum" { \_ -> ENUM} + "extends" { \_ -> EXTENDS} + "final" { \_ -> FINAL} + "finally" { \_ -> FINALLY} + "float" { \_ -> FLOAT} + "for" { \_ -> FOR} + "if" { \_ -> IF} + "goto" { \_ -> GOTO} + "implements" { \_ -> IMPLEMENTS} + "import" { \_ -> IMPORT} + "instanceof" { \_ -> INSTANCEOF} + "int" { \_ -> INT} + "long" { \_ -> LONG} + "native" { \_ -> NATIVE} + "new" { \_ -> NEW} + "package" { \_ -> PACKAGE} + "private" { \_ -> PRIVATE} + "protected" { \_ -> PROTECTED} + "public" { \_ -> PUBLIC} + "return" { \_ -> RETURN} + "short" { \_ -> SHORT} + "static" { \_ -> STATIC} + "strictfp" { \_ -> STRICTFP} + "super" { \_ -> SUPER} + "switch" { \_ -> SWITCH} + "synchronized" { \_ -> SYNCHRONIZED} + "this" { \_ -> THIS} + "throw" { \_ -> THROW} + "throws" { \_ -> THROWS} + "transient" { \_ -> TRANSIENT} + "try" { \_ -> TRY} + "void" { \_ -> VOID} + "volatile" { \_ -> VOLATILE} + "while" { \_ -> WHILE} + -- end keywords $JavaLetter$JavaLetterOrDigit* { \s -> Identifier s } - { data Token - = Identifier String + = ABSTRACT + | ASSERT + | BOOLEAN + | BREAK + | BYTE + | CASE + | CATCH + | CHAR + | CLASS + | CONST + | CONTINUE + | DEFAULT + | DO + | DOUBLE + | ELSE + | ENUM + | EXTENDS + | FINAL + | FINALLY + | FLOAT + | FOR + | IF + | GOTO + | IMPLEMENTS + | IMPORT + | INSTANCEOF + | INT + | INTERFACE + | LONG + | NATIVE + | NEW + | PACKAGE + | PRIVATE + | PROTECTED + | PUBLIC + | RETURN + | SHORT + | STATIC + | STRICTFP + | SUPER + | SWITCH + | SYNCHRONIZED + | THIS + | THROW + | THROWS + | TRANSIENT + | TRY + | VOID + | VOLATILE + | WHILE + | Identifier String deriving(Eq,Show) } \ No newline at end of file From e5baa701b2fe9370a64fd1584091541919e39cdc Mon Sep 17 00:00:00 2001 From: Marvin Schlegel Date: Wed, 1 May 2024 22:46:58 +0200 Subject: [PATCH 04/12] rename Token Identifier to IDENTIFIER --- Test/TestLexer.hs | 6 +++--- src/Parser/Lexer.x | 7 +++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Test/TestLexer.hs b/Test/TestLexer.hs index ddd55c9..99437e5 100644 --- a/Test/TestLexer.hs +++ b/Test/TestLexer.hs @@ -11,9 +11,9 @@ testEmptyComment = TestCase $ assertEqual "scan '/*x*/'" emptyTokenList $ alex testLineComment = TestCase $ assertEqual "scan '// comment'" emptyTokenList $ alexScanTokens "// comment" testLineCommentEnds = TestCase $ assertEqual "scan '// com\\n'" emptyTokenList $ alexScanTokens "// com\n" -testIdentifier = TestCase $ assertEqual "scan 'identifier'" [Identifier "identifier"] $ alexScanTokens "identifier" -testShortIdentifier = TestCase $ assertEqual "scan 'i'" [Identifier "i"] $ alexScanTokens "i" -testIdentifierWithNumber = TestCase $ assertEqual "scan 'i2'" [Identifier "i2"] $ alexScanTokens "i2" +testIdentifier = TestCase $ assertEqual "scan 'identifier'" [IDENTIFIER "identifier"] $ alexScanTokens "identifier" +testShortIdentifier = TestCase $ assertEqual "scan 'i'" [IDENTIFIER "i"] $ alexScanTokens "i" +testIdentifierWithNumber = TestCase $ assertEqual "scan 'i2'" [IDENTIFIER "i2"] $ alexScanTokens "i2" testKeywordBreak = TestCase $ assertEqual "scan 'break'" [BREAK] $ alexScanTokens "break" testKeywordInt = TestCase $ assertEqual "scan 'int'" [INT] $ alexScanTokens "int" diff --git a/src/Parser/Lexer.x b/src/Parser/Lexer.x index d961036..e8078f4 100644 --- a/src/Parser/Lexer.x +++ b/src/Parser/Lexer.x @@ -65,7 +65,9 @@ tokens :- "volatile" { \_ -> VOLATILE} "while" { \_ -> WHILE} -- end keywords - $JavaLetter$JavaLetterOrDigit* { \s -> Identifier s } + $JavaLetter$JavaLetterOrDigit* { \s -> IDENTIFIER s } + -- Literals + { data Token @@ -119,7 +121,8 @@ data Token | VOID | VOLATILE | WHILE - | Identifier String + | IDENTIFIER String + deriving(Eq,Show) } \ No newline at end of file From ecd778cc70f2966f8177cc174712d9d8cce5d22c Mon Sep 17 00:00:00 2001 From: Marvin Schlegel Date: Thu, 2 May 2024 15:57:32 +0200 Subject: [PATCH 05/12] lexer implement literals --- Test/TestLexer.hs | 15 ++++++++++++++- src/Parser/Lexer.x | 15 ++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/Test/TestLexer.hs b/Test/TestLexer.hs index 99437e5..8c1cd91 100644 --- a/Test/TestLexer.hs +++ b/Test/TestLexer.hs @@ -18,6 +18,14 @@ testIdentifierWithNumber = TestCase $ assertEqual "scan 'i2'" [IDENTIFIER "i2"] testKeywordBreak = TestCase $ assertEqual "scan 'break'" [BREAK] $ alexScanTokens "break" testKeywordInt = TestCase $ assertEqual "scan 'int'" [INT] $ alexScanTokens "int" +testIntLiteral = TestCase $ assertEqual "scan '234'" [INTEGERLITERAL 234] $ alexScanTokens "234" +testIntLiteral2 = TestCase $ assertEqual "scan '54_2'" [INTEGERLITERAL 542] $ alexScanTokens "54_2" + +testCharLiteral = TestCase $ assertEqual "scan ''f''" [CHARLITERAL 'f'] $ alexScanTokens "'f'" + +testBoolLiteralTrue = TestCase $ assertEqual "scan 'true'" [BOOLLITERAL True] $ alexScanTokens "true" +testBoolLiteralFalse = TestCase $ assertEqual "scan 'false'" [BOOLLITERAL False] $ alexScanTokens "false" + tests = TestList [ TestLabel "TestCommentSomething" testCommentSomething, TestLabel "TestEmptyComment" testEmptyComment, @@ -27,5 +35,10 @@ tests = TestList [ TestLabel "TestShortIdentifier" testShortIdentifier, TestLabel "TestIdentifierWithNumber" testIdentifierWithNumber, TestLabel "TestKeywordBreak" testKeywordBreak, - TestLabel "TestKeywordInt" testKeywordInt + TestLabel "TestKeywordInt" testKeywordInt, + TestLabel "TestIntLiteral" testIntLiteral, + TestLabel "TestIntLiteral2" testIntLiteral2, + TestLabel "TestCharLiteral" testCharLiteral, + TestLabel "TestBoolLiteralTrue" testBoolLiteralTrue, + TestLabel "TestBoolLiteralFalse" testBoolLiteralFalse ] \ No newline at end of file diff --git a/src/Parser/Lexer.x b/src/Parser/Lexer.x index e8078f4..54694cc 100644 --- a/src/Parser/Lexer.x +++ b/src/Parser/Lexer.x @@ -1,5 +1,6 @@ { - module Parser.Lexer(Token(..), alexScanTokens) where +module Parser.Lexer(Token(..), alexScanTokens) where +import Data.Char } %wrapper "basic" @@ -29,7 +30,7 @@ tokens :- "default" { \_ -> DEFAULT} "do" { \_ -> DO} "double" { \_ -> DOUBLE} - "else" { \_ -> ELSE} + ("else"|"ifn't") { \_ -> ELSE} "enum" { \_ -> ENUM} "extends" { \_ -> EXTENDS} "final" { \_ -> FINAL} @@ -67,7 +68,11 @@ tokens :- -- end keywords $JavaLetter$JavaLetterOrDigit* { \s -> IDENTIFIER s } -- Literals - + [1-9]([0-9\_]*[0-9])* { \s -> INTEGERLITERAL $ read $ filter ((/=) '_') s } + "'"."'" { \s -> CHARLITERAL $ read $ filter ((/=) '\'') s } + "true" { \_ -> BOOLLITERAL True } + "false" { \_ -> BOOLLITERAL False } + "null" { \_ -> NULLLITERAL } { data Token @@ -122,6 +127,10 @@ data Token | VOLATILE | WHILE | IDENTIFIER String + | INTEGERLITERAL Integer + | CHARLITERAL Char + | BOOLLITERAL Bool + | NULLLITERAL deriving(Eq,Show) From 4108eb58c1e7dd1ca04caf17b351c43f3bd6844f Mon Sep 17 00:00:00 2001 From: Marvin Schlegel Date: Thu, 2 May 2024 17:45:04 +0200 Subject: [PATCH 06/12] lexer implement separators and fix literals --- Test/TestLexer.hs | 5 ++++- src/Parser/Lexer.x | 27 +++++++++++++++++++++------ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/Test/TestLexer.hs b/Test/TestLexer.hs index 8c1cd91..b07b38a 100644 --- a/Test/TestLexer.hs +++ b/Test/TestLexer.hs @@ -26,6 +26,8 @@ testCharLiteral = TestCase $ assertEqual "scan ''f''" [CHARLITERAL 'f'] $ alexSc testBoolLiteralTrue = TestCase $ assertEqual "scan 'true'" [BOOLLITERAL True] $ alexScanTokens "true" testBoolLiteralFalse = TestCase $ assertEqual "scan 'false'" [BOOLLITERAL False] $ alexScanTokens "false" +testLBrace = TestCase $ assertEqual "scan '('" [LBRACE] $ alexScanTokens "(" + tests = TestList [ TestLabel "TestCommentSomething" testCommentSomething, TestLabel "TestEmptyComment" testEmptyComment, @@ -40,5 +42,6 @@ tests = TestList [ TestLabel "TestIntLiteral2" testIntLiteral2, TestLabel "TestCharLiteral" testCharLiteral, TestLabel "TestBoolLiteralTrue" testBoolLiteralTrue, - TestLabel "TestBoolLiteralFalse" testBoolLiteralFalse + TestLabel "TestBoolLiteralFalse" testBoolLiteralFalse, + TestLabel "TestLBrace" testLBrace ] \ No newline at end of file diff --git a/src/Parser/Lexer.x b/src/Parser/Lexer.x index 54694cc..13b944a 100644 --- a/src/Parser/Lexer.x +++ b/src/Parser/Lexer.x @@ -1,6 +1,6 @@ { module Parser.Lexer(Token(..), alexScanTokens) where -import Data.Char +import Text.Read } %wrapper "basic" @@ -65,14 +65,23 @@ tokens :- "void" { \_ -> VOID} "volatile" { \_ -> VOLATILE} "while" { \_ -> WHILE} - -- end keywords - $JavaLetter$JavaLetterOrDigit* { \s -> IDENTIFIER s } -- Literals - [1-9]([0-9\_]*[0-9])* { \s -> INTEGERLITERAL $ read $ filter ((/=) '_') s } - "'"."'" { \s -> CHARLITERAL $ read $ filter ((/=) '\'') s } "true" { \_ -> BOOLLITERAL True } "false" { \_ -> BOOLLITERAL False } "null" { \_ -> NULLLITERAL } + -- end keywords + $JavaLetter$JavaLetterOrDigit* { \s -> IDENTIFIER s } + -- Literals + [1-9]([0-9\_]*[0-9])* { \s -> case readMaybe $ filter ((/=) '_') s of Just a -> INTEGERLITERAL a; Nothing -> error ("failed to parse INTLITERAL " ++ s) } + "'"."'" { \s -> case (s) of _ : c : _ -> CHARLITERAL c; _ -> error ("failed to parse CHARLITERAL " ++ s) } + -- separators + "(" { \_ -> LBRACE } + ")" { \_ -> RBRACE } + "{" { \_ -> LBRACKET } + "}" { \_ -> RBRACKET } + ";" { \_ -> SEMICOLON } + "," { \_ -> COMMA} + "." { \_ -> DOT } { data Token @@ -131,7 +140,13 @@ data Token | CHARLITERAL Char | BOOLLITERAL Bool | NULLLITERAL - + | LBRACE + | RBRACE + | LBRACKET + | RBRACKET + | SEMICOLON + | COMMA + | DOT deriving(Eq,Show) } \ No newline at end of file From 95063ac64f93cd11b4df8f95b60433ffe3e1bc58 Mon Sep 17 00:00:00 2001 From: Marvin Schlegel Date: Thu, 2 May 2024 18:14:22 +0200 Subject: [PATCH 07/12] lexer implement operators --- Test/TestLexer.hs | 4 ++- src/Parser/Lexer.x | 72 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/Test/TestLexer.hs b/Test/TestLexer.hs index b07b38a..4838007 100644 --- a/Test/TestLexer.hs +++ b/Test/TestLexer.hs @@ -27,6 +27,7 @@ testBoolLiteralTrue = TestCase $ assertEqual "scan 'true'" [BOOLLITERAL True] $ testBoolLiteralFalse = TestCase $ assertEqual "scan 'false'" [BOOLLITERAL False] $ alexScanTokens "false" testLBrace = TestCase $ assertEqual "scan '('" [LBRACE] $ alexScanTokens "(" +testAnd = TestCase $ assertEqual "scan '&&'" [AND] $ alexScanTokens "&&" tests = TestList [ TestLabel "TestCommentSomething" testCommentSomething, @@ -43,5 +44,6 @@ tests = TestList [ TestLabel "TestCharLiteral" testCharLiteral, TestLabel "TestBoolLiteralTrue" testBoolLiteralTrue, TestLabel "TestBoolLiteralFalse" testBoolLiteralFalse, - TestLabel "TestLBrace" testLBrace + TestLabel "TestLBrace" testLBrace, + TestLabel "TestAnd" testAnd ] \ No newline at end of file diff --git a/src/Parser/Lexer.x b/src/Parser/Lexer.x index 13b944a..d7f551d 100644 --- a/src/Parser/Lexer.x +++ b/src/Parser/Lexer.x @@ -82,6 +82,43 @@ tokens :- ";" { \_ -> SEMICOLON } "," { \_ -> COMMA} "." { \_ -> DOT } + -- operators + "=" { \_ -> ASSIGN } + "==" { \_ -> EQUAL } + "+" { \_ -> PLUS } + "+=" { \_ -> PLUSEQUAL } + ">" { \_ -> GREATER } + ">=" { \_ -> GREATEREQUAL } + "-" { \_ -> MINUS } + "-=" { \_ -> MINUSEQUAL } + "<" { \_ -> LESS } + "<=" { \_ -> LESSEQUAL } + "*" { \_ -> TIMES } + "*=" { \_ -> TIMESEQUAL } + "!" { \_ -> NOT } + "!=" { \_ -> NOTEQUAL } + "/" { \_ -> DIV } + "/=" { \_ -> DIVEQUAL } + "~" { \_ -> BITWISENOT } + "&&" { \_ -> AND } + "&" { \_ -> BITWISEAND } + "&=" { \_ -> ANDEQUAL } + "?" { \_ -> QUESTIONMARK } + "||" { \_ -> OR } + "|" { \_ -> BITWISEOR } + "|=" { \_ -> OREQUAL } + ":" { \_ -> COLON } + "++" { \_ -> INCREMENT } + "^" { \_ -> XOR } + "^=" { \_ -> XOREQUAL } + "--" { \_ -> DECREMENT } + "%" { \_ -> MODULO } + "%=" { \_ -> MODULOEQUAL } + "<<" { \_ -> SHIFTLEFT } + "<<=" { \_ -> SHIFTLEFTEQUAL } + ">>" { \_ -> SHIFTRIGHT } + ">>=" { \_ -> SHIFTRIGHTEQUAL } + { data Token @@ -147,6 +184,41 @@ data Token | SEMICOLON | COMMA | DOT + | ASSIGN + | EQUAL + | PLUS + | PLUSEQUAL + | GREATER + | GREATEREQUAL + | MINUS + | MINUSEQUAL + | LESS + | LESSEQUAL + | TIMES + | TIMESEQUAL + | NOT + | NOTEQUAL + | DIV + | DIVEQUAL + | BITWISENOT + | AND + | BITWISEAND + | ANDEQUAL + | QUESTIONMARK + | OR + | BITWISEOR + | OREQUAL + | COLON + | INCREMENT + | XOR + | XOREQUAL + | DECREMENT + | MODULO + | MODULOEQUAL + | SHIFTLEFT + | SHIFTLEFTEQUAL + | SHIFTRIGHT + | SHIFTRIGHTEQUAL deriving(Eq,Show) } \ No newline at end of file From db2b4a142c716ac4e4e2a3a69cf93b46200ccb7e Mon Sep 17 00:00:00 2001 From: Marvin Schlegel Date: Thu, 2 May 2024 22:21:53 +0200 Subject: [PATCH 08/12] lexer adjustments --- src/Parser/Lexer.x | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Parser/Lexer.x b/src/Parser/Lexer.x index d7f551d..ef76773 100644 --- a/src/Parser/Lexer.x +++ b/src/Parser/Lexer.x @@ -118,6 +118,8 @@ tokens :- "<<=" { \_ -> SHIFTLEFTEQUAL } ">>" { \_ -> SHIFTRIGHT } ">>=" { \_ -> SHIFTRIGHTEQUAL } + ">>>" { \_ -> UNSIGNEDSHIFTRIGHT } + ">>>=" { \_ -> UNSIGNEDSHIFTRIGHTEQUAL } { @@ -173,7 +175,7 @@ data Token | VOLATILE | WHILE | IDENTIFIER String - | INTEGERLITERAL Integer + | INTEGERLITERAL Int | CHARLITERAL Char | BOOLLITERAL Bool | NULLLITERAL @@ -219,6 +221,8 @@ data Token | SHIFTLEFTEQUAL | SHIFTRIGHT | SHIFTRIGHTEQUAL + | UNSIGNEDSHIFTRIGHT + | UNSIGNEDSHIFTRIGHTEQUAL deriving(Eq,Show) } \ No newline at end of file From fe4091da99603678133bd6610aeea544dbaa9cde Mon Sep 17 00:00:00 2001 From: Marvin Schlegel Date: Thu, 2 May 2024 22:33:35 +0200 Subject: [PATCH 09/12] start implementing parser --- Test/TestParser.hs | 14 ++++++++++++++ Test/TestSuite.hs | 8 +++++--- project.cabal | 8 ++++++-- 3 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 Test/TestParser.hs diff --git a/Test/TestParser.hs b/Test/TestParser.hs new file mode 100644 index 0000000..23346f3 --- /dev/null +++ b/Test/TestParser.hs @@ -0,0 +1,14 @@ +module TestParser(tests) where + +import Test.HUnit +import Parser.Lexer +import Parser.JavaParser + + +testIntLiteral = TestCase $ assertEqual "IntLiteral 34" [IntLiteral 34] $ parse (INTLITERAL 34) + +testAnd = TestCase $ assertEqual "scan '&&'" [AND] $ alexScanTokens "&&" + +tests = TestList [ + testIntLiteral + ] \ No newline at end of file diff --git a/Test/TestSuite.hs b/Test/TestSuite.hs index 9748fba..1fd2cbb 100644 --- a/Test/TestSuite.hs +++ b/Test/TestSuite.hs @@ -1,11 +1,13 @@ module Main where import Test.HUnit -import Parser.Lexer import TestLexer +-- import TestParser -otherTest = TestCase $ assertEqual "math" (4+3) 7 -tests = TestList [TestLabel "TestLexer" TestLexer.tests, TestLabel "mathTest" otherTest] +tests = TestList [ + TestLabel "TestLexer" TestLexer.tests + -- TestLabel "TestParser" TestParser.tests + ] main = do runTestTTAndExit Main.tests \ No newline at end of file diff --git a/project.cabal b/project.cabal index 69ef52a..357434e 100644 --- a/project.cabal +++ b/project.cabal @@ -12,7 +12,7 @@ executable compiler default-language: Haskell2010 hs-source-dirs: src build-tool-depends: alex:alex, happy:happy - other-modules: Parser.Lexer, Ast + other-modules: Parser.Lexer, Parser.JavaParser, Ast test-suite tests type: exitcode-stdio-1.0 @@ -22,4 +22,8 @@ test-suite tests array, HUnit build-tool-depends: alex:alex, happy:happy - other-modules: Parser.Lexer, TestLexer + other-modules: Parser.Lexer, + Parser.JavaParser, + Ast, + TestLexer + TestParser From fa2dc24aa0213b8c9ce417dfab75e83a2d39036c Mon Sep 17 00:00:00 2001 From: Marvin Schlegel Date: Thu, 2 May 2024 22:38:58 +0200 Subject: [PATCH 10/12] indent with spaces --- src/Parser/JavaParser.y | 242 ++++++++++++++++++++-------------------- 1 file changed, 120 insertions(+), 122 deletions(-) diff --git a/src/Parser/JavaParser.y b/src/Parser/JavaParser.y index 7b0695c..fc4ce89 100644 --- a/src/Parser/JavaParser.y +++ b/src/Parser/JavaParser.y @@ -1,6 +1,6 @@ { module Parser.JavaParser (parse) where ---import AbsSyn +import Ast import Parser.Lexer } @@ -15,9 +15,9 @@ import Parser.Lexer CHAR { CHAR } CLASS { CLASS} IDENTIFIER { IDENTIFIER $$} - INTLITERAL { INTLITERAL $$} + INTLITERAL { INTEGERLITERAL $$} DOT { DOT } - MOD { MOD } + MOD { MODULO } TIMESEQUAL { TIMESEQUAL } GREATEREQUAL { GREATEREQUAL } WHILE { WHILE } @@ -29,30 +29,29 @@ import Parser.Lexer THIS { THIS } STATIC { STATIC } PROTECTED { PROTECTED } - TILDE { TILDE } - MUL { MUL } + TILDE { BITWISENOT } + MUL { TIMES } MINUS { MINUS } - EXCLMARK { EXCLMARK } + EXCLMARK { NOT } IF { IF } ELSE { ELSE } - DIVIDEEQUAL { DIVIDEEQUAL } + DIVIDEEQUAL { DIVEQUAL } NEW { NEW } LBRACKET { LBRACKET } - JNULL { JNULL } - BOOLLITERAL { BOOLLITERAL } + JNULL { NULLLITERAL } + BOOLLITERAL { BOOLLITERAL $$ } DIV { DIV } - LOGICALOR { LOGICALOR } + LOGICALOR { OR } NOTEQUAL { NOTEQUAL } INSTANCEOF { INSTANCEOF } ANDEQUAL { ANDEQUAL } ASSIGN { ASSIGN } DECREMENT { DECREMENT } - STRINGLITERAL { STRINGLITERAL } - CHARLITERAL { CHARLITERAL } + CHARLITERAL { CHARLITERAL $$ } AND { AND } XOREQUAL { XOREQUAL } RETURN { RETURN } - QUESMARK { QUESMARK } + QUESMARK { QUESTIONMARK } SHIFTLEFTEQUAL { SHIFTLEFTEQUAL } RBRACKET { RBRACKET } COMMA { COMMA } @@ -68,7 +67,7 @@ import Parser.Lexer INT { INT } ABSTRACT { ABSTRACT } SEMICOLON { SEMICOLON } - SIGNEDSHIFTRIGHTEQUAL { SIGNEDSHIFTRIGHTEQUAL } + SIGNEDSHIFTRIGHTEQUAL { SHIFTRIGHTEQUAL } UNSIGNEDSHIFTRIGHTEQUAL { UNSIGNEDSHIFTRIGHTEQUAL } PLUSEQUAL { PLUSEQUAL } OREQUAL { OREQUAL } @@ -79,10 +78,10 @@ import Parser.Lexer compilationunit : typedeclarations { } typedeclarations : typedeclaration { } - | typedeclarations typedeclaration { } + | typedeclarations typedeclaration { } name : qualifiedname { } - | simplename { } + | simplename { } typedeclaration : classdeclaration { } @@ -94,16 +93,16 @@ classdeclaration : CLASS IDENTIFIER classbody { } | modifiers CLASS IDENTIFIER classbody { } classbody : LBRACKET RBRACKET { ([], []) } - | LBRACKET classbodydeclarations RBRACKET { } + | LBRACKET classbodydeclarations RBRACKET { } modifiers : modifier { } - | modifiers modifier { } + | modifiers modifier { } classbodydeclarations : classbodydeclaration { } - | classbodydeclarations classbodydeclaration{ } + | classbodydeclarations classbodydeclaration{ } modifier : PUBLIC { } - | PROTECTED { } + | PROTECTED { } | PRIVATE { } | STATIC { } | ABSTRACT { } @@ -111,77 +110,77 @@ modifier : PUBLIC { } classtype : classorinterfacetype{ } classbodydeclaration : classmemberdeclaration { } - | constructordeclaration { } + | constructordeclaration { } classorinterfacetype : name{ } classmemberdeclaration : fielddeclaration { } - | methoddeclaration { } + | methoddeclaration { } constructordeclaration : constructordeclarator constructorbody { } - | modifiers constructordeclarator constructorbody { } + | modifiers constructordeclarator constructorbody { } fielddeclaration : type variabledeclarators SEMICOLON { } - | modifiers type variabledeclarators SEMICOLON { } + | modifiers type variabledeclarators SEMICOLON { } methoddeclaration : methodheader methodbody { } block : LBRACKET RBRACKET { } - | LBRACKET blockstatements RBRACKET { } + | LBRACKET blockstatements RBRACKET { } constructordeclarator : simplename LBRACE RBRACE { } - | simplename LBRACE formalparameterlist RBRACE { } + | simplename LBRACE formalparameterlist RBRACE { } -constructorbody : LBRACKET RBRACKET { } - | LBRACKET explicitconstructorinvocation RBRACKET { } - | LBRACKET blockstatements RBRACKET { } - | LBRACKET explicitconstructorinvocation blockstatements RBRACKET { } +constructorbody : LBRACKET RBRACKET { } + | LBRACKET explicitconstructorinvocation RBRACKET { } + | LBRACKET blockstatements RBRACKET { } + | LBRACKET explicitconstructorinvocation blockstatements RBRACKET { } -methodheader : type methoddeclarator { } - | modifiers type methoddeclarator { } - | VOID methoddeclarator { } - | modifiers VOID methoddeclarator { } +methodheader : type methoddeclarator { } + | modifiers type methoddeclarator { } + | VOID methoddeclarator { } + | modifiers VOID methoddeclarator { } type : primitivetype { } - | referencetype { } + | referencetype { } variabledeclarators : variabledeclarator { } - | variabledeclarators COMMA variabledeclarator { } + | variabledeclarators COMMA variabledeclarator { } methodbody : block { } - | SEMICOLON { } + | SEMICOLON { } blockstatements : blockstatement { } - | blockstatements blockstatement { } + | blockstatements blockstatement { } formalparameterlist : formalparameter { } - | formalparameterlist COMMA formalparameter{ } + | formalparameterlist COMMA formalparameter{ } explicitconstructorinvocation : THIS LBRACE RBRACE SEMICOLON { } - | THIS LBRACE argumentlist RBRACE SEMICOLON { } + | THIS LBRACE argumentlist RBRACE SEMICOLON { } classtypelist : classtype { } - | classtypelist COMMA classtype { } + | classtypelist COMMA classtype { } methoddeclarator : IDENTIFIER LBRACE RBRACE { } - | IDENTIFIER LBRACE formalparameterlist RBRACE { } + | IDENTIFIER LBRACE formalparameterlist RBRACE { } primitivetype : BOOLEAN { } - | numerictype { } + | numerictype { } referencetype : classorinterfacetype { } variabledeclarator : variabledeclaratorid { } - | variabledeclaratorid ASSIGN variableinitializer { } + | variabledeclaratorid ASSIGN variableinitializer { } -blockstatement : localvariabledeclarationstatement { } - | statement { } +blockstatement : localvariabledeclarationstatement { } + | statement { } formalparameter : type variabledeclaratorid { } argumentlist : expression { } - | argumentlist COMMA expression { } + | argumentlist COMMA expression { } numerictype : integraltype { } @@ -192,10 +191,10 @@ variableinitializer : expression { } localvariabledeclarationstatement : localvariabledeclaration SEMICOLON { } statement : statementwithouttrailingsubstatement{ } - | ifthenstatement { } - | ifthenelsestatement { } - | whilestatement { } - + | ifthenstatement { } + | ifthenelsestatement { } + | whilestatement { } + expression : assignmentexpression { } @@ -205,9 +204,9 @@ integraltype : INT { } localvariabledeclaration : type variabledeclarators { } statementwithouttrailingsubstatement : block { } - | emptystatement { } - | expressionstatement { } - | returnstatement { } + | emptystatement { } + | expressionstatement { } + | returnstatement { } ifthenstatement : IF LBRACE expression RBRACE statement { } @@ -216,55 +215,55 @@ ifthenelsestatement : IF LBRACE expression RBRACE statementnoshortif ELSE state whilestatement : WHILE LBRACE expression RBRACE statement { } assignmentexpression : conditionalexpression { } - | assignment{ } + | assignment{ } -emptystatement : SEMICOLON { } +emptystatement : SEMICOLON { } expressionstatement : statementexpression SEMICOLON { } returnstatement : RETURN SEMICOLON { } - | RETURN expression SEMICOLON { } + | RETURN expression SEMICOLON { } statementnoshortif : statementwithouttrailingsubstatement { } - | ifthenelsestatementnoshortif { } - | whilestatementnoshortif { } + | ifthenelsestatementnoshortif { } + | whilestatementnoshortif { } conditionalexpression : conditionalorexpression { } - | conditionalorexpression QUESMARK expression COLON conditionalexpression { } + | conditionalorexpression QUESMARK expression COLON conditionalexpression { } assignment :lefthandside assignmentoperator assignmentexpression { } - + statementexpression : assignment { } - | preincrementexpression { } - | predecrementexpression { } - | postincrementexpression { } - | postdecrementexpression { } - | methodinvocation { } - | classinstancecreationexpression { } + | preincrementexpression { } + | predecrementexpression { } + | postincrementexpression { } + | postdecrementexpression { } + | methodinvocation { } + | classinstancecreationexpression { } ifthenelsestatementnoshortif :IF LBRACE expression RBRACE statementnoshortif - ELSE statementnoshortif { } + ELSE statementnoshortif { } whilestatementnoshortif : WHILE LBRACE expression RBRACE statementnoshortif { } conditionalorexpression : conditionalandexpression { } - | conditionalorexpression LOGICALOR conditionalandexpression{ } + | conditionalorexpression LOGICALOR conditionalandexpression{ } lefthandside : name { } assignmentoperator : ASSIGN{ } - | TIMESEQUAL { } - | DIVIDEEQUAL { } - | MODULOEQUAL { } - | PLUSEQUAL { } - | MINUSEQUAL { } - | SHIFTLEFTEQUAL { } - | SIGNEDSHIFTRIGHTEQUAL { } - | UNSIGNEDSHIFTRIGHTEQUAL { } - | ANDEQUAL { } - | XOREQUAL { } - | OREQUAL{ } + | TIMESEQUAL { } + | DIVIDEEQUAL { } + | MODULOEQUAL { } + | PLUSEQUAL { } + | MINUSEQUAL { } + | SHIFTLEFTEQUAL { } + | SIGNEDSHIFTRIGHTEQUAL { } + | UNSIGNEDSHIFTRIGHTEQUAL { } + | ANDEQUAL { } + | XOREQUAL { } + | OREQUAL{ } preincrementexpression : INCREMENT unaryexpression { } @@ -275,9 +274,9 @@ postincrementexpression : postfixexpression INCREMENT { } postdecrementexpression : postfixexpression DECREMENT { } methodinvocation : name LBRACE RBRACE { } - | name LBRACE argumentlist RBRACE { } - | primary DOT IDENTIFIER LBRACE RBRACE { } - | primary DOT IDENTIFIER LBRACE argumentlist RBRACE { } + | name LBRACE argumentlist RBRACE { } + | primary DOT IDENTIFIER LBRACE RBRACE { } + | primary DOT IDENTIFIER LBRACE argumentlist RBRACE { } classinstancecreationexpression : NEW classtype LBRACE RBRACE { } | NEW classtype LBRACE argumentlist RBRACE { } @@ -286,70 +285,69 @@ conditionalandexpression : inclusiveorexpression { } fieldaccess : primary DOT IDENTIFIER { } -unaryexpression : preincrementexpression { } - | predecrementexpression { } - | PLUS unaryexpression { } - | MINUS unaryexpression { } - | unaryexpressionnotplusminus { } +unaryexpression : preincrementexpression { } + | predecrementexpression { } + | PLUS unaryexpression { } + | MINUS unaryexpression { } + | unaryexpressionnotplusminus { } postfixexpression : primary { } - | name { } - | postincrementexpression { } - | postdecrementexpression{ } + | name { } + | postincrementexpression { } + | postdecrementexpression{ } -primary : primarynonewarray { } +primary : primarynonewarray { } inclusiveorexpression : exclusiveorexpression { } - | inclusiveorexpression OR exclusiveorexpression { } + | inclusiveorexpression OR exclusiveorexpression { } primarynonewarray : literal { } - | THIS { } - | LBRACE expression RBRACE { } + | THIS { } + | LBRACE expression RBRACE { } | classinstancecreationexpression { } - | fieldaccess { } - | methodinvocation { } + | fieldaccess { } + | methodinvocation { } unaryexpressionnotplusminus : postfixexpression { } - | TILDE unaryexpression { } - | EXCLMARK unaryexpression { } - | castexpression{ } + | TILDE unaryexpression { } + | EXCLMARK unaryexpression { } + | castexpression{ } exclusiveorexpression : andexpression { } - | exclusiveorexpression XOR andexpression { } + | exclusiveorexpression XOR andexpression { } -literal : INTLITERAL { } - | BOOLLITERAL { } - | CHARLITERAL { } - | STRINGLITERAL { } - | JNULL { } +literal : INTLITERAL { } + | BOOLLITERAL { } + | CHARLITERAL { } + | JNULL { } -castexpression : LBRACE primitivetype RBRACE unaryexpression { } - | LBRACE expression RBRACE unaryexpressionnotplusminus{ } +castexpression : LBRACE primitivetype RBRACE unaryexpression { } + | LBRACE expression RBRACE unaryexpressionnotplusminus{ } andexpression : equalityexpression { } - | andexpression AND equalityexpression { } + | andexpression AND equalityexpression { } equalityexpression : relationalexpression { } - | equalityexpression EQUAL relationalexpression { } - | equalityexpression NOTEQUAL relationalexpression { } + | equalityexpression EQUAL relationalexpression { } + | equalityexpression NOTEQUAL relationalexpression { } relationalexpression : shiftexpression { } - | relationalexpression LESS shiftexpression { } - | relationalexpression GREATER shiftexpression { } - | relationalexpression LESSEQUAL shiftexpression { } - | relationalexpression GREATEREQUAL shiftexpression { } - | relationalexpression INSTANCEOF referencetype { } + | relationalexpression LESS shiftexpression { } + | relationalexpression GREATER shiftexpression { } + | relationalexpression LESSEQUAL shiftexpression { } + | relationalexpression GREATEREQUAL shiftexpression { } + | relationalexpression INSTANCEOF referencetype { } -shiftexpression : additiveexpression { } +shiftexpression : additiveexpression { } additiveexpression : multiplicativeexpression { } - | additiveexpression PLUS multiplicativeexpression { } - | additiveexpression MINUS multiplicativeexpression { } + | additiveexpression PLUS multiplicativeexpression { } + | additiveexpression MINUS multiplicativeexpression { } multiplicativeexpression : unaryexpression { } - | multiplicativeexpression MUL unaryexpression { } - | multiplicativeexpression DIV unaryexpression { } - | multiplicativeexpression MOD unaryexpression { } + | multiplicativeexpression MUL unaryexpression { } + | multiplicativeexpression DIV unaryexpression { } + | multiplicativeexpression MOD unaryexpression { } { From fa9cb761d52e132711bf1709530fd41b073987c5 Mon Sep 17 00:00:00 2001 From: Marvin Schlegel Date: Fri, 3 May 2024 15:47:41 +0200 Subject: [PATCH 11/12] parser implement class --- Test/TestParser.hs | 13 ++++++++++--- Test/TestSuite.hs | 6 +++--- src/Ast.hs | 9 +++++++++ src/Parser/JavaParser.y | 16 ++++++++-------- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/Test/TestParser.hs b/Test/TestParser.hs index 23346f3..775de17 100644 --- a/Test/TestParser.hs +++ b/Test/TestParser.hs @@ -3,12 +3,19 @@ module TestParser(tests) where import Test.HUnit import Parser.Lexer import Parser.JavaParser +import Ast -testIntLiteral = TestCase $ assertEqual "IntLiteral 34" [IntLiteral 34] $ parse (INTLITERAL 34) +testSingleEmptyClass = TestCase $ + assertEqual "expect single empty class hello" [Class "Hello" [] []] $ + parse [CLASS, IDENTIFIER "Hello", LBRACKET, RBRACKET] +testTwoEmptyClasses = TestCase $ + assertEqual "expect two empty classes" [Class "Class1" [] [], Class "Class2" [] []] $ + parse [CLASS,IDENTIFIER "Class1",LBRACKET,RBRACKET,CLASS,IDENTIFIER "Class2",LBRACKET,RBRACKET] + -testAnd = TestCase $ assertEqual "scan '&&'" [AND] $ alexScanTokens "&&" tests = TestList [ - testIntLiteral + testSingleEmptyClass, + testTwoEmptyClasses ] \ No newline at end of file diff --git a/Test/TestSuite.hs b/Test/TestSuite.hs index 1fd2cbb..ff395c5 100644 --- a/Test/TestSuite.hs +++ b/Test/TestSuite.hs @@ -2,12 +2,12 @@ module Main where import Test.HUnit import TestLexer --- import TestParser +import TestParser tests = TestList [ - TestLabel "TestLexer" TestLexer.tests - -- TestLabel "TestParser" TestParser.tests + TestLabel "TestLexer" TestLexer.tests, + TestLabel "TestParser" TestParser.tests ] main = do runTestTTAndExit Main.tests \ No newline at end of file diff --git a/src/Ast.hs b/src/Ast.hs index 2c131c6..10d3d28 100644 --- a/src/Ast.hs +++ b/src/Ast.hs @@ -5,9 +5,13 @@ type DataType = String type Identifier = String data ParameterDeclaration = ParameterDeclaration DataType Identifier + deriving(Show, Eq) data VariableDeclaration = VariableDeclaration DataType Identifier (Maybe Expression) + deriving(Show, Eq) data Class = Class DataType [MethodDeclaration] [VariableDeclaration] + deriving(Show, Eq) data MethodDeclaration = MethodDeclaration DataType Identifier [ParameterDeclaration] Statement + deriving(Show, Eq) data Statement = If Expression Statement (Maybe Statement) | LocalVariableDeclaration VariableDeclaration @@ -16,11 +20,13 @@ data Statement = If Expression Statement (Maybe Statement) | Return (Maybe Expression) | StatementExpressionStatement StatementExpression | TypedStatement DataType Statement + deriving(Show, Eq) data StatementExpression = Assignment Identifier Expression | ConstructorCall DataType [Expression] | MethodCall Identifier [Expression] | TypedStatementExpression DataType StatementExpression + deriving(Show, Eq) data BinaryOperator = Addition | Subtraction @@ -38,9 +44,11 @@ data BinaryOperator = Addition | And | Or | NameResolution + deriving(Show, Eq) data UnaryOperator = Not | Minus + deriving(Show, Eq) data Expression = IntegerLiteral Int | CharacterLiteral Char @@ -51,4 +59,5 @@ data Expression = IntegerLiteral Int | UnaryOperation UnaryOperator Expression | StatementExpressionExpression StatementExpression | TypedExpression DataType Expression + deriving(Show, Eq) \ No newline at end of file diff --git a/src/Parser/JavaParser.y b/src/Parser/JavaParser.y index fc4ce89..f673532 100644 --- a/src/Parser/JavaParser.y +++ b/src/Parser/JavaParser.y @@ -14,7 +14,7 @@ import Parser.Lexer CASE { CASE } CHAR { CHAR } CLASS { CLASS} - IDENTIFIER { IDENTIFIER $$} + IDENTIFIER { IDENTIFIER $$ } INTLITERAL { INTEGERLITERAL $$} DOT { DOT } MOD { MODULO } @@ -75,25 +75,25 @@ import Parser.Lexer LESS { LESS } %% -compilationunit : typedeclarations { } +compilationunit : typedeclarations { $1 } -typedeclarations : typedeclaration { } - | typedeclarations typedeclaration { } +typedeclarations : typedeclaration { [$1] } + | typedeclarations typedeclaration { $1 ++ [$2] } name : qualifiedname { } | simplename { } -typedeclaration : classdeclaration { } +typedeclaration : classdeclaration { $1 } qualifiedname : name DOT IDENTIFIER { } simplename : IDENTIFIER { } -classdeclaration : CLASS IDENTIFIER classbody { } - | modifiers CLASS IDENTIFIER classbody { } +classdeclaration : CLASS IDENTIFIER classbody { case $3 of (methods, attributes) -> Class $2 methods attributes } + | modifiers CLASS IDENTIFIER classbody { case $4 of (methods, attributes) -> Class $3 methods attributes } classbody : LBRACKET RBRACKET { ([], []) } - | LBRACKET classbodydeclarations RBRACKET { } + | LBRACKET classbodydeclarations RBRACKET { ([], []) } modifiers : modifier { } | modifiers modifier { } From af7162ea549e01554976dc950d1c5177d6e1fc01 Mon Sep 17 00:00:00 2001 From: Marvin Schlegel Date: Fri, 3 May 2024 17:47:59 +0200 Subject: [PATCH 12/12] parser implement fields --- Test/TestParser.hs | 11 +++++-- src/Parser/JavaParser.y | 67 ++++++++++++++++++++++++++--------------- 2 files changed, 52 insertions(+), 26 deletions(-) diff --git a/Test/TestParser.hs b/Test/TestParser.hs index 775de17..ce3f2cc 100644 --- a/Test/TestParser.hs +++ b/Test/TestParser.hs @@ -12,10 +12,17 @@ testSingleEmptyClass = TestCase $ testTwoEmptyClasses = TestCase $ assertEqual "expect two empty classes" [Class "Class1" [] [], Class "Class2" [] []] $ parse [CLASS,IDENTIFIER "Class1",LBRACKET,RBRACKET,CLASS,IDENTIFIER "Class2",LBRACKET,RBRACKET] - +testBooleanField = TestCase $ + assertEqual "expect class with boolean field" [Class "WithBool" [] [VariableDeclaration "boolean" "value" Nothing]] $ + parse [CLASS,IDENTIFIER "WithBool",LBRACKET,BOOLEAN,IDENTIFIER "value",SEMICOLON,RBRACKET] +testIntField = TestCase $ + assertEqual "expect class with int field" [Class "WithInt" [] [VariableDeclaration "int" "value" Nothing]] $ + parse [CLASS,IDENTIFIER "WithInt",LBRACKET,INT,IDENTIFIER "value",SEMICOLON,RBRACKET] tests = TestList [ testSingleEmptyClass, - testTwoEmptyClasses + testTwoEmptyClasses, + testBooleanField, + testIntField ] \ No newline at end of file diff --git a/src/Parser/JavaParser.y b/src/Parser/JavaParser.y index f673532..bfe74b2 100644 --- a/src/Parser/JavaParser.y +++ b/src/Parser/JavaParser.y @@ -89,17 +89,25 @@ qualifiedname : name DOT IDENTIFIER { } simplename : IDENTIFIER { } -classdeclaration : CLASS IDENTIFIER classbody { case $3 of (methods, attributes) -> Class $2 methods attributes } - | modifiers CLASS IDENTIFIER classbody { case $4 of (methods, attributes) -> Class $3 methods attributes } +classdeclaration : CLASS IDENTIFIER classbody { case $3 of (methods, fields) -> Class $2 methods fields } + -- | modifiers CLASS IDENTIFIER classbody { case $4 of (methods, fields) -> Class $3 methods fields } classbody : LBRACKET RBRACKET { ([], []) } - | LBRACKET classbodydeclarations RBRACKET { ([], []) } + | LBRACKET classbodydeclarations RBRACKET { $2 } modifiers : modifier { } | modifiers modifier { } -classbodydeclarations : classbodydeclaration { } - | classbodydeclarations classbodydeclaration{ } +classbodydeclarations : classbodydeclaration { + case $1 of + MethodDecl method -> ([method], []) + FieldDecls fields -> ([], fields) + } + -- | classbodydeclarations classbodydeclaration { + -- case ($1, $2) of + -- ((methods, fields), MethodDecl method) -> ((methods ++ [method]), fields) + -- ((methods, fields), FieldDecl field) -> (methods, (fields ++ [field])) + -- } modifier : PUBLIC { } | PROTECTED { } @@ -109,19 +117,19 @@ modifier : PUBLIC { } classtype : classorinterfacetype{ } -classbodydeclaration : classmemberdeclaration { } - | constructordeclaration { } +classbodydeclaration : classmemberdeclaration { $1 } + -- | constructordeclaration { FieldDecl $ VariableDeclaration "int" "a" Nothing } -- TODO classorinterfacetype : name{ } -classmemberdeclaration : fielddeclaration { } - | methoddeclaration { } +classmemberdeclaration : fielddeclaration { $1 } + -- | methoddeclaration { } constructordeclaration : constructordeclarator constructorbody { } | modifiers constructordeclarator constructorbody { } -fielddeclaration : type variabledeclarators SEMICOLON { } - | modifiers type variabledeclarators SEMICOLON { } +fielddeclaration : type variabledeclarators SEMICOLON { FieldDecls $ map (convertDeclarator $1) $2 } + -- | modifiers type variabledeclarators SEMICOLON {} methoddeclaration : methodheader methodbody { } @@ -141,11 +149,11 @@ methodheader : type methoddeclarator { } | VOID methoddeclarator { } | modifiers VOID methoddeclarator { } -type : primitivetype { } - | referencetype { } +type : primitivetype { $1 } + -- | referencetype { } -variabledeclarators : variabledeclarator { } - | variabledeclarators COMMA variabledeclarator { } +variabledeclarators : variabledeclarator { [$1] } + -- | variabledeclarators COMMA variabledeclarator { $1 ++ [$3] } methodbody : block { } | SEMICOLON { } @@ -165,14 +173,14 @@ classtypelist : classtype { } methoddeclarator : IDENTIFIER LBRACE RBRACE { } | IDENTIFIER LBRACE formalparameterlist RBRACE { } -primitivetype : BOOLEAN { } - | numerictype { } +primitivetype : BOOLEAN { "boolean" } + | numerictype { $1 } referencetype : classorinterfacetype { } -variabledeclarator : variabledeclaratorid { } - | variabledeclaratorid ASSIGN variableinitializer { } +variabledeclarator : variabledeclaratorid { Declarator $1 Nothing } + -- | variabledeclaratorid ASSIGN variableinitializer { Declarator $1 Nothing } -- TODO blockstatement : localvariabledeclarationstatement { } | statement { } @@ -182,9 +190,9 @@ formalparameter : type variabledeclaratorid { } argumentlist : expression { } | argumentlist COMMA expression { } -numerictype : integraltype { } +numerictype : integraltype { $1 } -variabledeclaratorid : IDENTIFIER { } +variabledeclaratorid : IDENTIFIER { $1 } variableinitializer : expression { } @@ -198,8 +206,8 @@ statement : statementwithouttrailingsubstatement{ } expression : assignmentexpression { } -integraltype : INT { } - | CHAR { } +integraltype : INT { "int" } + | CHAR { "char" } localvariabledeclaration : type variabledeclarators { } @@ -352,7 +360,18 @@ multiplicativeexpression : unaryexpression { } { +data MethodOrFieldDeclaration = MethodDecl MethodDeclaration + | FieldDecls [VariableDeclaration] + +data Declarator = Declarator Identifier (Maybe Expression) + +-- convertDeclaratorList :: [DataType] -> MethodOrFieldDeclaration +-- convertDeclaratorList = FieldDecls $ map + +convertDeclarator :: DataType -> Declarator -> VariableDeclaration +convertDeclarator dataType (Declarator id assigment) = VariableDeclaration dataType id assigment + parseError :: [Token] -> a -parseError _ = error "Parse error" +parseError msg = error ("Parse error: " ++ show msg) }