Compare commits

..

No commits in common. "af7162ea549e01554976dc950d1c5177d6e1fc01" and "b8e566a2a0d5ea4ab02cf71924f6d023e551add6" have entirely different histories.

7 changed files with 153 additions and 439 deletions

View File

@ -11,23 +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"
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 "&&"
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,
@ -36,14 +22,5 @@ tests = TestList [
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
TestLabel "TestIdentifierWithNumber" testIdentifierWithNumber
]

View File

@ -1,28 +0,0 @@
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
]

View File

@ -1,13 +1,11 @@
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 "TestParser" TestParser.tests
]
tests = TestList [TestLabel "TestLexer" TestLexer.tests, TestLabel "mathTest" otherTest]
main = do runTestTTAndExit Main.tests

View File

@ -12,7 +12,7 @@ executable compiler
default-language: Haskell2010
hs-source-dirs: src
build-tool-depends: alex:alex, happy:happy
other-modules: Parser.Lexer, Parser.JavaParser, Ast
other-modules: Parser.Lexer, Ast
test-suite tests
type: exitcode-stdio-1.0
@ -22,8 +22,4 @@ test-suite tests
array,
HUnit
build-tool-depends: alex:alex, happy:happy
other-modules: Parser.Lexer,
Parser.JavaParser,
Ast,
TestLexer
TestParser
other-modules: Parser.Lexer, TestLexer

View File

@ -5,13 +5,9 @@ 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
@ -20,13 +16,11 @@ 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
@ -44,11 +38,9 @@ data BinaryOperator = Addition
| And
| Or
| NameResolution
deriving(Show, Eq)
data UnaryOperator = Not
| Minus
deriving(Show, Eq)
data Expression = IntegerLiteral Int
| CharacterLiteral Char
@ -59,5 +51,4 @@ data Expression = IntegerLiteral Int
| UnaryOperation UnaryOperator Expression
| StatementExpressionExpression StatementExpression
| TypedExpression DataType Expression
deriving(Show, Eq)

View File

@ -1,6 +1,6 @@
{
module Parser.JavaParser (parse) where
import Ast
--import AbsSyn
import Parser.Lexer
}
@ -15,9 +15,9 @@ import Parser.Lexer
CHAR { CHAR }
CLASS { CLASS}
IDENTIFIER { IDENTIFIER $$}
INTLITERAL { INTEGERLITERAL $$}
INTLITERAL { INTLITERAL $$}
DOT { DOT }
MOD { MODULO }
MOD { MOD }
TIMESEQUAL { TIMESEQUAL }
GREATEREQUAL { GREATEREQUAL }
WHILE { WHILE }
@ -29,29 +29,30 @@ import Parser.Lexer
THIS { THIS }
STATIC { STATIC }
PROTECTED { PROTECTED }
TILDE { BITWISENOT }
MUL { TIMES }
TILDE { TILDE }
MUL { MUL }
MINUS { MINUS }
EXCLMARK { NOT }
EXCLMARK { EXCLMARK }
IF { IF }
ELSE { ELSE }
DIVIDEEQUAL { DIVEQUAL }
DIVIDEEQUAL { DIVIDEEQUAL }
NEW { NEW }
LBRACKET { LBRACKET }
JNULL { NULLLITERAL }
BOOLLITERAL { BOOLLITERAL $$ }
JNULL { JNULL }
BOOLLITERAL { BOOLLITERAL }
DIV { DIV }
LOGICALOR { OR }
LOGICALOR { LOGICALOR }
NOTEQUAL { NOTEQUAL }
INSTANCEOF { INSTANCEOF }
ANDEQUAL { ANDEQUAL }
ASSIGN { ASSIGN }
DECREMENT { DECREMENT }
CHARLITERAL { CHARLITERAL $$ }
STRINGLITERAL { STRINGLITERAL }
CHARLITERAL { CHARLITERAL }
AND { AND }
XOREQUAL { XOREQUAL }
RETURN { RETURN }
QUESMARK { QUESTIONMARK }
QUESMARK { QUESMARK }
SHIFTLEFTEQUAL { SHIFTLEFTEQUAL }
RBRACKET { RBRACKET }
COMMA { COMMA }
@ -67,7 +68,7 @@ import Parser.Lexer
INT { INT }
ABSTRACT { ABSTRACT }
SEMICOLON { SEMICOLON }
SIGNEDSHIFTRIGHTEQUAL { SHIFTRIGHTEQUAL }
SIGNEDSHIFTRIGHTEQUAL { SIGNEDSHIFTRIGHTEQUAL }
UNSIGNEDSHIFTRIGHTEQUAL { UNSIGNEDSHIFTRIGHTEQUAL }
PLUSEQUAL { PLUSEQUAL }
OREQUAL { OREQUAL }
@ -75,39 +76,31 @@ import Parser.Lexer
LESS { LESS }
%%
compilationunit : typedeclarations { $1 }
compilationunit : typedeclarations { }
typedeclarations : typedeclaration { [$1] }
| typedeclarations typedeclaration { $1 ++ [$2] }
typedeclarations : typedeclaration { }
| typedeclarations typedeclaration { }
name : qualifiedname { }
| simplename { }
typedeclaration : classdeclaration { $1 }
typedeclaration : classdeclaration { }
qualifiedname : name DOT IDENTIFIER { }
simplename : IDENTIFIER { }
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 }
classdeclaration : CLASS IDENTIFIER classbody { }
| modifiers CLASS IDENTIFIER classbody { }
classbody : LBRACKET RBRACKET { ([], []) }
| LBRACKET classbodydeclarations RBRACKET { $2 }
| LBRACKET classbodydeclarations RBRACKET { }
modifiers : modifier { }
| modifiers modifier { }
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]))
-- }
classbodydeclarations : classbodydeclaration { }
| classbodydeclarations classbodydeclaration{ }
modifier : PUBLIC { }
| PROTECTED { }
@ -117,19 +110,19 @@ modifier : PUBLIC { }
classtype : classorinterfacetype{ }
classbodydeclaration : classmemberdeclaration { $1 }
-- | constructordeclaration { FieldDecl $ VariableDeclaration "int" "a" Nothing } -- TODO
classbodydeclaration : classmemberdeclaration { }
| constructordeclaration { }
classorinterfacetype : name{ }
classmemberdeclaration : fielddeclaration { $1 }
-- | methoddeclaration { }
classmemberdeclaration : fielddeclaration { }
| methoddeclaration { }
constructordeclaration : constructordeclarator constructorbody { }
| modifiers constructordeclarator constructorbody { }
fielddeclaration : type variabledeclarators SEMICOLON { FieldDecls $ map (convertDeclarator $1) $2 }
-- | modifiers type variabledeclarators SEMICOLON {}
fielddeclaration : type variabledeclarators SEMICOLON { }
| modifiers type variabledeclarators SEMICOLON { }
methoddeclaration : methodheader methodbody { }
@ -149,11 +142,11 @@ methodheader : type methoddeclarator { }
| VOID methoddeclarator { }
| modifiers VOID methoddeclarator { }
type : primitivetype { $1 }
-- | referencetype { }
type : primitivetype { }
| referencetype { }
variabledeclarators : variabledeclarator { [$1] }
-- | variabledeclarators COMMA variabledeclarator { $1 ++ [$3] }
variabledeclarators : variabledeclarator { }
| variabledeclarators COMMA variabledeclarator { }
methodbody : block { }
| SEMICOLON { }
@ -173,14 +166,14 @@ classtypelist : classtype { }
methoddeclarator : IDENTIFIER LBRACE RBRACE { }
| IDENTIFIER LBRACE formalparameterlist RBRACE { }
primitivetype : BOOLEAN { "boolean" }
| numerictype { $1 }
primitivetype : BOOLEAN { }
| numerictype { }
referencetype : classorinterfacetype { }
variabledeclarator : variabledeclaratorid { Declarator $1 Nothing }
-- | variabledeclaratorid ASSIGN variableinitializer { Declarator $1 Nothing } -- TODO
variabledeclarator : variabledeclaratorid { }
| variabledeclaratorid ASSIGN variableinitializer { }
blockstatement : localvariabledeclarationstatement { }
| statement { }
@ -190,9 +183,9 @@ formalparameter : type variabledeclaratorid { }
argumentlist : expression { }
| argumentlist COMMA expression { }
numerictype : integraltype { $1 }
numerictype : integraltype { }
variabledeclaratorid : IDENTIFIER { $1 }
variabledeclaratorid : IDENTIFIER { }
variableinitializer : expression { }
@ -206,8 +199,8 @@ statement : statementwithouttrailingsubstatement{ }
expression : assignmentexpression { }
integraltype : INT { "int" }
| CHAR { "char" }
integraltype : INT { }
| CHAR { }
localvariabledeclaration : type variabledeclarators { }
@ -327,6 +320,7 @@ exclusiveorexpression : andexpression { }
literal : INTLITERAL { }
| BOOLLITERAL { }
| CHARLITERAL { }
| STRINGLITERAL { }
| JNULL { }
castexpression : LBRACE primitivetype RBRACE unaryexpression { }
@ -360,18 +354,7 @@ 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 msg = error ("Parse error: " ++ show msg)
parseError _ = error "Parse error"
}

View File

@ -1,6 +1,5 @@
{
module Parser.Lexer(Token(..), alexScanTokens) where
import Text.Read
}
%wrapper "basic"
@ -15,214 +14,12 @@ 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"|"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 }
$JavaLetter$JavaLetterOrDigit* { \s -> Identifier s }
{
data Token
= 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
= Identifier String
deriving(Eq,Show)
}