Skip to content
This repository was archived by the owner on Oct 5, 2024. It is now read-only.

Parse comments #106

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
513 changes: 356 additions & 157 deletions src/Elm/AST/Frontend.elm

Large diffs are not rendered by default.

67 changes: 44 additions & 23 deletions src/Elm/AST/Frontend/Unwrapped.elm
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,78 @@ module Elm.AST.Frontend.Unwrapped exposing
, Pattern(..)
)

{-| Version of [Frontend AST](Elm.AST.Frontend) without the location info.
{-| Version of [Frontend AST](Elm.AST.Frontend) without the location info or comments.

Handy for parser tests, or when you don't need the location info.
Handy for parser tests, or when you don't need the location info and the comments.

Convert to it using the [`Elm.AST.Frontend.unwrap`](Elm.AST.Frontend#unwrap).

@docs Expr

-}

import Elm.Data.Binding exposing (Binding)
import Elm.Data.Binding as Binding exposing (Binding)
import Elm.Data.Comment exposing (Comment)
import Elm.Data.Qualifiedness exposing (PossiblyQualified)
import Elm.Data.VarName exposing (VarName)


{-| -}
type Expr
= Int Int
= Unit
| Bool Bool
| Int Int
| Float Float
| Char Char
| String String
| Bool Bool
| Var { qualifiedness : PossiblyQualified, name : VarName }
| Argument VarName
| Plus Expr Expr
| Cons Expr Expr
| ListConcat Expr Expr
| Lambda { arguments : List VarName, body : Expr }
| Call { fn : Expr, argument : Expr }
| If { test : Expr, then_ : Expr, else_ : Expr }
| Let { bindings : List (Binding Expr), body : Expr }
| List (List Expr)
| Unit
| Tuple Expr Expr
| Tuple3 Expr Expr Expr
| Record (List (Binding Expr))
| Case Expr (List { pattern : Pattern, body : Expr })
| List (List Expr)
| Call
{ fn : Expr
, argument : Expr
}
| Lambda
{ arguments : List VarName
, body : Expr
}
| Plus Expr Expr
| Cons Expr Expr
| ListConcat Expr Expr
| Let
{ bindings : List (Binding Expr)
, body : Expr
}
| If
{ test : Expr
, then_ : Expr
, else_ : Expr
}
| Case
{ test : Expr
, branches :
List
{ pattern : Pattern
, body : Expr
}
}


type Pattern
= PAnything
| PVar VarName
| PRecord (List VarName)
| PAlias Pattern VarName
| PUnit
| PBool Bool
| PInt Int
| PFloat Float
| PChar Char
| PString String
| PVar VarName
| PTuple Pattern Pattern
| PTuple3 Pattern Pattern Pattern
| PRecord (List VarName)
| PList (List Pattern)
| PAlias Pattern VarName
| PCons Pattern Pattern
| PBool Bool
| PChar Char
| PString String
| PInt Int
| PFloat Float
10 changes: 6 additions & 4 deletions src/Elm/Compiler.elm
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,9 @@ type alias Parser a =
-}
parse : Parser a -> FileContents -> Result Error a
parse parser sourceCode =
Result.mapError
(\errorList -> ParseError (ParseProblem ( errorList, sourceCode )))
(P.run parser sourceCode)
P.run parser sourceCode
|> Result.mapError
(\errorList -> ParseError (ParseProblem ( errorList, sourceCode )))


{-| Parse a single expression like
Expand All @@ -198,6 +198,7 @@ use [`Elm.AST.Frontend.unwrap`](Elm.AST.Frontend#unwrap) to get something like
parseExpr : FileContents -> Result Error Frontend.LocatedExpr
parseExpr sourceCode =
parse Stage.Parse.Parser.expr sourceCode
|> Result.map Tuple.first


{-| Parse a module (one `*.elm` file). Get a [`Module`](Elm.Data.Module#Module) datastructure back, holding
Expand Down Expand Up @@ -288,6 +289,7 @@ into
parseImport : FileContents -> Result Error Import
parseImport sourceCode =
parse Stage.Parse.Parser.import_ sourceCode
|> Result.map (\import_ -> Tuple.first (import_ []))


{-| Parse a single declaration, like
Expand All @@ -308,7 +310,7 @@ parseDeclaration :
-> Result Error (Declaration Frontend.LocatedExpr TypeAnnotation PossiblyQualified)
parseDeclaration { moduleName, declaration } =
parse Stage.Parse.Parser.declaration declaration
|> Result.map (\toDeclaration -> toDeclaration moduleName)
|> Result.map (\toDeclaration -> Tuple.first (toDeclaration []) moduleName)



Expand Down
107 changes: 106 additions & 1 deletion src/Elm/Compiler/Error.elm
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ type ParseContext
| InTuple
| InTuple3
| InRecord
| InRecordBinding
| InFile FilePath
| InCase
| InPattern
Expand All @@ -96,13 +97,15 @@ type ParseContext
| InTypeBinding
| InPatternVar
| InPatternRecord
| InImport


{-| The specific problem the parser encountered. Together with [`ParseContext`](#ParseContext)
and the [location info](Elm.Data.Located) this should give you enough info about what's wrong.
-}
type ParseProblem
= ExpectingPortKeyword -- `>port< module ...`
= TooMuchIndentation String
| ExpectingPortKeyword -- `>port< module ...`
| ExpectingEffectKeyword -- `>effect< module ...`
| ExpectingModuleKeyword -- `>module< Foo.Bar exposing (..)`
| ExpectingModuleName -- `module >Foo.Bar< exposing (..)`
Expand Down Expand Up @@ -151,6 +154,8 @@ type ParseProblem
| ExpectingTrue
| ExpectingFalse
| ExpectingLet
| ExpectingLetIndentation
| ExpectingLetBindingIndentation
| ExpectingIn
| ExpectingUnit
| ExpectingColon
Expand All @@ -168,9 +173,14 @@ type ParseProblem
| ExpectingIndentation
| ExpectingPatternAnything -- `>_< ->`
| ExpectingMaxThreeTuple
| ExpectingExpression
| ExpectingTypeName
| ExpectingNewlineAfterTypeAnnotation
| ExpectingTypeAnnotationDefinition
| ExpectingNonSpaceAfterTypeAnnotationNewlines
| ExpectingSingleLineCommentStart -- --
| ExpectingMultiLineCommentStart -- {-
| ExpectingMultiLineCommentEnd -- -}
| InvalidTab
| InvalidNumber
| TriedToParseCharacterStoppingDelimiter
Expand Down Expand Up @@ -404,6 +414,18 @@ fullVarName { qualifiedness, name } =
parseProblemToString : ParseProblem -> String
parseProblemToString problem =
case problem of
TooMuchIndentation str ->
{- TODO
Too Much Indentation
Line 1, Column 2
This `module` should not have any spaces before it:

1| module Main
^
Delete the spaces before `module` until there are none left!
-}
"TooMuchIndentation " ++ str

ExpectingPortKeyword ->
"ExpectingPortKeyword"

Expand Down Expand Up @@ -551,6 +573,51 @@ parseProblemToString problem =
ExpectingLet ->
"ExpectingLet"

ExpectingLetIndentation ->
{- TODO
Unfinished Let
Line 20, Column 6
I was partway through parsing a `let` expression, but I got stuck here:

20| let
^
I was expecting a value to be defined here.

Note: Here is an example with a valid `let` expression for reference:

viewPerson person =
let
fullName =
person.firstName ++ " " ++ person.lastName
in
div [] [ text fullName ]

Here we defined a `viewPerson` function that turns a person into some HTML. We
use a `let` expression to define the `fullName` we want to show. Notice the
indentation! The `fullName` is indented more than the `let` keyword, and the
actual value of `fullName` is indented a bit more than that. That is important!
-}
"ExpectingLetIndentation"

ExpectingLetBindingIndentation ->
{- TODO
ERRORS
Unexpected Equals
Line 22, Column 7
I was not expecting to see this equals sign:

22| y = 2 in { count = 0 }
^
Maybe you want == instead? To check if two values are equal?

Note: I may be getting confused by your indentation. I think I am still parsing
the `x` definition. Is this supposed to be part of a definition after that? If
so, the problem may be a bit before the equals sign. I need all definitions to
be indented exactly the same amount, so the problem may be that this new
definition has too many spaces in front of it.
-}
"ExpectingLetBindingIndentation"

ExpectingIn ->
"ExpectingIn"

Expand Down Expand Up @@ -600,17 +667,55 @@ parseProblemToString problem =
"ExpectingPatternAnything"

ExpectingMaxThreeTuple ->
{- TODO
I only accept tuples with two or three items. This has too many:

39| x = (1, 2, 3, 4)
^^^^^^^^^^^^
I recommend switching to records. Each item will be named, and you can use the
`point.x` syntax to access them.

Note: Read <https://elm-lang.org/0.19.1/tuples> for more comprehensive advice on
working with large chunks of data in Elm.
-}
"ExpectingMaxThreeTuple"

ExpectingExpression ->
{- TODO
I am partway through parsing some parentheses, but I got stuck here:

39| x = ( )
^
I was expecting to see an expression like 42 or "hello". Once there is something
there, I can probably give a more specific hint!

Note: This can also happen if run into reserved words like `let` or `as`
unexpectedly. Or if I run into operators in unexpected spots. Point is, there
are a couple ways I can get confused and give sort of weird advice!
-}
"ExpectingExpression"

ExpectingTypeName ->
"ExpectingTypeName"

ExpectingNewlineAfterTypeAnnotation ->
"ExpectingNewlineAfterTypeAnnotation"

ExpectingTypeAnnotationDefinition ->
"ExpectingTypeAnnotationDefinition"

ExpectingNonSpaceAfterTypeAnnotationNewlines ->
"ExpectingNonSpaceAfterTypeAnnotationNewlines"

ExpectingSingleLineCommentStart ->
"ExpectingSingleLineCommentStart"

ExpectingMultiLineCommentStart ->
"ExpectingMultiLineCommentStart"

ExpectingMultiLineCommentEnd ->
"ExpectingMultiLineCommentEnd"

InvalidTab ->
"InvalidTab"

Expand Down
42 changes: 41 additions & 1 deletion src/Elm/Data/Binding.elm
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
module Elm.Data.Binding exposing (Binding, combine, map)
module Elm.Data.Binding exposing
( Binding, combine, map
, Commented, fromCommented, mapCommented
)

{-| Binding in the `let...in` expression.

Expand All @@ -14,9 +17,12 @@ module Elm.Data.Binding exposing (Binding, combine, map)
contains two bindings: `myNumber` and `answer`.

@docs Binding, combine, map
@docs Commented, fromCommented, mapCommented

-}

import Elm.Data.Comment exposing (Comment)


{-| -}
type alias Binding expr =
Expand Down Expand Up @@ -51,3 +57,37 @@ combine { name, body } =
}
)
body


{-| Binding with comments:

x {- commentsAfterName -} = {- commentsBeforeBody -} 2

-}
type alias Commented expr =
-- TODO type annotation for the let...in binding
{ name : String
, commentsAfterName : List Comment
, commentsBeforeBody : List Comment
, body : expr
}


{-| Create a [Binding](#Binding) from a [Commented](#Commented).
-}
fromCommented : Commented e -> Binding e
fromCommented { name, body } =
{ name = name
, body = body
}


{-| Apply a function to the expression inside the commented binding.
-}
mapCommented : (e1 -> e2) -> Commented e1 -> Commented e2
mapCommented fn { name, commentsAfterName, commentsBeforeBody, body } =
{ name = name
, commentsAfterName = commentsAfterName
, commentsBeforeBody = commentsBeforeBody
, body = fn body
}
19 changes: 19 additions & 0 deletions src/Elm/Data/Comment.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module Elm.Data.Comment exposing (Comment, CommentType(..))

import Elm.Data.Located exposing (Located)


{-| Comment information

@docs Comment, CommentType

-}
type alias Comment =
{ content : Located String
, type_ : CommentType
}


type CommentType
= SingleLine
| MultiLine
Loading