Commit f0877237 authored by Kenton Varda's avatar Kenton Varda

Bunch of little things.

parent 2e3f671c
...@@ -19,5 +19,6 @@ executable capnproto-compiler ...@@ -19,5 +19,6 @@ executable capnproto-compiler
Grammar, Grammar,
Parser, Parser,
Compiler, Compiler,
Semantics Semantics,
Util
This diff is collapsed.
...@@ -39,8 +39,9 @@ data FieldValue = VoidFieldValue ...@@ -39,8 +39,9 @@ data FieldValue = VoidFieldValue
| IntegerFieldValue Integer | IntegerFieldValue Integer
| FloatFieldValue Double | FloatFieldValue Double
| StringFieldValue String | StringFieldValue String
| ArrayFieldValue [FieldValue] | IdentifierFieldValue String
| RecordFieldValue [(String, FieldValue)] | ListFieldValue [Located FieldValue]
| RecordFieldValue [(Located String, Located FieldValue)]
deriving (Show) deriving (Show)
data Declaration = AliasDecl (Located String) DeclName data Declaration = AliasDecl (Located String) DeclName
...@@ -56,3 +57,14 @@ data Declaration = AliasDecl (Located String) DeclName ...@@ -56,3 +57,14 @@ data Declaration = AliasDecl (Located String) DeclName
TypeExpression [Declaration] TypeExpression [Declaration]
| OptionDecl DeclName (Located FieldValue) | OptionDecl DeclName (Located FieldValue)
deriving (Show) deriving (Show)
declarationName :: Declaration -> Maybe (Located String)
declarationName (AliasDecl n _) = Just n
declarationName (ConstantDecl n _ _) = Just n
declarationName (EnumDecl n _) = Just n
declarationName (EnumValueDecl n _ _) = Just n
declarationName (StructDecl n _) = Just n
declarationName (FieldDecl n _ _ _ _) = Just n
declarationName (InterfaceDecl n _) = Just n
declarationName (MethodDecl n _ _ _ _) = Just n
declarationName (OptionDecl _ _) = Nothing
...@@ -86,6 +86,7 @@ token = keyword ...@@ -86,6 +86,7 @@ token = keyword
<|> liftM (const Colon) (symbol ":") <|> liftM (const Colon) (symbol ":")
<|> liftM (const Period) (symbol ".") <|> liftM (const Period) (symbol ".")
<|> liftM (const EqualsSign) (symbol "=") <|> liftM (const EqualsSign) (symbol "=")
<|> liftM (const MinusSign) (symbol "-")
<?> "token" <?> "token"
locatedToken = located token locatedToken = located token
......
...@@ -25,6 +25,10 @@ module Main ( main ) where ...@@ -25,6 +25,10 @@ module Main ( main ) where
import System.Environment import System.Environment
import Compiler import Compiler
import Util(delimit)
import Text.Parsec.Pos
import Text.Parsec.Error
import Text.Printf(printf)
main::IO() main::IO()
main = do main = do
...@@ -35,5 +39,22 @@ handleFile filename = do ...@@ -35,5 +39,22 @@ handleFile filename = do
text <- readFile filename text <- readFile filename
case parseAndCompileFile filename text of case parseAndCompileFile filename text of
Active desc [] -> print desc Active desc [] -> print desc
Active _ e -> mapM_ print e Active _ e -> mapM_ printError e
Failed e -> mapM_ print e Failed e -> mapM_ printError e
--printError e = mapM_ printMessage (errorMessages e) where
-- pos = errorPos e
-- f = sourceName pos
-- l = sourceLine pos
-- c = sourceColumn pos
-- printMessage :: Message -> IO ()
-- printMessage m = printf "%s:%d:%d: %s\n" f l c (messageString m)
printError e = printf "%s:%d:%d: %s\n" f l c m' where
pos = errorPos e
f = sourceName pos
l = sourceLine pos
c = sourceColumn pos
m = showErrorMessages "or" "Unknown parse error" "Expected" "Unexpected" "end of expression"
(errorMessages e)
m' = delimit "; " (lines m)
...@@ -25,12 +25,31 @@ module Parser (parseFile) where ...@@ -25,12 +25,31 @@ module Parser (parseFile) where
import Text.Parsec hiding (tokens) import Text.Parsec hiding (tokens)
import Token import Token
import Control.Monad (liftM)
import Grammar import Grammar
import Lexer (lexer) import Lexer (lexer)
import Control.Monad.Identity
tokenParser :: (Located Token -> Maybe a) -> Parsec [Located Token] u a tokenParser :: (Located Token -> Maybe a) -> Parsec [Located Token] u a
tokenParser = token (show . locatedValue) locatedPos tokenParser = token (tokenErrorString . locatedValue) locatedPos
tokenErrorString (Identifier s) = "identifier \"" ++ s ++ "\""
tokenErrorString (ParenthesizedList _) = "parenthesized list"
tokenErrorString (BracketedList _) = "bracketed list"
tokenErrorString (LiteralInt i) = "integer literal " ++ show i
tokenErrorString (LiteralFloat f) = "float literal " ++ show f
tokenErrorString (LiteralString s) = "string literal " ++ show s
tokenErrorString AtSign = "\"@\""
tokenErrorString Colon = "\":\""
tokenErrorString Period = "\".\""
tokenErrorString EqualsSign = "\"=\""
tokenErrorString MinusSign = "\"-\""
tokenErrorString ImportKeyword = "\"import\""
tokenErrorString UsingKeyword = "\"using\""
tokenErrorString ConstKeyword = "\"const\""
tokenErrorString EnumKeyword = "\"enum\""
tokenErrorString StructKeyword = "\"struct\""
tokenErrorString InterfaceKeyword = "\"interface\""
tokenErrorString OptionKeyword = "\"option\""
type TokenParser = Parsec [Located Token] [ParseError] type TokenParser = Parsec [Located Token] [ParseError]
...@@ -49,22 +68,23 @@ matchLiteralFloat t = case locatedValue t of { (LiteralFloat v) -> Jus ...@@ -49,22 +68,23 @@ matchLiteralFloat t = case locatedValue t of { (LiteralFloat v) -> Jus
matchLiteralString t = case locatedValue t of { (LiteralString v) -> Just v; _ -> Nothing } matchLiteralString t = case locatedValue t of { (LiteralString v) -> Just v; _ -> Nothing }
matchSimpleToken expected t = if locatedValue t == expected then Just () else Nothing matchSimpleToken expected t = if locatedValue t == expected then Just () else Nothing
identifier = tokenParser matchIdentifier identifier = tokenParser matchIdentifier <?> "identifier"
literalInt = tokenParser matchLiteralInt literalInt = tokenParser matchLiteralInt <?> "integer"
literalFloat = tokenParser matchLiteralFloat literalFloat = tokenParser matchLiteralFloat <?> "floating-point number"
literalString = tokenParser matchLiteralString literalString = tokenParser matchLiteralString <?> "string"
atSign = tokenParser (matchSimpleToken AtSign) atSign = tokenParser (matchSimpleToken AtSign) <?> "\"@\""
colon = tokenParser (matchSimpleToken Colon) colon = tokenParser (matchSimpleToken Colon) <?> "\":\""
period = tokenParser (matchSimpleToken Period) period = tokenParser (matchSimpleToken Period) <?> "\".\""
equalsSign = tokenParser (matchSimpleToken EqualsSign) equalsSign = tokenParser (matchSimpleToken EqualsSign) <?> "\"=\""
importKeyword = tokenParser (matchSimpleToken ImportKeyword) minusSign = tokenParser (matchSimpleToken MinusSign) <?> "\"=\""
usingKeyword = tokenParser (matchSimpleToken UsingKeyword) importKeyword = tokenParser (matchSimpleToken ImportKeyword) <?> "\"import\""
constKeyword = tokenParser (matchSimpleToken ConstKeyword) usingKeyword = tokenParser (matchSimpleToken UsingKeyword) <?> "\"using\""
enumKeyword = tokenParser (matchSimpleToken EnumKeyword) constKeyword = tokenParser (matchSimpleToken ConstKeyword) <?> "\"const\""
structKeyword = tokenParser (matchSimpleToken StructKeyword) enumKeyword = tokenParser (matchSimpleToken EnumKeyword) <?> "\"enum\""
interfaceKeyword = tokenParser (matchSimpleToken InterfaceKeyword) structKeyword = tokenParser (matchSimpleToken StructKeyword) <?> "\"struct\""
optionKeyword = tokenParser (matchSimpleToken OptionKeyword) interfaceKeyword = tokenParser (matchSimpleToken InterfaceKeyword) <?> "\"interface\""
optionKeyword = tokenParser (matchSimpleToken OptionKeyword) <?> "\"option\""
parenthesizedList parser = do parenthesizedList parser = do
items <- tokenParser matchParenthesizedList items <- tokenParser matchParenthesizedList
...@@ -155,16 +175,22 @@ fieldDecl statements = do ...@@ -155,16 +175,22 @@ fieldDecl statements = do
children <- parseBlock fieldLine statements children <- parseBlock fieldLine statements
return (FieldDecl name ordinal t value children) return (FieldDecl name ordinal t value children)
negativeFieldValue = liftM (IntegerFieldValue . negate) literalInt
<|> liftM (FloatFieldValue . negate) literalFloat
fieldValue = liftM IntegerFieldValue literalInt fieldValue = liftM IntegerFieldValue literalInt
<|> liftM FloatFieldValue literalFloat <|> liftM FloatFieldValue literalFloat
<|> liftM StringFieldValue literalString <|> liftM StringFieldValue literalString
<|> liftM ArrayFieldValue (bracketedList fieldValue) <|> liftM IdentifierFieldValue identifier
<|> liftM ListFieldValue (bracketedList (located fieldValue))
<|> liftM RecordFieldValue (parenthesizedList fieldAssignment) <|> liftM RecordFieldValue (parenthesizedList fieldAssignment)
<|> (minusSign >> negativeFieldValue)
<?> "default value"
fieldAssignment = do fieldAssignment = do
name <- identifier name <- located identifier
equalsSign equalsSign
value <- fieldValue value <- located fieldValue
return (name, value) return (name, value)
fieldLine :: Maybe [Located Statement] -> TokenParser Declaration fieldLine :: Maybe [Located Statement] -> TokenParser Declaration
...@@ -186,6 +212,7 @@ methodDecl statements = do ...@@ -186,6 +212,7 @@ methodDecl statements = do
atSign atSign
ordinal <- located literalInt ordinal <- located literalInt
params <- parenthesizedList paramDecl params <- parenthesizedList paramDecl
colon
t <- typeExpression t <- typeExpression
children <- parseBlock methodLine statements children <- parseBlock methodLine statements
return (MethodDecl name ordinal params t children) return (MethodDecl name ordinal params t children)
...@@ -227,8 +254,16 @@ parseBlock parser statements = finish where ...@@ -227,8 +254,16 @@ parseBlock parser statements = finish where
return [ result | Right (result, _) <- results ] return [ result | Right (result, _) <- results ]
parseCollectingErrors :: TokenParser a -> [Located Token] -> Either ParseError (a, [ParseError]) parseCollectingErrors :: TokenParser a -> [Located Token] -> Either ParseError (a, [ParseError])
parseCollectingErrors parser = runParser parser' [] "" where parseCollectingErrors parser tokens = runParser parser' [] "" tokens where
parser' = do parser' = do
-- Work around Parsec bug: Text.Parsec.Print.token is supposed to produce a parser that
-- sets the position by using the provided function to extract it from each token. However,
-- it doesn't bother to call this function for the *first* token, only subsequent tokens.
-- The first token is always assumed to be at 1:1. To fix this, set it manually.
case tokens of
Located pos _:_ -> setPosition pos
[] -> return ()
result <- parser result <- parser
eof eof
errors <- getState errors <- getState
......
...@@ -30,6 +30,7 @@ import Data.Word (Word8, Word16, Word32, Word64) ...@@ -30,6 +30,7 @@ import Data.Word (Word8, Word16, Word32, Word64)
import Data.Char (chr) import Data.Char (chr)
import Text.Printf(printf) import Text.Printf(printf)
import Control.Monad(join) import Control.Monad(join)
import Util(delimit)
type ByteString = [Word8] type ByteString = [Word8]
...@@ -81,7 +82,7 @@ data BuiltinType = BuiltinVoid | BuiltinBool ...@@ -81,7 +82,7 @@ data BuiltinType = BuiltinVoid | BuiltinBool
| BuiltinInt8 | BuiltinInt16 | BuiltinInt32 | BuiltinInt64 | BuiltinInt8 | BuiltinInt16 | BuiltinInt32 | BuiltinInt64
| BuiltinUInt8 | BuiltinUInt16 | BuiltinUInt32 | BuiltinUInt64 | BuiltinUInt8 | BuiltinUInt16 | BuiltinUInt32 | BuiltinUInt64
| BuiltinFloat32 | BuiltinFloat64 | BuiltinFloat32 | BuiltinFloat64
| BuiltinText | BuiltinBytes | BuiltinText | BuiltinData
deriving (Show, Enum, Bounded, Eq) deriving (Show, Enum, Bounded, Eq)
builtinTypes = [minBound::BuiltinType .. maxBound::BuiltinType] builtinTypes = [minBound::BuiltinType .. maxBound::BuiltinType]
...@@ -103,7 +104,10 @@ data ValueDesc = VoidDesc ...@@ -103,7 +104,10 @@ data ValueDesc = VoidDesc
| Float32Desc Float | Float32Desc Float
| Float64Desc Double | Float64Desc Double
| TextDesc String | TextDesc String
| BytesDesc ByteString | DataDesc ByteString
| EnumValueValueDesc EnumValueDesc
| StructValueDesc [(FieldDesc, ValueDesc)]
| ListDesc [ValueDesc]
deriving (Show) deriving (Show)
valueString VoidDesc = error "Can't stringify void value." valueString VoidDesc = error "Can't stringify void value."
...@@ -119,7 +123,11 @@ valueString (UInt64Desc i) = show i ...@@ -119,7 +123,11 @@ valueString (UInt64Desc i) = show i
valueString (Float32Desc x) = show x valueString (Float32Desc x) = show x
valueString (Float64Desc x) = show x valueString (Float64Desc x) = show x
valueString (TextDesc s) = show s valueString (TextDesc s) = show s
valueString (BytesDesc s) = show (map (chr . fromIntegral) s) valueString (DataDesc s) = show (map (chr . fromIntegral) s)
valueString (EnumValueValueDesc v) = enumValueName v
valueString (StructValueDesc l) = "(" ++ delimit ", " (map assignmentString l) ++ ")" where
assignmentString (field, value) = fieldName field ++ " = " ++ valueString value
valueString (ListDesc l) = "[" ++ delimit ", " (map valueString l) ++ "]" where
data TypeDesc = BuiltinType BuiltinType data TypeDesc = BuiltinType BuiltinType
| EnumType EnumDesc | EnumType EnumDesc
......
...@@ -26,11 +26,17 @@ module Token where ...@@ -26,11 +26,17 @@ module Token where
import Text.Parsec.Pos (SourcePos, sourceLine, sourceColumn) import Text.Parsec.Pos (SourcePos, sourceLine, sourceColumn)
import Text.Printf (printf) import Text.Printf (printf)
data Located t = Located { locatedPos :: SourcePos, locatedValue :: t } deriving (Eq) data Located t = Located { locatedPos :: SourcePos, locatedValue :: t }
instance Show t => Show (Located t) where instance Show t => Show (Located t) where
show (Located pos x) = printf "%d:%d:%s" (sourceLine pos) (sourceColumn pos) (show x) show (Located pos x) = printf "%d:%d:%s" (sourceLine pos) (sourceColumn pos) (show x)
instance Eq a => Eq (Located a) where
Located _ a == Located _ b = a == b
instance Ord a => Ord (Located a) where
compare (Located _ a) (Located _ b) = compare a b
data Token = Identifier String data Token = Identifier String
| ParenthesizedList [[Located Token]] | ParenthesizedList [[Located Token]]
| BracketedList [[Located Token]] | BracketedList [[Located Token]]
...@@ -41,6 +47,7 @@ data Token = Identifier String ...@@ -41,6 +47,7 @@ data Token = Identifier String
| Colon | Colon
| Period | Period
| EqualsSign | EqualsSign
| MinusSign
| ImportKeyword | ImportKeyword
| UsingKeyword | UsingKeyword
| ConstKeyword | ConstKeyword
......
-- Copyright (c) 2013, Kenton Varda <temporal@gmail.com>
-- All rights reserved.
--
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- 1. Redistributions of source code must retain the above copyright notice, this
-- list of conditions and the following disclaimer.
-- 2. Redistributions in binary form must reproduce the above copyright notice,
-- this list of conditions and the following disclaimer in the documentation
-- and/or other materials provided with the distribution.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
module Util where
delimit delimiter list = concat $ loop list where
loop ("":t) = loop t
loop (a:"":t) = loop (a:t)
loop (a:b:t) = a:delimiter:loop (b:t)
loop a = a
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment