Compare commits
2 commits
49e06c175f
...
33d28566ad
Author | SHA1 | Date | |
---|---|---|---|
33d28566ad | |||
e82ec1ce09 |
12 changed files with 427 additions and 73 deletions
|
@ -22,9 +22,15 @@ library
|
||||||
ClassTypeParameter
|
ClassTypeParameter
|
||||||
JavaClass
|
JavaClass
|
||||||
JavaClassAccess
|
JavaClassAccess
|
||||||
|
JavaClassField
|
||||||
|
JavaClassFieldVisibility
|
||||||
JavaClassModifier
|
JavaClassModifier
|
||||||
|
JavaExpression
|
||||||
JavaFile
|
JavaFile
|
||||||
|
JavaLanguage
|
||||||
|
JavaVariableInitializer
|
||||||
Lib
|
Lib
|
||||||
|
LiteralExpression
|
||||||
PrimitiveTypes
|
PrimitiveTypes
|
||||||
Syntax
|
Syntax
|
||||||
other-modules:
|
other-modules:
|
||||||
|
|
8
src/Annotation.hs
Normal file
8
src/Annotation.hs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
module Annotation (Annotation(..) )
|
||||||
|
where
|
||||||
|
|
||||||
|
import JavaExpression (JavaExpression)
|
||||||
|
|
||||||
|
import Data.Map (Map)
|
||||||
|
|
||||||
|
data Annotation = Normal String (Map String JavaExpression)
|
31
src/ClassLiteral.hs
Normal file
31
src/ClassLiteral.hs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
module ClassLiteral (ClassLiteral(..), parseClassLiteral ) where
|
||||||
|
|
||||||
|
import qualified Data.List as List
|
||||||
|
import Numeric.Natural (Natural)
|
||||||
|
|
||||||
|
import PrimitiveTypes (PrimitiveType, primitiveType)
|
||||||
|
import JavaLanguage (m_reserved, m_lexeme, m_identifier)
|
||||||
|
|
||||||
|
import Text.Parsec (choice, string', many, sepBy, char, manyTill, lookAhead)
|
||||||
|
import Text.Parsec.String (Parser)
|
||||||
|
|
||||||
|
data ClassLiteral = Void
|
||||||
|
| Primitive PrimitiveType Natural -- type, array dimension
|
||||||
|
| Type String Natural -- type, array dimension
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
parseClassLiteral :: Parser ClassLiteral
|
||||||
|
parseClassLiteral = choice
|
||||||
|
[ m_reserved "void" *> return Void
|
||||||
|
, primitiveType >>= parseArrayDims . Primitive
|
||||||
|
, typeName >>= parseArrayDims . Type
|
||||||
|
] <* string' ".class"
|
||||||
|
|
||||||
|
typeName :: Parser String
|
||||||
|
typeName = do
|
||||||
|
start <- m_identifier
|
||||||
|
paths <- manyTill (char '.' *> m_identifier) (choice [ lookAhead $ string' ".class" , lookAhead $ string' "[]" ])
|
||||||
|
return . List.intercalate "." $ (start:paths)
|
||||||
|
|
||||||
|
parseArrayDims :: (Natural -> ClassLiteral) -> Parser ClassLiteral
|
||||||
|
parseArrayDims f = m_lexeme $ many (string' "[]") >>= return . f . fromInteger . toInteger . List.length
|
|
@ -14,5 +14,7 @@ data JavaClass = JavaClass { name :: String
|
||||||
, isAbstract :: Bool
|
, isAbstract :: Bool
|
||||||
, typeParameters :: [ClassTypeParameter]
|
, typeParameters :: [ClassTypeParameter]
|
||||||
, extends :: Maybe ClassType
|
, extends :: Maybe ClassType
|
||||||
|
, implements :: [ClassType]
|
||||||
|
, permits :: [String]
|
||||||
}
|
}
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
28
src/JavaClassField.hs
Normal file
28
src/JavaClassField.hs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
module JavaClassField (module JavaClassField) where
|
||||||
|
|
||||||
|
import JavaClassFieldVisibility (JavaClassFieldVisibility)
|
||||||
|
import PrimitiveTypes (PrimitiveType)
|
||||||
|
import ClassTypeParameter (ClassType, ArrayType)
|
||||||
|
import JavaVariableInitializer (JavaVariableInitializer)
|
||||||
|
|
||||||
|
import Data.Set (Set)
|
||||||
|
|
||||||
|
data JavaClassField = JavaClassField { name :: String
|
||||||
|
, visiblity :: JavaClassFieldVisibility
|
||||||
|
, modifiers :: Set JavaClassFieldModifier
|
||||||
|
, type_ :: JavaClassFieldType
|
||||||
|
, initializer :: Maybe JavaVariableInitializer
|
||||||
|
}
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
data JavaClassFieldModifier = Static
|
||||||
|
| Final
|
||||||
|
| Transient
|
||||||
|
| Volatile
|
||||||
|
deriving (Show, Ord, Eq)
|
||||||
|
|
||||||
|
data JavaClassFieldType = PrimitiveFieldType PrimitiveType
|
||||||
|
| ClassFieldType ClassType
|
||||||
|
| VariableFieldType String
|
||||||
|
| ArrayFieldType ArrayType
|
||||||
|
deriving Show
|
4
src/JavaClassFieldVisibility.hs
Normal file
4
src/JavaClassFieldVisibility.hs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
module JavaClassFieldVisibility (JavaClassFieldVisibility(..) ) where
|
||||||
|
|
||||||
|
data JavaClassFieldVisibility = Public | Protected | Private | Package
|
||||||
|
deriving Show
|
65
src/JavaLanguage.hs
Normal file
65
src/JavaLanguage.hs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
module JavaLanguage
|
||||||
|
( javaLanguageDef
|
||||||
|
, m_paren
|
||||||
|
, m_identifier
|
||||||
|
, m_reserved
|
||||||
|
, m_lexeme
|
||||||
|
, m_symbol
|
||||||
|
, m_commaSep1
|
||||||
|
, m_commaSep
|
||||||
|
, m_angles
|
||||||
|
, m_braces
|
||||||
|
, m_reservedOp
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Text.Parsec
|
||||||
|
import Text.Parsec.Language
|
||||||
|
import Text.Parsec.Token
|
||||||
|
|
||||||
|
import Data.Functor.Identity
|
||||||
|
|
||||||
|
javaLanguageDef :: GenLanguageDef String u Identity
|
||||||
|
javaLanguageDef = emptyDef{ commentStart = "/*"
|
||||||
|
, commentEnd = "*/"
|
||||||
|
, commentLine = "//"
|
||||||
|
, nestedComments = False
|
||||||
|
, identStart = letter <|> char '_'
|
||||||
|
, identLetter = alphaNum <|> char '_'
|
||||||
|
, opStart = oneOf ".+-*/;"
|
||||||
|
, opLetter = oneOf ".+-*/;"
|
||||||
|
, reservedOpNames = [";"]
|
||||||
|
, reservedNames = [ "true"
|
||||||
|
, "false"
|
||||||
|
, "package"
|
||||||
|
, "class"
|
||||||
|
, "interface"
|
||||||
|
, "void"
|
||||||
|
, "boolean"
|
||||||
|
, "char"
|
||||||
|
, "short"
|
||||||
|
, "int"
|
||||||
|
, "float"
|
||||||
|
, "long"
|
||||||
|
, "double"
|
||||||
|
, "instanceof"
|
||||||
|
, "public"
|
||||||
|
, "private"
|
||||||
|
, "protected"
|
||||||
|
, "static"
|
||||||
|
, "final"
|
||||||
|
, "volatile"
|
||||||
|
, "transient"
|
||||||
|
]
|
||||||
|
, caseSensitive = True
|
||||||
|
}
|
||||||
|
|
||||||
|
TokenParser{ parens = m_paren
|
||||||
|
, identifier = m_identifier
|
||||||
|
, reserved = m_reserved
|
||||||
|
, lexeme = m_lexeme
|
||||||
|
, symbol = m_symbol
|
||||||
|
, commaSep1 = m_commaSep1
|
||||||
|
, commaSep = m_commaSep
|
||||||
|
, angles = m_angles
|
||||||
|
, braces = m_braces
|
||||||
|
, reservedOp = m_reservedOp } = makeTokenParser javaLanguageDef
|
7
src/JavaVariableInitializer.hs
Normal file
7
src/JavaVariableInitializer.hs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
module JavaVariableInitializer (JavaVariableInitializer(..) ) where
|
||||||
|
|
||||||
|
import JavaExpression (JavaExpression)
|
||||||
|
|
||||||
|
data JavaVariableInitializer = ArrayVariableInitializer [JavaVariableInitializer]
|
||||||
|
| ExpressionVariableInitializer JavaExpression
|
||||||
|
deriving Show
|
140
src/LiteralExpression.hs
Normal file
140
src/LiteralExpression.hs
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
module LiteralExpression (LiteralExpression(..))
|
||||||
|
where
|
||||||
|
|
||||||
|
import Data.Ratio ((%))
|
||||||
|
import Data.Int (Int16)
|
||||||
|
import qualified Data.Char as Char
|
||||||
|
|
||||||
|
import JavaLanguage (m_lexeme, m_reserved)
|
||||||
|
|
||||||
|
import Text.Parsec (many1, digit, oneOf, option, char, choice, many, try, satisfy, manyTill, string', endOfLine, space)
|
||||||
|
import Text.Parsec.String (Parser)
|
||||||
|
|
||||||
|
data LiteralExpression = NullLiteral
|
||||||
|
| IntegerLiteral Integer IntegerLiteralType
|
||||||
|
| FloatingLiteral Rational DecimalLiteralType
|
||||||
|
| BooleanLiteral Bool
|
||||||
|
| CharacterLiteral Char
|
||||||
|
| StringLiteral String
|
||||||
|
| TextLiteral String
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
data IntegerLiteralType = IntLiteral | LongLiteral
|
||||||
|
deriving Show
|
||||||
|
data DecimalLiteralType = DoubleLiteral | FloatLiteral
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
signedInteger :: Parser Integer
|
||||||
|
signedInteger = do
|
||||||
|
signFactor <- option 1 (char '-' *> return (-1))
|
||||||
|
digits <- many1 digit
|
||||||
|
return (signFactor * read digits)
|
||||||
|
|
||||||
|
parseNullLiteral :: Parser LiteralExpression
|
||||||
|
parseNullLiteral = m_reserved "null" *> return NullLiteral
|
||||||
|
|
||||||
|
-- TODO: Hex, Oct, Bin
|
||||||
|
parseDecimalIntegerLiteral :: Parser LiteralExpression
|
||||||
|
parseDecimalIntegerLiteral = m_lexeme $ do
|
||||||
|
negative <- option False (char '-' *> return True)
|
||||||
|
digitString <- many1 digit
|
||||||
|
literalType <- option IntLiteral (oneOf "Ll" *> return LongLiteral)
|
||||||
|
let positiveNumber = read digitString :: Integer
|
||||||
|
let number = (if (negative) then negate else id) positiveNumber
|
||||||
|
return (IntegerLiteral number literalType)
|
||||||
|
|
||||||
|
-- TODO: Hex
|
||||||
|
parseDecimalFloatingLiteral :: Parser LiteralExpression
|
||||||
|
parseDecimalFloatingLiteral = do
|
||||||
|
prefix <- option "0" $ many1 digit
|
||||||
|
_ <- option '.' (char '.')
|
||||||
|
suffix <- many digit
|
||||||
|
exponent <- option 0 (char 'e' *> signedInteger)
|
||||||
|
literalType <- option FloatLiteral $ choice [
|
||||||
|
oneOf "fF" *> return FloatLiteral
|
||||||
|
, oneOf "dD" *> return DoubleLiteral
|
||||||
|
]
|
||||||
|
let suffixLength = length suffix
|
||||||
|
let prefixPower = 10 ^ suffixLength :: Integer
|
||||||
|
let iprefix = read prefix :: Integer
|
||||||
|
let isuffix = if (suffixLength == 0) then 0 else read suffix :: Integer
|
||||||
|
let exponentPower = (if exponent > 0 then 10 ^ exponent else 1) % (if exponent < 0 then 10^(-exponent) else 1)
|
||||||
|
let rational = ((iprefix * prefixPower + isuffix) % prefixPower) * exponentPower
|
||||||
|
return (FloatingLiteral rational literalType)
|
||||||
|
|
||||||
|
|
||||||
|
parseBooleanLiteral :: Parser LiteralExpression
|
||||||
|
parseBooleanLiteral = choice
|
||||||
|
[ m_reserved "true" *> return (BooleanLiteral True)
|
||||||
|
, m_reserved "false" *> return (BooleanLiteral False)
|
||||||
|
]
|
||||||
|
|
||||||
|
parseCharLiteral :: Parser LiteralExpression
|
||||||
|
parseCharLiteral = (char '\'' *> choice [
|
||||||
|
parseEscapedChar
|
||||||
|
, satisfy (not . flip elem "'\\")
|
||||||
|
] <* char '\'') >>= return . CharacterLiteral
|
||||||
|
|
||||||
|
-- TODO: Support double line terminator
|
||||||
|
parseEscapedChar :: Parser Char
|
||||||
|
parseEscapedChar = char '\\' *> choice [
|
||||||
|
char 'b' *> return '\b'
|
||||||
|
, char 's' *> return ' '
|
||||||
|
, char 't' *> return '\t'
|
||||||
|
, char 'n' *> return '\n'
|
||||||
|
, char 'f' *> return '\f'
|
||||||
|
, char 'r' *> return '\r'
|
||||||
|
, char '"' *> return '"'
|
||||||
|
, char '\'' *> return '\''
|
||||||
|
, char '\\' *> return '\\'
|
||||||
|
, parseOctalEscapedChar
|
||||||
|
]
|
||||||
|
|
||||||
|
parseOctalEscapedChar :: Parser Char
|
||||||
|
parseOctalEscapedChar = choice [
|
||||||
|
try $ tripleOctalEscapedChar
|
||||||
|
, try $ doubleOctalEscapedChar
|
||||||
|
, singleOctalEscapedChar
|
||||||
|
]
|
||||||
|
|
||||||
|
singleOctalEscapedChar :: Parser Char
|
||||||
|
singleOctalEscapedChar = do
|
||||||
|
char1 <- oneOf "01234567"
|
||||||
|
let num1 = read [char1] :: Int
|
||||||
|
return . Char.chr $ num1
|
||||||
|
|
||||||
|
doubleOctalEscapedChar :: Parser Char
|
||||||
|
doubleOctalEscapedChar = do
|
||||||
|
char1 <- oneOf "01234567"
|
||||||
|
char2 <- oneOf "01234567"
|
||||||
|
let num1 = read [char1] :: Int
|
||||||
|
let num2 = read [char2] :: Int
|
||||||
|
let num = num2 + num1 * 8
|
||||||
|
return . Char.chr $ num
|
||||||
|
|
||||||
|
tripleOctalEscapedChar :: Parser Char
|
||||||
|
tripleOctalEscapedChar = do
|
||||||
|
char1 <- oneOf "0123"
|
||||||
|
char2 <- oneOf "01234567"
|
||||||
|
char3 <- oneOf "01234567"
|
||||||
|
let num1 = read [char1] :: Int
|
||||||
|
let num2 = read [char2] :: Int
|
||||||
|
let num3 = read [char3] :: Int
|
||||||
|
let num = num3 + num2 * 8 + num1 * 64
|
||||||
|
return . Char.chr $ num
|
||||||
|
|
||||||
|
parseStringLiteral :: Parser LiteralExpression
|
||||||
|
parseStringLiteral = do
|
||||||
|
_ <- char '"'
|
||||||
|
content <- manyTill (choice
|
||||||
|
[ parseEscapedChar
|
||||||
|
, satisfy (not . flip elem "\r\n\"\\")
|
||||||
|
]) (char '"')
|
||||||
|
return (StringLiteral content)
|
||||||
|
|
||||||
|
parseTextLiteral :: Parser LiteralExpression
|
||||||
|
parseTextLiteral = do
|
||||||
|
_ <- string' "\"\"\""
|
||||||
|
_ <- space `manyTill` endOfLine
|
||||||
|
content <- (choice [ parseEscapedChar , satisfy (not . flip elem "\\") ] ) `manyTill` (string' "\"\"\"")
|
||||||
|
return . TextLiteral $ content
|
26
src/PrimaryExpression.hs
Normal file
26
src/PrimaryExpression.hs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
module PrimaryExpression (PrimaryExpression(..) ) where
|
||||||
|
|
||||||
|
import qualified Data.List as List
|
||||||
|
|
||||||
|
import ClassLiteral (ClassLiteral)
|
||||||
|
import JavaLanguage (m_identifier)
|
||||||
|
import LiteralExpression (LiteralExpression)
|
||||||
|
|
||||||
|
import Text.Parsec (manyTill, char, string')
|
||||||
|
import Text.Parsec.String (Parser)
|
||||||
|
|
||||||
|
data PrimaryExpression = Literal LiteralExpression
|
||||||
|
| ClassLiteral ClassLiteral
|
||||||
|
| This
|
||||||
|
| TypedThis String
|
||||||
|
| InstanceCreation
|
||||||
|
deriving Show
|
||||||
|
|
||||||
|
parseThis :: Parser PrimaryExpression
|
||||||
|
parseThis = string' "this" *> return This
|
||||||
|
|
||||||
|
parseTypedThis :: Parser PrimaryExpression
|
||||||
|
parseTypedThis = do
|
||||||
|
start <- m_identifier
|
||||||
|
paths <- manyTill (char '.' *> m_identifier) (string' ".this")
|
||||||
|
return . TypedThis . List.intercalate "." $ (start:paths)
|
|
@ -1,7 +1,25 @@
|
||||||
module PrimitiveTypes (
|
module PrimitiveTypes
|
||||||
module PrimitiveTypes
|
( PrimitiveType(..)
|
||||||
, PrimitiveType
|
, primitiveType
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import JavaLanguage (m_reserved)
|
||||||
|
|
||||||
|
import Text.Parsec (choice)
|
||||||
|
import Text.Parsec.String (Parser)
|
||||||
|
|
||||||
data PrimitiveType = PrimitiveBoolean | PrimitiveByte | PrimitiveShort | PrimitiveInt | PrimitiveLong | PrimitiveChar | PrimitiveFloat | PrimitiveDouble
|
data PrimitiveType = PrimitiveBoolean | PrimitiveByte | PrimitiveShort | PrimitiveInt | PrimitiveLong | PrimitiveChar | PrimitiveFloat | PrimitiveDouble
|
||||||
deriving Show
|
deriving Show
|
||||||
|
|
||||||
|
primitiveType :: Parser PrimitiveType
|
||||||
|
primitiveType = choice [
|
||||||
|
m_reserved "boolean" *> return PrimitiveTypes.PrimitiveBoolean
|
||||||
|
, m_reserved "byte" *> return PrimitiveTypes.PrimitiveByte
|
||||||
|
, m_reserved "char" *> return PrimitiveTypes.PrimitiveChar
|
||||||
|
, m_reserved "short" *> return PrimitiveTypes.PrimitiveShort
|
||||||
|
, m_reserved "int" *> return PrimitiveTypes.PrimitiveInt
|
||||||
|
, m_reserved "float" *> return PrimitiveTypes.PrimitiveFloat
|
||||||
|
, m_reserved "long" *> return PrimitiveTypes.PrimitiveLong
|
||||||
|
, m_reserved "double" *> return PrimitiveTypes.PrimitiveDouble
|
||||||
|
]
|
||||||
|
|
||||||
|
|
159
src/Syntax.hs
159
src/Syntax.hs
|
@ -13,58 +13,17 @@ import qualified JavaClassAccess as JavaClassAccess
|
||||||
import qualified JavaClassModifier as JavaClassModifier
|
import qualified JavaClassModifier as JavaClassModifier
|
||||||
import qualified JavaFile as JavaFile
|
import qualified JavaFile as JavaFile
|
||||||
import qualified ClassTypeParameter as ClassTypeParameter
|
import qualified ClassTypeParameter as ClassTypeParameter
|
||||||
|
import qualified JavaClassFieldVisibility as JavaClassFieldVisibility
|
||||||
|
import qualified JavaClassField as JavaClassField
|
||||||
import PrimitiveTypes
|
import PrimitiveTypes
|
||||||
|
import JavaLanguage
|
||||||
|
|
||||||
import Data.Functor.Identity
|
|
||||||
import qualified Data.List as List
|
import qualified Data.List as List
|
||||||
import qualified Data.Maybe as Maybe
|
import qualified Data.Maybe as Maybe
|
||||||
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
import Numeric.Natural
|
import Numeric.Natural
|
||||||
|
|
||||||
javaLanguageDef :: GenLanguageDef String u Identity
|
|
||||||
javaLanguageDef = emptyDef{ commentStart = "/*"
|
|
||||||
, commentEnd = "*/"
|
|
||||||
, commentLine = "//"
|
|
||||||
, nestedComments = False
|
|
||||||
, identStart = letter <|> char '_'
|
|
||||||
, identLetter = alphaNum <|> char '_'
|
|
||||||
, opStart = oneOf ".+-*/;"
|
|
||||||
, opLetter = oneOf ".+-*/;"
|
|
||||||
, reservedOpNames = [";"]
|
|
||||||
, reservedNames = [ "true"
|
|
||||||
, "false"
|
|
||||||
, "package"
|
|
||||||
, "class"
|
|
||||||
, "interface"
|
|
||||||
, "void"
|
|
||||||
, "boolean"
|
|
||||||
, "char"
|
|
||||||
, "short"
|
|
||||||
, "int"
|
|
||||||
, "float"
|
|
||||||
, "long"
|
|
||||||
, "double"
|
|
||||||
, "instanceof"
|
|
||||||
, "public"
|
|
||||||
, "private"
|
|
||||||
, "protected"
|
|
||||||
, "static"
|
|
||||||
, "final"
|
|
||||||
, "volatile"
|
|
||||||
, "transient"
|
|
||||||
]
|
|
||||||
, caseSensitive = True
|
|
||||||
}
|
|
||||||
|
|
||||||
TokenParser{ parens = m_paren
|
|
||||||
, identifier = m_identifier
|
|
||||||
, reserved = m_reserved
|
|
||||||
, lexeme = m_lexeme
|
|
||||||
, symbol = m_symbol
|
|
||||||
, commaSep1 = m_commaSep1
|
|
||||||
, angles = m_angles
|
|
||||||
, reservedOp = m_reservedOp } = makeTokenParser javaLanguageDef
|
|
||||||
|
|
||||||
javaPathParser = m_identifier `sepBy1` (string ".")
|
javaPathParser = m_identifier `sepBy1` (string ".")
|
||||||
|
|
||||||
semicolon = (m_lexeme . char $ ';') <?> "semicolon"
|
semicolon = (m_lexeme . char $ ';') <?> "semicolon"
|
||||||
|
@ -128,20 +87,9 @@ arrayType = do
|
||||||
, classType >>= return . ClassTypeParameter.ClassArrayType
|
, classType >>= return . ClassTypeParameter.ClassArrayType
|
||||||
, typeIdentifier >>= return . ClassTypeParameter.VariableArrayType
|
, typeIdentifier >>= return . ClassTypeParameter.VariableArrayType
|
||||||
]
|
]
|
||||||
arrayDepth <- (many1 $ string "[]") >>= return . List.length
|
arrayDepth <- m_lexeme $ (many1 $ string "[]") >>= return . List.length
|
||||||
return (partialConstructor (fromInteger . toInteger $ arrayDepth))
|
return (partialConstructor (fromInteger . toInteger $ arrayDepth))
|
||||||
|
|
||||||
primitiveType = choice [
|
|
||||||
m_reserved "boolean" *> return PrimitiveTypes.PrimitiveBoolean
|
|
||||||
, m_reserved "byte" *> return PrimitiveTypes.PrimitiveByte
|
|
||||||
, m_reserved "char" *> return PrimitiveTypes.PrimitiveChar
|
|
||||||
, m_reserved "short" *> return PrimitiveTypes.PrimitiveShort
|
|
||||||
, m_reserved "int" *> return PrimitiveTypes.PrimitiveInt
|
|
||||||
, m_reserved "float" *> return PrimitiveTypes.PrimitiveFloat
|
|
||||||
, m_reserved "long" *> return PrimitiveTypes.PrimitiveLong
|
|
||||||
, m_reserved "double" *> return PrimitiveTypes.PrimitiveDouble
|
|
||||||
]
|
|
||||||
|
|
||||||
qualifiedClassType = do
|
qualifiedClassType = do
|
||||||
qualifiedType <- typeIdentifier `sepBy1` (string' ".") >>= return . List.intercalate "."
|
qualifiedType <- typeIdentifier `sepBy1` (string' ".") >>= return . List.intercalate "."
|
||||||
maybeTypeArguments <- optionMaybe $ m_angles (m_commaSep1 typeArgument)
|
maybeTypeArguments <- optionMaybe $ m_angles (m_commaSep1 typeArgument)
|
||||||
|
@ -154,12 +102,13 @@ unqualifiedClassType = do
|
||||||
let typeArguments = Maybe.fromMaybe [] maybeTypeArguments
|
let typeArguments = Maybe.fromMaybe [] maybeTypeArguments
|
||||||
return (ClassTypeParameter.NonRecursiveTypeBound unqualifiedType typeArguments)
|
return (ClassTypeParameter.NonRecursiveTypeBound unqualifiedType typeArguments)
|
||||||
|
|
||||||
|
-- TODO: Review this, i cancelled the left-recursive rule
|
||||||
recursiveClassType = do
|
recursiveClassType = do
|
||||||
classType_ <- classType
|
|
||||||
_ <- char '.'
|
|
||||||
unqualifiedType <- typeIdentifier
|
unqualifiedType <- typeIdentifier
|
||||||
maybeTypeArguments <- optionMaybe $ m_angles (m_commaSep1 typeArgument)
|
maybeTypeArguments <- optionMaybe $ m_angles (m_commaSep1 typeArgument)
|
||||||
let typeArguments = Maybe.fromMaybe [] maybeTypeArguments
|
let typeArguments = Maybe.fromMaybe [] maybeTypeArguments
|
||||||
|
_ <- char '.'
|
||||||
|
classType_ <- classType
|
||||||
return (ClassTypeParameter.RecursiveTypeBound classType_ unqualifiedType typeArguments)
|
return (ClassTypeParameter.RecursiveTypeBound classType_ unqualifiedType typeArguments)
|
||||||
|
|
||||||
classType = choice [ qualifiedClassType
|
classType = choice [ qualifiedClassType
|
||||||
|
@ -169,13 +118,14 @@ classType = choice [ qualifiedClassType
|
||||||
|
|
||||||
classTypeParameterClassOrInterfaceBound = do
|
classTypeParameterClassOrInterfaceBound = do
|
||||||
classType_ <- classType
|
classType_ <- classType
|
||||||
interfaces <- m_commaSep1 interfaceType
|
interfaces <- m_commaSep interfaceType
|
||||||
return (ClassTypeParameter.ClassTypeBound classType_ interfaces)
|
return (ClassTypeParameter.ClassTypeBound classType_ interfaces)
|
||||||
|
|
||||||
classTypeParameterBound = do
|
classTypeParameterBound = do
|
||||||
_ <- m_reserved' "extends"
|
_ <- m_reserved' "extends"
|
||||||
bound <- choice [ typeIdentifier >>= return . ClassTypeParameter.SimpleTypeBound
|
bound <- choice [
|
||||||
, classTypeParameterClassOrInterfaceBound
|
try classTypeParameterClassOrInterfaceBound
|
||||||
|
, typeIdentifier >>= return . ClassTypeParameter.SimpleTypeBound
|
||||||
]
|
]
|
||||||
return bound
|
return bound
|
||||||
|
|
||||||
|
@ -185,17 +135,86 @@ classTypeParameter = do
|
||||||
-- TODO: Interfaces
|
-- TODO: Interfaces
|
||||||
return (ClassTypeParameter.ClassTypeParameter name typeBound [])
|
return (ClassTypeParameter.ClassTypeParameter name typeBound [])
|
||||||
|
|
||||||
classTypeParameters = optionMaybe $ m_angles $ (classTypeParameter `sepBy1` (m_symbol ","))
|
classTypeParameters = optionMaybe $ m_angles $ ((classTypeParameter <?> "class type parameter") `sepBy1` (m_symbol ","))
|
||||||
|
|
||||||
fileLevelClass= do
|
classPermits = do
|
||||||
accessModifier <- fileLevelClassAccess
|
_ <- m_reserved "permits"
|
||||||
_ <- m_reserved' "class"
|
m_commaSep typeName
|
||||||
className <- m_identifier <?> "class name"
|
|
||||||
let isStatic = False
|
typeName = choice [
|
||||||
maybeModifier <- fileLevelClassModifier
|
qualifiedTypeIdentifier
|
||||||
|
, typeIdentifier
|
||||||
|
]
|
||||||
|
|
||||||
|
qualifiedTypeIdentifier = do
|
||||||
|
packagePath <- many (try $ m_identifier <* char '.')
|
||||||
|
typeName_ <- typeIdentifier
|
||||||
|
return . List.intercalate "." $ packagePath ++ [typeName_]
|
||||||
|
|
||||||
|
--classBody = many $ choice [
|
||||||
|
-- classMemberDeclaration
|
||||||
|
-- , classInstanceInitializer
|
||||||
|
-- , classStaticInitializer
|
||||||
|
-- , classConstructorDeclaration
|
||||||
|
-- ]
|
||||||
|
--
|
||||||
|
--classMemberDeclaration = choice [
|
||||||
|
-- classFieldDeclaration
|
||||||
|
-- , classMethodDeclaration
|
||||||
|
-- , classClassDeclaration
|
||||||
|
-- , classInterfaceDeclaration
|
||||||
|
-- ]
|
||||||
|
--
|
||||||
|
|
||||||
|
-- TODO: Support multiple declarations
|
||||||
|
classFieldDeclaration = do
|
||||||
|
visibility <- optionMaybe classFieldVisibility >>= return . Maybe.fromMaybe JavaClassFieldVisibility.Package
|
||||||
|
modifiers <- many $ classFieldModifier
|
||||||
|
fieldType <- classFieldType
|
||||||
|
let modifierSet = Set.fromList modifiers
|
||||||
|
-- TODO: throw errors for duplicates
|
||||||
|
-- TODO: Support declarator lists
|
||||||
|
fieldName <- m_identifier
|
||||||
|
-- maybeInitializer <- optionMaybe $ m_reservedOp "=" *> variableInitializer
|
||||||
|
return $ JavaClassField.JavaClassField fieldName visibility modifierSet fieldType
|
||||||
|
|
||||||
|
--variableInitializer = choice
|
||||||
|
-- [
|
||||||
|
|
||||||
|
classFieldType = choice
|
||||||
|
[ arrayType >>= return . JavaClassField.ArrayFieldType
|
||||||
|
, primitiveType >>= return . JavaClassField.PrimitiveFieldType
|
||||||
|
, classType >>= return . JavaClassField.ClassFieldType
|
||||||
|
, typeIdentifier >>= return . JavaClassField.VariableFieldType
|
||||||
|
]
|
||||||
|
|
||||||
|
classFieldModifier = choice [
|
||||||
|
m_reserved "final" *> return JavaClassField.Final
|
||||||
|
, m_reserved "static" *> return JavaClassField.Static
|
||||||
|
, m_reserved "volatile" *> return JavaClassField.Volatile
|
||||||
|
, m_reserved "transient" *> return JavaClassField.Transient
|
||||||
|
]
|
||||||
|
|
||||||
|
classFieldVisibility = choice [
|
||||||
|
m_reserved "public" *> return JavaClassFieldVisibility.Public
|
||||||
|
, m_reserved "private" *> return JavaClassFieldVisibility.Private
|
||||||
|
, m_reserved "protected" *> return JavaClassFieldVisibility.Protected
|
||||||
|
]
|
||||||
|
|
||||||
|
fileLevelClass = do
|
||||||
|
accessModifier <- fileLevelClassAccess
|
||||||
|
_ <- m_reserved' "class"
|
||||||
|
className <- m_identifier <?> "class name"
|
||||||
|
maybeModifier <- fileLevelClassModifier
|
||||||
maybeTypeParameters <- classTypeParameters
|
maybeTypeParameters <- classTypeParameters
|
||||||
|
maybeExtends <- optionMaybe (m_reserved "extends" *> classType)
|
||||||
|
maybeImplements <- optionMaybe (m_reserved "implements" *> m_commaSep interfaceType)
|
||||||
|
permits <- optionMaybe classPermits >>= return . Maybe.fromMaybe []
|
||||||
|
--body <- m_braces classBody
|
||||||
|
let isStatic = False
|
||||||
let typeParameters = Maybe.fromMaybe [] maybeTypeParameters
|
let typeParameters = Maybe.fromMaybe [] maybeTypeParameters
|
||||||
return (JavaClass.JavaClass className accessModifier maybeModifier isStatic typeParameters)
|
let implements = Maybe.fromMaybe [] maybeImplements
|
||||||
|
return (JavaClass.JavaClass className accessModifier maybeModifier isStatic typeParameters maybeExtends implements permits)
|
||||||
|
|
||||||
fileLevelParser = do
|
fileLevelParser = do
|
||||||
package <- packageParser
|
package <- packageParser
|
||||||
|
|
Loading…
Reference in a new issue