diff --git a/Test/TestLexer.hs b/Test/TestLexer.hs index 6e09005..4838007 100644 --- a/Test/TestLexer.hs +++ b/Test/TestLexer.hs @@ -4,14 +4,46 @@ 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" +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" + +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" + +testLBrace = TestCase $ assertEqual "scan '('" [LBRACE] $ alexScanTokens "(" +testAnd = TestCase $ assertEqual "scan '&&'" [AND] $ alexScanTokens "&&" tests = TestList [ TestLabel "TestCommentSomething" testCommentSomething, TestLabel "TestEmptyComment" testEmptyComment, - TestLabel "TestLineComment" testLineComment + TestLabel "TestLineComment" testLineComment, + TestLabel "TestLineCommentEnds" testLineCommentEnds, + TestLabel "TestIdentifier" testIdentifier, + TestLabel "TestShortIdentifier" testShortIdentifier, + TestLabel "TestIdentifierWithNumber" testIdentifierWithNumber, + TestLabel "TestKeywordBreak" testKeywordBreak, + TestLabel "TestKeywordInt" testKeywordInt, + TestLabel "TestIntLiteral" testIntLiteral, + TestLabel "TestIntLiteral2" testIntLiteral2, + TestLabel "TestCharLiteral" testCharLiteral, + TestLabel "TestBoolLiteralTrue" testBoolLiteralTrue, + TestLabel "TestBoolLiteralFalse" testBoolLiteralFalse, + TestLabel "TestLBrace" testLBrace, + TestLabel "TestAnd" testAnd ] \ No newline at end of file diff --git a/Test/TestParser.hs b/Test/TestParser.hs new file mode 100644 index 0000000..ce3f2cc --- /dev/null +++ b/Test/TestParser.hs @@ -0,0 +1,28 @@ +module TestParser(tests) where + +import Test.HUnit +import Parser.Lexer +import Parser.JavaParser +import Ast + + +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] +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, + testBooleanField, + testIntField + ] \ No newline at end of file diff --git a/Test/TestSuite.hs b/Test/TestSuite.hs index da03223..bf2c67e 100644 --- a/Test/TestSuite.hs +++ b/Test/TestSuite.hs @@ -3,9 +3,12 @@ module Main where import Test.HUnit import TestLexer import TestByteCodeGenerator +import TestParser -otherTest = TestCase $ assertEqual "math" (4+3) 7 -tests = TestList [TestLabel "TestLexer" TestLexer.tests, TestLabel "mathTest" otherTest, TestLabel "bytecodeTest" TestByteCodeGenerator.tests] +tests = TestList [ + TestLabel "TestLexer" TestLexer.tests, + TestLabel "TestParser" TestParser.tests, + TestLabel "TestByteCodeGenerator" TestByteCodeGenerator.tests] main = do runTestTTAndExit Main.tests \ No newline at end of file diff --git a/project.cabal b/project.cabal index 0b698ae..cf8bce0 100644 --- a/project.cabal +++ b/project.cabal @@ -1,31 +1,48 @@ -name: MiniJavaCompiler -version: 0.1.0.0 -build-type: Simple -cabal-version: >= 1.10 -Synopsis: A compiler for a minimal version of Java with watered down syntax. - -executable compiler - main-is: Main.hs - build-depends: base, - array, - HUnit, - utf8-string, - bytestring - default-language: Haskell2010 - hs-source-dirs: src, - src/ByteCode, - src/ByteCode/ClassFile - build-tool-depends: alex:alex, happy:happy - other-modules: Ast, Example, Typecheck, ByteCode.ByteUtil, ByteCode.ClassFile, ByteCode.ClassFile.Generator, ByteCode.Constants - -test-suite tests - type: exitcode-stdio-1.0 - main-is: TestSuite.hs - hs-source-dirs: src,Test - build-depends: base, - array, - HUnit, - utf8-string, - bytestring - build-tool-depends: alex:alex, happy:happy - other-modules: TestLexer, TestByteCodeGenerator +name: MiniJavaCompiler +version: 0.1.0.0 +build-type: Simple +cabal-version: >= 1.10 +Synopsis: A compiler for a minimal version of Java with watered down syntax. + +executable compiler + main-is: Main.hs + build-depends: base, + array, + HUnit, + utf8-string, + bytestring + default-language: Haskell2010 + hs-source-dirs: src, + src/ByteCode, + src/ByteCode/ClassFile + build-tool-depends: alex:alex, happy:happy + other-modules: Parser.Lexer, + Parser.JavaParser + Ast, + Example, + Typecheck, + ByteCode.ByteUtil, + ByteCode.ClassFile, + ByteCode.ClassFile.Generator, + ByteCode.Constants + +test-suite tests + type: exitcode-stdio-1.0 + main-is: TestSuite.hs + hs-source-dirs: src,Test + build-depends: base, + array, + HUnit, + utf8-string, + bytestring + build-tool-depends: alex:alex, happy:happy + other-modules: Parser.Lexer, + Parser.JavaParser, + Ast, + TestLexer, + TestParser, + TestByteCodeGenerator, + ByteCode.ByteUtil, + ByteCode.ClassFile, + ByteCode.ClassFile.Generator, + ByteCode.Constants diff --git a/src/Parser/JavaParser.y b/src/Parser/JavaParser.y index 7b0695c..bfe74b2 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 } @@ -14,10 +14,10 @@ import Parser.Lexer CASE { CASE } CHAR { CHAR } CLASS { CLASS} - IDENTIFIER { IDENTIFIER $$} - INTLITERAL { INTLITERAL $$} + IDENTIFIER { IDENTIFIER $$ } + 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 } @@ -76,138 +75,146 @@ import Parser.Lexer LESS { LESS } %% -compilationunit : typedeclarations { } +compilationunit : typedeclarations { $1 } -typedeclarations : typedeclaration { } - | typedeclarations typedeclaration { } +typedeclarations : typedeclaration { [$1] } + | typedeclarations typedeclaration { $1 ++ [$2] } name : qualifiedname { } - | simplename { } + | 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, 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 { } + | 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 { } + | PROTECTED { } | PRIVATE { } | STATIC { } | ABSTRACT { } 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 { } + | 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 { } 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 { } +type : primitivetype { $1 } + -- | referencetype { } -variabledeclarators : variabledeclarator { } - | variabledeclarators COMMA variabledeclarator { } +variabledeclarators : variabledeclarator { [$1] } + -- | variabledeclarators COMMA variabledeclarator { $1 ++ [$3] } 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 { } +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 { } +blockstatement : localvariabledeclarationstatement { } + | statement { } formalparameter : type variabledeclaratorid { } argumentlist : expression { } - | argumentlist COMMA expression { } + | argumentlist COMMA expression { } -numerictype : integraltype { } +numerictype : integraltype { $1 } -variabledeclaratorid : IDENTIFIER { } +variabledeclaratorid : IDENTIFIER { $1 } variableinitializer : expression { } localvariabledeclarationstatement : localvariabledeclaration SEMICOLON { } statement : statementwithouttrailingsubstatement{ } - | ifthenstatement { } - | ifthenelsestatement { } - | whilestatement { } - + | ifthenstatement { } + | ifthenelsestatement { } + | whilestatement { } + expression : assignmentexpression { } -integraltype : INT { } - | CHAR { } +integraltype : INT { "int" } + | CHAR { "char" } localvariabledeclaration : type variabledeclarators { } statementwithouttrailingsubstatement : block { } - | emptystatement { } - | expressionstatement { } - | returnstatement { } + | emptystatement { } + | expressionstatement { } + | returnstatement { } ifthenstatement : IF LBRACE expression RBRACE statement { } @@ -216,55 +223,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 +282,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,75 +293,85 @@ 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 { } { +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) } diff --git a/src/Parser/Lexer.x b/src/Parser/Lexer.x index 2cfa338..ef76773 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 Text.Read } %wrapper "basic" @@ -7,18 +8,221 @@ $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)*"*/" { \s -> Comment s } - "//".* {\s -> Comment s} - + "/*"(.|\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"|"ifn't") { \_ -> 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} + -- Literals + "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 } + -- 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 } + ">>>" { \_ -> UNSIGNEDSHIFTRIGHT } + ">>>=" { \_ -> UNSIGNEDSHIFTRIGHTEQUAL } { data Token - = Comment String - | Different + = 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 + | INTEGERLITERAL Int + | CHARLITERAL Char + | BOOLLITERAL Bool + | NULLLITERAL + | LBRACE + | RBRACE + | LBRACKET + | RBRACKET + | 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 + | UNSIGNEDSHIFTRIGHT + | UNSIGNEDSHIFTRIGHTEQUAL deriving(Eq,Show) } \ No newline at end of file