Compare commits

...

12 Commits

2 changed files with 124 additions and 62 deletions

View File

@ -18,11 +18,74 @@ testBooleanField = TestCase $
testIntField = TestCase $
assertEqual "expect class with int field" [Class "WithInt" [] [VariableDeclaration "int" "value" Nothing]] $
parse [CLASS,IDENTIFIER "WithInt",LBRACKET,INT,IDENTIFIER "value",SEMICOLON,RBRACKET]
testCustomTypeField = TestCase $
assertEqual "expect class with foo field" [Class "WithFoo" [] [VariableDeclaration "Foo" "value" Nothing]] $
parse [CLASS,IDENTIFIER "WithFoo",LBRACKET,IDENTIFIER "Foo",IDENTIFIER "value",SEMICOLON,RBRACKET]
testMultipleDeclarationSameLine = TestCase $
assertEqual "expect class with two int fields" [Class "TwoInts" [] [VariableDeclaration "int" "num1" Nothing, VariableDeclaration "int" "num2" Nothing]] $
parse [CLASS,IDENTIFIER "TwoInts",LBRACKET,INT,IDENTIFIER "num1",COMMA,IDENTIFIER "num2",SEMICOLON,RBRACKET]
testMultipleDeclarations = TestCase $
assertEqual "expect class with int and char field" [Class "Multiple" [] [VariableDeclaration "int" "value" Nothing, VariableDeclaration "char" "letter" Nothing]] $
parse [CLASS,IDENTIFIER "Multiple",LBRACKET,INT,IDENTIFIER "value",SEMICOLON,CHAR,IDENTIFIER "letter",SEMICOLON,RBRACKET]
testWithModifier = TestCase $
assertEqual "expect class with int field" [Class "WithInt" [] [VariableDeclaration "int" "value" Nothing]] $
parse [ABSTRACT,CLASS,IDENTIFIER "WithInt",LBRACKET,PUBLIC,INT,IDENTIFIER "value",SEMICOLON,RBRACKET]
testEmptyMethod = TestCase $
assertEqual "expect class with method" [Class "WithMethod" [MethodDeclaration "int" "foo" [] (Block [])] []] $
parse [CLASS,IDENTIFIER "WithMethod",LBRACKET,INT,IDENTIFIER "foo",LBRACE,RBRACE,SEMICOLON,RBRACKET]
testEmptyPrivateMethod = TestCase $
assertEqual "expect class with method" [Class "WithMethod" [MethodDeclaration "int" "foo" [] (Block [])] []] $
parse [CLASS,IDENTIFIER "WithMethod",LBRACKET,PRIVATE,INT,IDENTIFIER "foo",LBRACE,RBRACE,LBRACKET,RBRACKET,RBRACKET]
testEmptyVoidMethod = TestCase $
assertEqual "expect class with method" [Class "WithMethod" [MethodDeclaration "void" "foo" [] (Block [])] []] $
parse [CLASS,IDENTIFIER "WithMethod",LBRACKET,VOID,IDENTIFIER "foo",LBRACE,RBRACE,LBRACKET,RBRACKET,RBRACKET]
testEmptyMethodWithParam = TestCase $
assertEqual "expect class with method with param" [Class "WithParam" [MethodDeclaration "void" "foo" [ParameterDeclaration "int" "param"] (Block [])] []] $
parse [CLASS,IDENTIFIER "WithParam",LBRACKET,VOID,IDENTIFIER "foo",LBRACE,INT,IDENTIFIER "param",RBRACE,SEMICOLON,RBRACKET]
testEmptyMethodWithParams = TestCase $
assertEqual "expect class with multiple params" [Class "WithParams" [MethodDeclaration "void" "foo" [ParameterDeclaration "int" "p1",ParameterDeclaration "Custom" "p2"] (Block [])] []] $
parse [CLASS,IDENTIFIER "WithParams",LBRACKET,VOID,IDENTIFIER "foo",LBRACE,INT,IDENTIFIER "p1",COMMA,IDENTIFIER "Custom",IDENTIFIER "p2",RBRACE,SEMICOLON,RBRACKET]
testClassWithMethodAndField = TestCase $
assertEqual "expect class with method and field" [Class "WithMethodAndField" [MethodDeclaration "void" "foo" [] (Block []), MethodDeclaration "int" "bar" [] (Block [])] [VariableDeclaration "int" "value" Nothing]] $
parse [CLASS,IDENTIFIER "WithMethodAndField",LBRACKET,VOID,IDENTIFIER "foo",LBRACE,RBRACE,LBRACKET,RBRACKET,INT,IDENTIFIER "value",SEMICOLON,INT,IDENTIFIER "bar",LBRACE,RBRACE,SEMICOLON,RBRACKET]
testClassWithConstructor = TestCase $
assertEqual "expect class with constructor" [Class "WithConstructor" [MethodDeclaration "WithConstructor" "<init>" [] (Block [])] []] $
parse [CLASS,IDENTIFIER "WithConstructor",LBRACKET,IDENTIFIER "WithConstructor",LBRACE,RBRACE,LBRACKET,RBRACKET,RBRACKET]
testEmptyBlock = TestCase $ assertEqual "expect empty block" (Block []) $ parseBlock [LBRACKET,RBRACKET]
testBlockWithLocalVarDecl = TestCase $
assertEqual "expect block with local var delcaration" (Block [LocalVariableDeclaration $ VariableDeclaration "int" "localvar" Nothing]) $
parseBlock [LBRACKET,INT,IDENTIFIER "localvar",SEMICOLON,RBRACKET]
testBlockWithMultipleLocalVarDecls = TestCase $
assertEqual "expect block with multiple local var declarations" (Block [LocalVariableDeclaration $ VariableDeclaration "int" "var1" Nothing, LocalVariableDeclaration $ VariableDeclaration "boolean" "var2" Nothing]) $
parseBlock [LBRACKET,INT,IDENTIFIER "var1",SEMICOLON,BOOLEAN,IDENTIFIER "var2",SEMICOLON,RBRACKET]
testNestedBlocks = TestCase $
assertEqual "expect block with block inside" (Block [Block []]) $
parseBlock [LBRACKET,LBRACKET,RBRACKET,RBRACKET]
testBlockWithEmptyStatement = TestCase $
assertEqual "expect empty block" (Block []) $
parseBlock [LBRACKET,SEMICOLON,SEMICOLON,RBRACKET]
tests = TestList [
testSingleEmptyClass,
testTwoEmptyClasses,
testBooleanField,
testIntField
testIntField,
testCustomTypeField,
testMultipleDeclarations,
testWithModifier,
testEmptyMethod,
testEmptyPrivateMethod,
testEmptyVoidMethod,
testEmptyMethodWithParam,
testEmptyMethodWithParams,
testClassWithMethodAndField,
testClassWithConstructor,
testEmptyBlock,
testBlockWithLocalVarDecl,
testBlockWithMultipleLocalVarDecls,
testNestedBlocks,
testBlockWithEmptyStatement
]

View File

@ -1,12 +1,14 @@
{
module Parser.JavaParser (parse) where
module Parser.JavaParser (parse, parseBlock) where
import Ast
import Parser.Lexer
}
%name parse
%name parseBlock block
%tokentype { Token }
%error { parseError }
%errorhandlertype explist
%token
BOOLEAN { BOOLEAN }
@ -80,17 +82,17 @@ compilationunit : typedeclarations { $1 }
typedeclarations : typedeclaration { [$1] }
| typedeclarations typedeclaration { $1 ++ [$2] }
name : qualifiedname { }
| simplename { }
name : simplename { $1 }
-- | qualifiedname { }
typedeclaration : classdeclaration { $1 }
qualifiedname : name DOT IDENTIFIER { }
simplename : IDENTIFIER { }
simplename : IDENTIFIER { $1 }
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 }
| modifiers CLASS IDENTIFIER classbody { case $4 of (methods, fields) -> Class $3 methods fields }
classbody : LBRACKET RBRACKET { ([], []) }
| LBRACKET classbodydeclarations RBRACKET { $2 }
@ -103,11 +105,11 @@ classbodydeclarations : classbodydeclaration {
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]))
-- }
| classbodydeclarations classbodydeclaration {
case ($1, $2) of
((methods, fields), MethodDecl method) -> ((methods ++ [method]), fields)
((methods, fields), FieldDecls newFields) -> (methods, (fields ++ newFields))
}
modifier : PUBLIC { }
| PROTECTED { }
@ -118,51 +120,51 @@ modifier : PUBLIC { }
classtype : classorinterfacetype{ }
classbodydeclaration : classmemberdeclaration { $1 }
-- | constructordeclaration { FieldDecl $ VariableDeclaration "int" "a" Nothing } -- TODO
| constructordeclaration { $1 }
classorinterfacetype : name{ }
classorinterfacetype : name { $1 }
classmemberdeclaration : fielddeclaration { $1 }
-- | methoddeclaration { }
| methoddeclaration { $1 }
constructordeclaration : constructordeclarator constructorbody { }
| modifiers constructordeclarator constructorbody { }
constructordeclaration : constructordeclarator constructorbody { case $1 of (classname, parameters) -> MethodDecl $ MethodDeclaration classname "<init>" parameters $2 }
| modifiers constructordeclarator constructorbody { case $2 of (classname, parameters) -> MethodDecl $ MethodDeclaration classname "<init>" parameters $3 }
fielddeclaration : type variabledeclarators SEMICOLON { FieldDecls $ map (convertDeclarator $1) $2 }
-- | modifiers type variabledeclarators SEMICOLON {}
| modifiers type variabledeclarators SEMICOLON { FieldDecls $ map (convertDeclarator $2) $3 }
methoddeclaration : methodheader methodbody { }
methoddeclaration : methodheader methodbody { case $1 of (returnType, (name, parameters)) -> MethodDecl (MethodDeclaration returnType name parameters $2) }
block : LBRACKET RBRACKET { }
| LBRACKET blockstatements RBRACKET { }
block : LBRACKET RBRACKET { Block [] }
| LBRACKET blockstatements RBRACKET { Block $2 }
constructordeclarator : simplename LBRACE RBRACE { }
| simplename LBRACE formalparameterlist RBRACE { }
constructordeclarator : simplename LBRACE RBRACE { ($1, []) }
| simplename LBRACE formalparameterlist RBRACE { ($1, $3) }
constructorbody : LBRACKET RBRACKET { }
| LBRACKET explicitconstructorinvocation RBRACKET { }
| LBRACKET blockstatements RBRACKET { }
| LBRACKET explicitconstructorinvocation blockstatements RBRACKET { }
constructorbody : LBRACKET RBRACKET { Block [] }
-- | LBRACKET explicitconstructorinvocation RBRACKET { }
-- | LBRACKET blockstatements RBRACKET { }
-- | LBRACKET explicitconstructorinvocation blockstatements RBRACKET { }
methodheader : type methoddeclarator { }
| modifiers type methoddeclarator { }
| VOID methoddeclarator { }
| modifiers VOID methoddeclarator { }
methodheader : type methoddeclarator { ($1, $2) }
| modifiers type methoddeclarator { ($2, $3) }
| VOID methoddeclarator { ("void", $2) }
| modifiers VOID methoddeclarator { ("void", $3)}
type : primitivetype { $1 }
-- | referencetype { }
| referencetype { $1 }
variabledeclarators : variabledeclarator { [$1] }
-- | variabledeclarators COMMA variabledeclarator { $1 ++ [$3] }
| variabledeclarators COMMA variabledeclarator { $1 ++ [$3] }
methodbody : block { }
| SEMICOLON { }
methodbody : block { $1 }
| SEMICOLON { Block [] }
blockstatements : blockstatement { }
| blockstatements blockstatement { }
blockstatements : blockstatement { $1 }
| blockstatements blockstatement { $1 ++ $2}
formalparameterlist : formalparameter { }
| formalparameterlist COMMA formalparameter{ }
formalparameterlist : formalparameter { [$1] }
| formalparameterlist COMMA formalparameter { $1 ++ [$3] }
explicitconstructorinvocation : THIS LBRACE RBRACE SEMICOLON { }
| THIS LBRACE argumentlist RBRACE SEMICOLON { }
@ -170,22 +172,22 @@ explicitconstructorinvocation : THIS LBRACE RBRACE SEMICOLON { }
classtypelist : classtype { }
| classtypelist COMMA classtype { }
methoddeclarator : IDENTIFIER LBRACE RBRACE { }
| IDENTIFIER LBRACE formalparameterlist RBRACE { }
methoddeclarator : IDENTIFIER LBRACE RBRACE { ($1, []) }
| IDENTIFIER LBRACE formalparameterlist RBRACE { ($1, $3) }
primitivetype : BOOLEAN { "boolean" }
| numerictype { $1 }
referencetype : classorinterfacetype { }
referencetype : classorinterfacetype { $1 }
variabledeclarator : variabledeclaratorid { Declarator $1 Nothing }
-- | variabledeclaratorid ASSIGN variableinitializer { Declarator $1 Nothing } -- TODO
blockstatement : localvariabledeclarationstatement { }
| statement { }
blockstatement : localvariabledeclarationstatement { $1 }
| statement { $1 }
formalparameter : type variabledeclaratorid { }
formalparameter : type variabledeclaratorid { ParameterDeclaration $1 $2 }
argumentlist : expression { }
| argumentlist COMMA expression { }
@ -196,12 +198,12 @@ variabledeclaratorid : IDENTIFIER { $1 }
variableinitializer : expression { }
localvariabledeclarationstatement : localvariabledeclaration SEMICOLON { }
localvariabledeclarationstatement : localvariabledeclaration SEMICOLON { $1 }
statement : statementwithouttrailingsubstatement{ }
| ifthenstatement { }
| ifthenelsestatement { }
| whilestatement { }
statement : statementwithouttrailingsubstatement{ $1 }
-- | ifthenstatement { }
-- | ifthenelsestatement { }
-- | whilestatement { }
expression : assignmentexpression { }
@ -209,12 +211,12 @@ expression : assignmentexpression { }
integraltype : INT { "int" }
| CHAR { "char" }
localvariabledeclaration : type variabledeclarators { }
localvariabledeclaration : type variabledeclarators { map LocalVariableDeclaration $ map (convertDeclarator $1) $2 }
statementwithouttrailingsubstatement : block { }
| emptystatement { }
| expressionstatement { }
| returnstatement { }
statementwithouttrailingsubstatement : block { [$1] }
| emptystatement { [] }
-- | expressionstatement { }
-- | returnstatement { }
ifthenstatement : IF LBRACE expression RBRACE statement { }
@ -225,7 +227,7 @@ whilestatement : WHILE LBRACE expression RBRACE statement { }
assignmentexpression : conditionalexpression { }
| assignment{ }
emptystatement : SEMICOLON { }
emptystatement : SEMICOLON { Block [] }
expressionstatement : statementexpression SEMICOLON { }
@ -336,8 +338,8 @@ andexpression : equalityexpression { }
| andexpression AND equalityexpression { }
equalityexpression : relationalexpression { }
| equalityexpression EQUAL relationalexpression { }
| equalityexpression NOTEQUAL relationalexpression { }
-- | equalityexpression EQUAL relationalexpression { }
-- | equalityexpression NOTEQUAL relationalexpression { }
relationalexpression : shiftexpression { }
| relationalexpression LESS shiftexpression { }
@ -365,13 +367,10 @@ data MethodOrFieldDeclaration = MethodDecl MethodDeclaration
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 msg = error ("Parse error: " ++ show msg)
parseError :: ([Token], [String]) -> a
parseError (errortoken, expected) = error ("parse error on token: " ++ show errortoken ++ "\nexpected one of: " ++ show expected)
}