git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
First attempt at whitespace sensitive syntax
6b2d16bPhil Freeman
PureScript.cabal+6−5
@@ -11,10 +11,11 @@ synopsis: PureScript Programming Language Compiler
11description: A small compile-to-JS language with extensible records and type-safe blocks
11description: A small compile-to-JS language with extensible records and type-safe blocks
12author: Phil Freeman <paf31@cantab.net>
12author: Phil Freeman <paf31@cantab.net>
13data-dir: ""
13data-dir: ""
14−
14+
15library
15library
16 build-depends: base -any, syb -any, cmdtheline -any,
16 build-depends: base -any, syb -any, cmdtheline -any,
17− containers -any, mtl -any, parsec -any, utf8-string -any
17+ containers -any, mtl -any, parsec -any, utf8-string -any,
18+ indents -any
18 exposed-modules: PureScript
19 exposed-modules: PureScript
19 exposed: True
20 exposed: True
20 buildable: True
21 buildable: True
@@ -28,14 +29,14 @@ library
28 PureScript.Parser.Types PureScript.Parser.Values
29 PureScript.Parser.Types PureScript.Parser.Values
29 PureScript.TypeChecker.Kinds PureScript.TypeChecker.Monad
30 PureScript.TypeChecker.Kinds PureScript.TypeChecker.Monad
30 PureScript.TypeChecker.Types
31 PureScript.TypeChecker.Types
31−
32+
32executable psc
33executable psc
33 build-depends: base -any, cmdtheline -any, containers -any,
34 build-depends: base -any, cmdtheline -any, containers -any,
34− mtl -any, parsec -any, utf8-string -any
35+ mtl -any, parsec -any, utf8-string -any, indents -any
35 main-is: Main.hs
36 main-is: Main.hs
36 buildable: True
37 buildable: True
37 hs-source-dirs: src
38 hs-source-dirs: src
38 other-modules: PureScript.Names PureScript.TypeChecker.Synonyms
39 other-modules: PureScript.Names PureScript.TypeChecker.Synonyms
39 PureScript.CodeGen.Externs PureScript.CodeGen.JS
40 PureScript.CodeGen.Externs PureScript.CodeGen.JS
40 PureScript.CodeGen.Common.Gen PureScript.CodeGen.Common
41 PureScript.CodeGen.Common.Gen PureScript.CodeGen.Common
41−
42+
src/PureScript/Parser/Common.hs+51−28
@@ -16,14 +16,14 @@ module PureScript.Parser.Common where
16
16
17import Control.Applicative
17import Control.Applicative
18import qualified Text.Parsec as P
18import qualified Text.Parsec as P
19+import qualified Text.Parsec.Indent as I
19import qualified Text.Parsec.Token as PT
20import qualified Text.Parsec.Token as PT
20import qualified Text.Parsec.Language as PL
21import qualified Text.Parsec.Language as PL
21
22
22import PureScript.Names
23import PureScript.Names
23
24
24−langDef = PL.haskellStyle
25+langDef = PT.LanguageDef
25− { PT.identStart = P.lower <|> P.char '_'
26− , PT.reservedNames = [ "case"
26+ { PT.reservedNames = [ "case"
27 , "data"
27 , "data"
28 , "type"
28 , "type"
29 , "var"
29 , "var"
@@ -39,34 +39,57 @@ langDef = PL.haskellStyle
39 , "forall" ]
39 , "forall" ]
40 , PT.reservedOpNames = [ "!", "~", "-", "<=", ">=", "<", ">", "*", "/", "%", "++", "+", "<<", ">>>", ">>"
40 , PT.reservedOpNames = [ "!", "~", "-", "<=", ">=", "<", ">", "*", "/", "%", "++", "+", "<<", ">>>", ">>"
41 , "==", "!=", "&", "^", "|", "&&", "||" ]
41 , "==", "!=", "&", "^", "|", "&&", "||" ]
42+ , PT.commentStart = "{-"
43+ , PT.commentEnd = "-}"
44+ , PT.commentLine = "--"
45+ , PT.nestedComments = True
46+ , PT.identStart = P.lower <|> P.oneOf "_$"
47+ , PT.identLetter = P.alphaNum <|> P.oneOf "_'"
48+ , PT.opStart = P.oneOf ":#?@\\"
49+ , PT.opLetter = P.oneOf ":!#$%&*+./<=>?@\\^|-~"
50+ , PT.caseSensitive = True
42 }
51 }
43
52
44−tokenParser = PT.makeTokenParser langDef
53+tokenParser = PT.makeTokenParser langDef
45−lexeme = PT.lexeme tokenParser
54+
55+whiteSpace = P.skipMany $ (P.oneOf " \t" >> return ()) <|> P.try (P.skipMany1 (P.oneOf "\r\n")) >> I.indented <|> P.try lineComment <|> P.try blockComment
56+
57+lineComment = do
58+ P.string $ PT.commentLine langDef
59+ P.skipMany $ P.satisfy (/= '\n')
60+ I.indented
61+
62+blockComment = do
63+ P.string $ PT.commentStart langDef
64+ P.manyTill P.anyChar $ P.try $ P.string $ PT.commentEnd langDef
65+ return ()
66+
67+lexeme p = p <* whiteSpace
46−identifier = PT.identifier tokenParser
68+identifier = lexeme $ PT.identifier tokenParser
47−reserved = PT.reserved tokenParser
69+reserved s = lexeme $ PT.reserved tokenParser s
48−operator = PT.operator tokenParser
70+operator = lexeme $ PT.operator tokenParser
49−stringLiteral = PT.stringLiteral tokenParser
71+stringLiteral = lexeme $ PT.stringLiteral tokenParser
50−natural = PT.natural tokenParser
72+natural = lexeme $ PT.natural tokenParser
51−naturalOrFloat = PT.naturalOrFloat tokenParser
73+naturalOrFloat = lexeme $ PT.naturalOrFloat tokenParser
52−whiteSpace = PT.whiteSpace tokenParser
74+
53−parens = PT.parens tokenParser
54−braces = PT.braces tokenParser
55−angles = PT.angles tokenParser
56−brackets = PT.brackets tokenParser
57−squares = PT.squares tokenParser
58−semi = PT.semi tokenParser
75+semi = lexeme $ PT.semi tokenParser
59−comma = PT.comma tokenParser
76+comma = lexeme $ PT.comma tokenParser
60−colon = PT.colon tokenParser
77+colon = lexeme $ PT.colon tokenParser
61−dot = PT.dot tokenParser
78+dot = lexeme $ PT.dot tokenParser
62−semiSep = PT.semiSep tokenParser
79+
63−semiSep1 = PT.semiSep1 tokenParser
80+semiSep p = P.sepBy p semi
64−commaSep = PT.commaSep tokenParser
81+semiSep1 p = P.sepBy1 p semi
65−commaSep1 = PT.commaSep1 tokenParser
82+commaSep p = P.sepBy p comma
83+commaSep1 p = P.sepBy1 p comma
84+
85+parens p = lexeme (P.char '(') *> lexeme p <* lexeme (P.char ')')
86+braces p = lexeme (P.char '{') *> lexeme p <* lexeme (P.char '}')
87+angles p = lexeme (P.char '<') *> lexeme p <* lexeme (P.char '>')
88+squares p = lexeme (P.char '[') *> lexeme p <* lexeme (P.char ']')
66
89
67tick = lexeme (P.char '`')
90tick = lexeme (P.char '`')
68
91
69−properName :: P.Parsec String u String
92+properName :: I.IndentParser String u String
70properName = lexeme $ P.try properName'
93properName = lexeme $ P.try properName'
71 where
94 where
72 properName' = (:) <$> P.upper <*> many (PT.identLetter langDef) P.<?> "name"
95 properName' = (:) <$> P.upper <*> many (PT.identLetter langDef) P.<?> "name"
@@ -80,8 +103,8 @@ fold first more combine = do
80 bs <- P.many more
103 bs <- P.many more
81 return $ foldl combine a bs
104 return $ foldl combine a bs
82
105
83−parseIdent :: P.Parsec String () Ident
106+parseIdent :: I.IndentParser String () Ident
84parseIdent = (Ident <$> identifier) <|> (Op <$> parens operator)
107parseIdent = (Ident <$> identifier) <|> (Op <$> parens operator)
85
108
86−parseIdentInfix :: P.Parsec String () Ident
109+parseIdentInfix :: I.IndentParser String () Ident
87parseIdentInfix = (Ident <$> P.between tick tick identifier) <|> (Op <$> operator)
110parseIdentInfix = (Ident <$> P.between tick tick identifier) <|> (Op <$> operator)
src/PureScript/Parser/Declarations.hs+14−24
@@ -22,8 +22,11 @@ import Data.List
22import Data.Maybe
22import Data.Maybe
23import Data.Function
23import Data.Function
24import Control.Applicative
24import Control.Applicative
25−import qualified Text.Parsec as P
26import Control.Arrow (Arrow(..))
25import Control.Arrow (Arrow(..))
26+import Control.Monad.State
27+import qualified Text.Parsec as P
28+import qualified Text.Parsec.Pos as P
29+import qualified Text.Parsec.Indent as I
27
30
28import PureScript.Values
31import PureScript.Values
29import PureScript.Types
32import PureScript.Types
@@ -32,7 +35,7 @@ import PureScript.Declarations
32import PureScript.Parser.Values
35import PureScript.Parser.Values
33import PureScript.Parser.Types
36import PureScript.Parser.Types
34
37
35−parseDataDeclaration :: P.Parsec String () Declaration
38+parseDataDeclaration :: I.IndentParser String () Declaration
36parseDataDeclaration = do
39parseDataDeclaration = do
37 reserved "data"
40 reserved "data"
38 name <- properName
41 name <- properName
@@ -41,19 +44,19 @@ parseDataDeclaration = do
41 ctors <- P.sepBy1 ((,) <$> properName <*> P.optionMaybe parseType) (lexeme $ P.char '|')
44 ctors <- P.sepBy1 ((,) <$> properName <*> P.optionMaybe parseType) (lexeme $ P.char '|')
42 return $ DataDeclaration name tyArgs ctors
45 return $ DataDeclaration name tyArgs ctors
43
46
44−parseTypeDeclaration :: P.Parsec String () Declaration
47+parseTypeDeclaration :: I.IndentParser String () Declaration
45parseTypeDeclaration = TypeDeclaration <$> parseIdent <*> (lexeme (P.string "::") *> parsePolyType)
48parseTypeDeclaration = TypeDeclaration <$> parseIdent <*> (lexeme (P.string "::") *> parsePolyType)
46
49
47−parseTypeSynonymDeclaration :: P.Parsec String () Declaration
50+parseTypeSynonymDeclaration :: I.IndentParser String () Declaration
48parseTypeSynonymDeclaration = TypeSynonymDeclaration <$> (reserved "type" *> properName) <*> many identifier <*> (lexeme (P.char '=') *> parseType)
51parseTypeSynonymDeclaration = TypeSynonymDeclaration <$> (reserved "type" *> properName) <*> many identifier <*> (lexeme (P.char '=') *> parseType)
49
52
50−parseValueDeclaration :: P.Parsec String () Declaration
53+parseValueDeclaration :: I.IndentParser String () Declaration
51parseValueDeclaration = ValueDeclaration <$> parseIdent <*> (lexeme (P.char '=') *> parseValue)
54parseValueDeclaration = ValueDeclaration <$> parseIdent <*> (lexeme (P.char '=') *> parseValue)
52
55
53−parseExternDeclaration :: P.Parsec String () Declaration
56+parseExternDeclaration :: I.IndentParser String () Declaration
54parseExternDeclaration = ExternDeclaration <$> (reserved "extern" *> parseIdent) <*> (lexeme (P.string "::") *> parsePolyType)
57parseExternDeclaration = ExternDeclaration <$> (reserved "extern" *> parseIdent) <*> (lexeme (P.string "::") *> parsePolyType)
55
58
56−parseDeclaration :: P.Parsec String () Declaration
59+parseDeclaration :: I.IndentParser String () Declaration
57parseDeclaration = P.choice $ map P.try
60parseDeclaration = P.choice $ map P.try
58 [ parseDataDeclaration
61 [ parseDataDeclaration
59 , parseTypeDeclaration
62 , parseTypeDeclaration
@@ -61,22 +64,9 @@ parseDeclaration = P.choice $ map P.try
61 , parseValueDeclaration
64 , parseValueDeclaration
62 , parseExternDeclaration ]
65 , parseExternDeclaration ]
63
66
64−parseDeclarations :: String -> Either P.ParseError [Declaration]
67+parseManyDeclarations :: I.IndentParser String () [Declaration]
65−parseDeclarations = fmap catMaybes . mapM (P.parse (whiteSpace *> (P.optionMaybe parseDeclaration <* whiteSpace) <* P.eof) "Declaration") . splitFileIntoDeclarations
68+parseManyDeclarations = I.block $ I.withPos parseDeclaration
66−
67−isIndented :: String -> Bool
68−isIndented = any isSpace . take 1
69−
70−splitFileIntoDeclarations :: String -> [String]
71−splitFileIntoDeclarations = reverse . map (dropWhile isSpace . unlines . reverse) . go [] [] . lines
72− where
73− go [] sss [] = sss
74− go ss sss [] = ss:sss
75− go ss sss (s:rest)
76− | all isSpace s = go ss sss rest
77− | isIndented s = go (s:ss) sss rest
78− | null ss = go [s] sss rest
79− | otherwise = go [s] (ss:sss) rest
80−
81
69
70+parseDeclarations :: String -> Either P.ParseError [Declaration]
71+parseDeclarations = flip evalState (P.initialPos "Declarations") . P.runPT parseManyDeclarations () "Declarations"
82
72
src/PureScript/Parser/Types.hs+15−14
@@ -22,37 +22,38 @@ import PureScript.Types
22import PureScript.Parser.Common
22import PureScript.Parser.Common
23import Control.Applicative
23import Control.Applicative
24import qualified Text.Parsec as P
24import qualified Text.Parsec as P
25+import qualified Text.Parsec.Indent as I
25import Control.Arrow (Arrow(..))
26import Control.Arrow (Arrow(..))
26
27
27−parseNumber :: P.Parsec String () Type
28+parseNumber :: I.IndentParser String () Type
28parseNumber = const Number <$> P.string "Number"
29parseNumber = const Number <$> P.string "Number"
29
30
30−parseString :: P.Parsec String () Type
31+parseString :: I.IndentParser String () Type
31parseString = const String <$> P.string "String"
32parseString = const String <$> P.string "String"
32
33
33−parseBoolean :: P.Parsec String () Type
34+parseBoolean :: I.IndentParser String () Type
34parseBoolean = const Boolean <$> P.string "Boolean"
35parseBoolean = const Boolean <$> P.string "Boolean"
35
36
36−parseArray :: P.Parsec String () Type
37+parseArray :: I.IndentParser String () Type
37parseArray = squares $ Array <$> parseType
38parseArray = squares $ Array <$> parseType
38
39
39−parseObject :: P.Parsec String () Type
40+parseObject :: I.IndentParser String () Type
40parseObject = braces $ Object <$> parseRow
41parseObject = braces $ Object <$> parseRow
41
42
42−parseFunction :: P.Parsec String () Type
43+parseFunction :: I.IndentParser String () Type
43parseFunction = do
44parseFunction = do
44 args <- lexeme $ parens $ commaSep parseType
45 args <- lexeme $ parens $ commaSep parseType
45 lexeme $ P.string "->"
46 lexeme $ P.string "->"
46 resultType <- parseType
47 resultType <- parseType
47 return $ Function args resultType
48 return $ Function args resultType
48
49
49−parseTypeVariable :: P.Parsec String () Type
50+parseTypeVariable :: I.IndentParser String () Type
50parseTypeVariable = TypeVar <$> identifier
51parseTypeVariable = TypeVar <$> identifier
51
52
52−parseTypeConstructor :: P.Parsec String () Type
53+parseTypeConstructor :: I.IndentParser String () Type
53parseTypeConstructor = TypeConstructor <$> properName
54parseTypeConstructor = TypeConstructor <$> properName
54
55
55−parseTypeAtom :: P.Parsec String () Type
56+parseTypeAtom :: I.IndentParser String () Type
56parseTypeAtom = P.choice $ map P.try
57parseTypeAtom = P.choice $ map P.try
57 [ parseNumber
58 [ parseNumber
58 , parseString
59 , parseString
@@ -64,20 +65,20 @@ parseTypeAtom = P.choice $ map P.try
64 , parseTypeConstructor
65 , parseTypeConstructor
65 , parens parseType ]
66 , parens parseType ]
66
67
67−parsePolyType :: P.Parsec String () PolyType
68+parsePolyType :: I.IndentParser String () PolyType
68parsePolyType = PolyType <$> (P.option [] (reserved "forall" *> many identifier <* dot))
69parsePolyType = PolyType <$> (P.option [] (reserved "forall" *> many identifier <* dot))
69 <*> parseType
70 <*> parseType
70
71
71−parseType :: P.Parsec String () Type
72+parseType :: I.IndentParser String () Type
72parseType = fold (lexeme parseTypeAtom) (lexeme parseTypeAtom) TypeApp
73parseType = fold (lexeme parseTypeAtom) (lexeme parseTypeAtom) TypeApp
73
74
74−parseNameAndType :: P.Parsec String () (String, Type)
75+parseNameAndType :: I.IndentParser String () (String, Type)
75parseNameAndType = (,) <$> (identifier <* lexeme (P.string "::")) <*> parseType
76parseNameAndType = (,) <$> (identifier <* lexeme (P.string "::")) <*> parseType
76
77
77−parseRowEnding :: P.Parsec String () Row
78+parseRowEnding :: I.IndentParser String () Row
78parseRowEnding = P.option REmpty (RowVar <$> (lexeme (P.char '|') *> identifier))
79parseRowEnding = P.option REmpty (RowVar <$> (lexeme (P.char '|') *> identifier))
79
80
80−parseRow :: P.Parsec String () Row
81+parseRow :: I.IndentParser String () Row
81parseRow = fromList <$> semiSep parseNameAndType <*> parseRowEnding
82parseRow = fromList <$> semiSep parseNameAndType <*> parseRowEnding
82 where
83 where
83 fromList :: [(String, Type)] -> Row -> Row
84 fromList :: [(String, Type)] -> Row -> Row
src/PureScript/Parser/Values.hs+36−35
@@ -21,38 +21,39 @@ import PureScript.Values
21import qualified PureScript.Parser.Common as C
21import qualified PureScript.Parser.Common as C
22import Control.Applicative
22import Control.Applicative
23import qualified Text.Parsec as P
23import qualified Text.Parsec as P
24+import qualified Text.Parsec.Indent as I
24import Text.Parsec.Expr
25import Text.Parsec.Expr
25import Control.Monad
26import Control.Monad
26import Control.Arrow (Arrow(..))
27import Control.Arrow (Arrow(..))
27import PureScript.Parser.Types
28import PureScript.Parser.Types
28import PureScript.Types
29import PureScript.Types
29
30
30−booleanLiteral :: P.Parsec String () Bool
31+booleanLiteral :: I.IndentParser String () Bool
31booleanLiteral = (C.reserved "true" >> return True) P.<|> (C.reserved "false" >> return False)
32booleanLiteral = (C.reserved "true" >> return True) P.<|> (C.reserved "false" >> return False)
32
33
33−parseNumericLiteral :: P.Parsec String () Value
34+parseNumericLiteral :: I.IndentParser String () Value
34parseNumericLiteral = NumericLiteral <$> C.naturalOrFloat
35parseNumericLiteral = NumericLiteral <$> C.naturalOrFloat
35
36
36−parseStringLiteral :: P.Parsec String () Value
37+parseStringLiteral :: I.IndentParser String () Value
37parseStringLiteral = StringLiteral <$> C.stringLiteral
38parseStringLiteral = StringLiteral <$> C.stringLiteral
38
39
39−parseBooleanLiteral :: P.Parsec String () Value
40+parseBooleanLiteral :: I.IndentParser String () Value
40parseBooleanLiteral = BooleanLiteral <$> booleanLiteral
41parseBooleanLiteral = BooleanLiteral <$> booleanLiteral
41
42
42−parseArrayLiteral :: P.Parsec String () Value
43+parseArrayLiteral :: I.IndentParser String () Value
43parseArrayLiteral = ArrayLiteral <$> (C.squares $ C.commaSep parseValue)
44parseArrayLiteral = ArrayLiteral <$> (C.squares $ C.commaSep parseValue)
44
45
45−parseObjectLiteral :: P.Parsec String () Value
46+parseObjectLiteral :: I.IndentParser String () Value
46parseObjectLiteral = ObjectLiteral <$> (C.braces $ C.commaSep parseIdentifierAndValue)
47parseObjectLiteral = ObjectLiteral <$> (C.braces $ C.commaSep parseIdentifierAndValue)
47
48
48−parseIdentifierAndValue :: P.Parsec String () (String, Value)
49+parseIdentifierAndValue :: I.IndentParser String () (String, Value)
49parseIdentifierAndValue = do
50parseIdentifierAndValue = do
50 name <- C.lexeme C.identifier
51 name <- C.lexeme C.identifier
51 C.colon
52 C.colon
52 value <- parseValue
53 value <- parseValue
53 return (name, value)
54 return (name, value)
54
55
55−parseAbs :: P.Parsec String () Value
56+parseAbs :: I.IndentParser String () Value
56parseAbs = do
57parseAbs = do
57 C.lexeme $ P.char '\\'
58 C.lexeme $ P.char '\\'
58 args <- C.commaSep C.parseIdent
59 args <- C.commaSep C.parseIdent
@@ -60,27 +61,27 @@ parseAbs = do
60 value <- parseValue
61 value <- parseValue
61 return $ Abs args value
62 return $ Abs args value
62
63
63−parseApp :: P.Parsec String () Value
64+parseApp :: I.IndentParser String () Value
64parseApp = App <$> parseValue
65parseApp = App <$> parseValue
65 <*> (C.parens $ C.commaSep parseValue)
66 <*> (C.parens $ C.commaSep parseValue)
66
67
67−parseVar :: P.Parsec String () Value
68+parseVar :: I.IndentParser String () Value
68parseVar = Var <$> C.parseIdent
69parseVar = Var <$> C.parseIdent
69
70
70−parseConstructor :: P.Parsec String () Value
71+parseConstructor :: I.IndentParser String () Value
71parseConstructor = Constructor <$> C.properName
72parseConstructor = Constructor <$> C.properName
72
73
73−parseCase :: P.Parsec String () Value
74+parseCase :: I.IndentParser String () Value
74parseCase = Case <$> P.between (C.reserved "case") (C.reserved "of") parseValue
75parseCase = Case <$> P.between (C.reserved "case") (C.reserved "of") parseValue
75 <*> C.braces (C.semiSep parseCaseAlternative)
76 <*> C.braces (C.semiSep parseCaseAlternative)
76
77
77−parseCaseAlternative :: P.Parsec String () (Binder, Value)
78+parseCaseAlternative :: I.IndentParser String () (Binder, Value)
78parseCaseAlternative = (,) <$> (parseBinder <* C.lexeme (P.string "->")) <*> parseValue
79parseCaseAlternative = (,) <$> (parseBinder <* C.lexeme (P.string "->")) <*> parseValue
79
80
80−parseBlock :: P.Parsec String () Value
81+parseBlock :: I.IndentParser String () Value
81parseBlock = Block <$> (C.braces $ P.many (parseStatement True))
82parseBlock = Block <$> (C.braces $ P.many (parseStatement True))
82
83
83−parseValueAtom :: P.Parsec String () Value
84+parseValueAtom :: I.IndentParser String () Value
84parseValueAtom = P.choice $ map P.try
85parseValueAtom = P.choice $ map P.try
85 [ parseNumericLiteral
86 [ parseNumericLiteral
86 , parseStringLiteral
87 , parseStringLiteral
@@ -94,7 +95,7 @@ parseValueAtom = P.choice $ map P.try
94 , parseCase
95 , parseCase
95 , C.parens parseValue ]
96 , C.parens parseValue ]
96
97
97−parseValue :: P.Parsec String () Value
98+parseValue :: I.IndentParser String () Value
98parseValue = buildExpressionParser operators $ C.fold (C.lexeme typedValue) (C.lexeme funArgs) App
99parseValue = buildExpressionParser operators $ C.fold (C.lexeme typedValue) (C.lexeme funArgs) App
99 where
100 where
100 typedValue = C.augment parseValueAtom parseTypeAnnotation TypedValue
101 typedValue = C.augment parseValueAtom parseTypeAnnotation TypedValue
@@ -128,7 +129,7 @@ parseValue = buildExpressionParser operators $ C.fold (C.lexeme typedValue) (C.l
128 , [ Infix (C.lexeme (P.string "||") >> return (Binary Or)) AssocRight ]
129 , [ Infix (C.lexeme (P.string "||") >> return (Binary Or)) AssocRight ]
129 ]
130 ]
130
131
131−parseVariableIntroduction :: Bool -> P.Parsec String () Statement
132+parseVariableIntroduction :: Bool -> I.IndentParser String () Statement
132parseVariableIntroduction requireSemi = do
133parseVariableIntroduction requireSemi = do
133 C.reserved "var"
134 C.reserved "var"
134 name <- C.parseIdent
135 name <- C.parseIdent
@@ -137,7 +138,7 @@ parseVariableIntroduction requireSemi = do
137 when requireSemi (void C.semi)
138 when requireSemi (void C.semi)
138 return $ VariableIntroduction name value
139 return $ VariableIntroduction name value
139
140
140−parseAssignment :: Bool -> P.Parsec String () (Statement)
141+parseAssignment :: Bool -> I.IndentParser String () (Statement)
141parseAssignment requireSemi = do
142parseAssignment requireSemi = do
142 tgt <- parseAssignmentTarget
143 tgt <- parseAssignmentTarget
143 C.lexeme $ P.char '='
144 C.lexeme $ P.char '='
@@ -145,14 +146,14 @@ parseAssignment requireSemi = do
145 when requireSemi (void C.semi)
146 when requireSemi (void C.semi)
146 return $ Assignment tgt value
147 return $ Assignment tgt value
147
148
148−parseManyStatements :: P.Parsec String () [Statement]
149+parseManyStatements :: I.IndentParser String () [Statement]
149parseManyStatements = C.braces $ P.many (parseStatement True)
150parseManyStatements = C.braces $ P.many (parseStatement True)
150
151
151−parseWhile :: P.Parsec String () Statement
152+parseWhile :: I.IndentParser String () Statement
152parseWhile = While <$> (C.reserved "while" *> C.parens parseValue)
153parseWhile = While <$> (C.reserved "while" *> C.parens parseValue)
153 <*> parseManyStatements
154 <*> parseManyStatements
154
155
155−parseFor :: P.Parsec String () Statement
156+parseFor :: I.IndentParser String () Statement
156parseFor = For <$> (C.reserved "for" *> C.parens forIntro)
157parseFor = For <$> (C.reserved "for" *> C.parens forIntro)
157 <*> parseManyStatements
158 <*> parseManyStatements
158 where
159 where
@@ -160,16 +161,16 @@ parseFor = For <$> (C.reserved "for" *> C.parens forIntro)
160 <*> (C.semi *> parseValue)
161 <*> (C.semi *> parseValue)
161 <*> (C.semi *> parseStatement False)
162 <*> (C.semi *> parseStatement False)
162
163
163−parseIfThenElse :: P.Parsec String () Statement
164+parseIfThenElse :: I.IndentParser String () Statement
164parseIfThenElse = IfThenElse
165parseIfThenElse = IfThenElse
165 <$> (C.reserved "if" *> C.parens parseValue)
166 <$> (C.reserved "if" *> C.parens parseValue)
166 <*> parseManyStatements
167 <*> parseManyStatements
167 <*> P.optionMaybe (C.reserved "else" *> parseManyStatements)
168 <*> P.optionMaybe (C.reserved "else" *> parseManyStatements)
168
169
169−parseReturn :: Bool -> P.Parsec String () Statement
170+parseReturn :: Bool -> I.IndentParser String () Statement
170parseReturn requireSemi = Return <$> (C.reserved "return" *> parseValue <* when requireSemi (void C.semi))
171parseReturn requireSemi = Return <$> (C.reserved "return" *> parseValue <* when requireSemi (void C.semi))
171
172
172−parseStatement :: Bool -> P.Parsec String () Statement
173+parseStatement :: Bool -> I.IndentParser String () Statement
173parseStatement requireSemi = P.choice $ map P.try
174parseStatement requireSemi = P.choice $ map P.try
174 [ parseVariableIntroduction requireSemi
175 [ parseVariableIntroduction requireSemi
175 , parseAssignment requireSemi
176 , parseAssignment requireSemi
@@ -178,38 +179,38 @@ parseStatement requireSemi = P.choice $ map P.try
178 , parseIfThenElse
179 , parseIfThenElse
179 , parseReturn requireSemi ]
180 , parseReturn requireSemi ]
180
181
181−parseStringBinder :: P.Parsec String () Binder
182+parseStringBinder :: I.IndentParser String () Binder
182parseStringBinder = StringBinder <$> C.stringLiteral
183parseStringBinder = StringBinder <$> C.stringLiteral
183
184
184−parseBooleanBinder :: P.Parsec String () Binder
185+parseBooleanBinder :: I.IndentParser String () Binder
185parseBooleanBinder = BooleanBinder <$> booleanLiteral
186parseBooleanBinder = BooleanBinder <$> booleanLiteral
186
187
187−parseNumberBinder :: P.Parsec String () Binder
188+parseNumberBinder :: I.IndentParser String () Binder
188parseNumberBinder = NumberBinder <$> C.naturalOrFloat
189parseNumberBinder = NumberBinder <$> C.naturalOrFloat
189
190
190−parseVarBinder :: P.Parsec String () Binder
191+parseVarBinder :: I.IndentParser String () Binder
191parseVarBinder = VarBinder <$> C.parseIdent
192parseVarBinder = VarBinder <$> C.parseIdent
192
193
193−parseNullaryBinder :: P.Parsec String () Binder
194+parseNullaryBinder :: I.IndentParser String () Binder
194parseNullaryBinder = NullaryBinder <$> C.lexeme C.properName
195parseNullaryBinder = NullaryBinder <$> C.lexeme C.properName
195
196
196−parseUnaryBinder :: P.Parsec String () Binder
197+parseUnaryBinder :: I.IndentParser String () Binder
197parseUnaryBinder = UnaryBinder <$> C.lexeme C.properName <*> parseBinder
198parseUnaryBinder = UnaryBinder <$> C.lexeme C.properName <*> parseBinder
198
199
199−parseObjectBinder :: P.Parsec String () Binder
200+parseObjectBinder :: I.IndentParser String () Binder
200parseObjectBinder = ObjectBinder <$> C.braces (C.commaSep parseIdentifierAndBinder)
201parseObjectBinder = ObjectBinder <$> C.braces (C.commaSep parseIdentifierAndBinder)
201
202
202−parseArrayBinder :: P.Parsec String () Binder
203+parseArrayBinder :: I.IndentParser String () Binder
203parseArrayBinder = C.squares $ ArrayBinder <$> (C.commaSep parseBinder) <*> P.optionMaybe (C.colon *> parseBinder)
204parseArrayBinder = C.squares $ ArrayBinder <$> (C.commaSep parseBinder) <*> P.optionMaybe (C.colon *> parseBinder)
204
205
205−parseIdentifierAndBinder :: P.Parsec String () (String, Binder)
206+parseIdentifierAndBinder :: I.IndentParser String () (String, Binder)
206parseIdentifierAndBinder = do
207parseIdentifierAndBinder = do
207 name <- C.lexeme C.identifier
208 name <- C.lexeme C.identifier
208 C.lexeme $ P.char '='
209 C.lexeme $ P.char '='
209 binder <- parseBinder
210 binder <- parseBinder
210 return (name, binder)
211 return (name, binder)
211
212
212−parseBinder :: P.Parsec String () Binder
213+parseBinder :: I.IndentParser String () Binder
213parseBinder = P.choice $ map P.try
214parseBinder = P.choice $ map P.try
214 [ parseStringBinder
215 [ parseStringBinder
215 , parseBooleanBinder
216 , parseBooleanBinder
@@ -221,7 +222,7 @@ parseBinder = P.choice $ map P.try
221 , parseArrayBinder
222 , parseArrayBinder
222 , C.parens parseBinder ]
223 , C.parens parseBinder ]
223
224
224−parseAssignmentTarget :: P.Parsec String () AssignmentTarget
225+parseAssignmentTarget :: I.IndentParser String () AssignmentTarget
225parseAssignmentTarget = buildExpressionParser operators (AssignVariable <$> C.parseIdent)
226parseAssignmentTarget = buildExpressionParser operators (AssignVariable <$> C.parseIdent)
226 where
227 where
227 operators = [ [ Postfix $ AssignArrayIndex <$> C.squares parseValue
228 operators = [ [ Postfix $ AssignArrayIndex <$> C.squares parseValue