Skip to content
Merged
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
348 changes: 244 additions & 104 deletions examples/ast/jbeam/fender.hs

Large diffs are not rendered by default.

576 changes: 398 additions & 178 deletions examples/ast/jbeam/frame.hs

Large diffs are not rendered by default.

582 changes: 402 additions & 180 deletions examples/ast/jbeam/suspension.hs

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src-extra/transformation/JbeamEdit/Transformation.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import Data.Bool (bool)
import Data.Foldable.Extra (notNull)
import Data.Function (on)
import Data.List (foldl', partition)

Check warning on line 7 in src-extra/transformation/JbeamEdit/Transformation.hs

View workflow job for this annotation

GitHub Actions / Build and test with Cabal (GHC latest) on ubuntu-latest

The import of ‘foldl'’ from module ‘Data.List’ is redundant

Check warning on line 7 in src-extra/transformation/JbeamEdit/Transformation.hs

View workflow job for this annotation

GitHub Actions / Build and test with Cabal (GHC latest) on windows-latest

The import of ‘foldl'’ from module ‘Data.List’ is redundant

Check warning on line 7 in src-extra/transformation/JbeamEdit/Transformation.hs

View workflow job for this annotation

GitHub Actions / Build for release for 9.10.3 (experimental)

The import of ‘foldl'’ from module ‘Data.List’ is redundant
import Data.List.NonEmpty (NonEmpty)
import Data.List.NonEmpty qualified as NE
import Data.Map (Map)
Expand Down Expand Up @@ -290,9 +290,9 @@
vertexArray :: Node
vertexArray =
let name = String (vName vertex)
x = Number (vX vertex)
y = Number (vY vertex)
z = Number (vZ vertex)
x = Number (DecimalValue (vX vertex))
y = Number (DecimalValue (vY vertex))
z = Number (DecimalValue (vZ vertex))
possiblyMeta = concatMap (pure . Object) (vMeta vertex)
in Array . V.fromList $ [name, x, y, z] ++ possiblyMeta
in ( map Comment preComments
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import Data.Map (Map)
import Data.Map qualified as M
import Data.Map.Ordered (OMap)
import Data.Maybe (isJust, isNothing, mapMaybe)
import Data.Scientific (Scientific)
import Data.Set (Set)
import Data.Set qualified as S
import Data.Text (Text)
Expand All @@ -34,16 +35,24 @@ import JbeamEdit.Transformation.Types
verticesQuery :: NP.NodePath
verticesQuery = fromList [NP.ObjectIndex 0, NP.ObjectKey "nodes"]

nodeScientific :: Node -> Maybe Scientific
nodeScientific (Number nv) = Just (numberValueToScientific nv)
nodeScientific _ = Nothing

newVertex :: Node -> Maybe Vertex
newVertex (Array ns) = f . V.toList $ ns
where
f [String name, Number x, Number y, Number z, Object m] =
Just (Vertex {vName = name, vX = x, vY = y, vZ = z, vMeta = Just m})
f [String name, Number x, Number y, Number z] =
Just (Vertex {vName = name, vX = x, vY = y, vZ = z, vMeta = Nothing})
f _ = Nothing
newVertex (Array ns) = case V.toList ns of
[String name, n1, n2, n3] -> mkVertex name n1 n2 n3 Nothing
[String name, n1, n2, n3, Object m] -> mkVertex name n1 n2 n3 (Just m)
_ -> Nothing
newVertex _ = Nothing

mkVertex :: Text -> Node -> Node -> Node -> Maybe Object -> Maybe Vertex
mkVertex name n1 n2 n3 meta = do
x <- nodeScientific n1
y <- nodeScientific n2
z <- nodeScientific n3
pure Vertex {vName = name, vX = x, vY = y, vZ = z, vMeta = meta}

isNonVertex :: Node -> Bool
isNonVertex = isNothing . newVertex

Expand Down
13 changes: 12 additions & 1 deletion src/JbeamEdit/Core/Node.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ module JbeamEdit.Core.Node (
isComplexNode,
extractPreviousAssocCmt,
possiblyChildren,
numberValueToScientific,
Node (..),
NumberValue (..),
InternalComment (..),
AssociationDirection (..),
Object,
Expand Down Expand Up @@ -60,12 +62,17 @@ Text is yet a another string type in Haskell which is good fit when doing append
I comptemplated using something like [OMap](https://hackage.haskell.org/package/ordered-containers-0.2.4/docs/Data-Map-Ordered.html) for the Object but then I realized that I do not only need support pairs of keys and values for the Object case, I also need to support the Object having Comments as direct children.
The parser is currently written using attoaparsec but I are considering to migrate to Megaparsec since Megaparsec has better support implementing error messages which can be given to the end user.
-}
data NumberValue
= IntValue Integer
| DecimalValue Scientific
deriving (Eq, Ord, Read, Show)

data Node
= Array Array
| Object Object
| ObjectKey ObjectKey
| String Text
| Number Scientific
| Number NumberValue
| Bool Bool
| Comment InternalComment
| Null
Expand Down Expand Up @@ -105,6 +112,10 @@ isNumberNode :: Node -> Bool
isNumberNode (Number _) = True
isNumberNode _ = False

numberValueToScientific :: NumberValue -> Scientific
numberValueToScientific (IntValue n) = fromIntegral n
numberValueToScientific (DecimalValue n) = n

isSinglelineComment :: Node -> Bool
isSinglelineComment (Comment (InternalComment _ False _ _)) = True
isSinglelineComment _ = False
Expand Down
8 changes: 5 additions & 3 deletions src/JbeamEdit/Formatting.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import Data.Vector qualified as V
import JbeamEdit.Core.Node (
InternalComment (..),
Node (..),
NumberValue (..),
expectArray,
extractPreviousAssocCmt,
isCommentNode,
Expand Down Expand Up @@ -238,9 +239,9 @@ doFormatNode rs cursor state nodes =
autoPadEnabled = lookupRule AutoPad exactProps == Just True

complexChildren =
(lookupRule ForceComplexNewLine prefixProps == Just True)
lookupRule ForceComplexNewLine prefixProps == Just True
|| any (liftA2 (||) isSinglelineComment isComplexNode) nodes
&& (lookupRule NoComplexNewLine prefixProps /= Just True)
&& lookupRule NoComplexNewLine prefixProps /= Just True

(colWidths, formattedCache, headerWasExtracted) =
maxColumnLengthsWithCache rs cursor nodes
Expand Down Expand Up @@ -286,7 +287,8 @@ formatComment (InternalComment {cMultiline = True, cText = c}) =

formatScalarNode :: Node -> Text
formatScalarNode (String s) = T.concat ["\"", s, "\""]
formatScalarNode (Number n) = T.pack (formatScientific Fixed Nothing n)
formatScalarNode (Number (IntValue n)) = T.pack (show n)
formatScalarNode (Number (DecimalValue n)) = T.pack (formatScientific Fixed Nothing n)
formatScalarNode (Bool True) = "true"
formatScalarNode (Bool _) = "false"
formatScalarNode Null = "null"
Expand Down
30 changes: 23 additions & 7 deletions src/JbeamEdit/Parsing/Jbeam.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ import JbeamEdit.Core.Node (
AssociationDirection (..),
InternalComment (..),
Node (..),
NumberValue (..),
)
import JbeamEdit.Parsing.Common
import Text.Megaparsec ((<?>), (<|>))
import Text.Megaparsec qualified as MP
import Text.Megaparsec.Byte qualified as B
import Text.Megaparsec.Byte.Lexer qualified as L (scientific)
import Text.Megaparsec.Byte.Lexer qualified as L (decimal, scientific)
import Text.Megaparsec.Char qualified as C

data ParseState = ParseState
Expand Down Expand Up @@ -66,13 +67,18 @@ separatorParser = do
---
--- selectors for numbers, comments, strings and bools
---
numberParser :: JbeamParser Node
numberParser = do

numberParser
:: Num b
=> (b -> Node)
-> JbeamParser b
-> JbeamParser Node
numberParser c p = do
char <- MP.lookAhead B.asciiChar
Number
c
<$> bool
L.scientific
(negate <$> (byteChar '-' *> L.scientific))
p
(negate <$> (byteChar '-' *> p))
(char == toWord8 '-')

associationDirection :: ParseState -> AssociationDirection
Expand Down Expand Up @@ -132,10 +138,20 @@ stringParser = parseWord8s String string
emptyString = C.string "\"\"" >> pure []
string = emptyString <|> validString

intDecimalParser :: JbeamParser Integer
intDecimalParser =
L.decimal <* MP.notFollowedBy (byteChar '.' <|> byteChar 'e' <|> byteChar 'E')

scalarParser :: JbeamParser Node
scalarParser =
tryScalarParsers
[stringParser, commentParser, numberParser, boolParser, nullParser]
[ stringParser
, commentParser
, numberParser (Number . IntValue) intDecimalParser
, numberParser (Number . DecimalValue) L.scientific
, boolParser
, nullParser
]
where
tryScalarParsers = MP.try . tryParsers . map MP.hidden

Expand Down
22 changes: 13 additions & 9 deletions test/Core/NodeSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,42 @@ spec = do
( do
isCommentNode (Comment (InternalComment "test" False NextNode False))
`shouldBe` True
isCommentNode (Number 123) `shouldBe` False
isCommentNode (Number (IntValue 123)) `shouldBe` False
)
describe "isObjectNode" . works $
( do
isObjectNode (Object (V.singleton (ObjectKey (String "test", Number 1))))
isObjectNode
(Object (V.singleton (ObjectKey (String "test", Number (IntValue 1)))))
`shouldBe` True
isObjectNode (Number 123) `shouldBe` False
isObjectNode (Number (IntValue 123)) `shouldBe` False
)
describe "isStringNode" . works $
( do
isStringNode (String "test") `shouldBe` True
isStringNode (Number 123) `shouldBe` False
isStringNode (Number (IntValue 123)) `shouldBe` False
)
describe "isNumberNode" . works $
( do
isNumberNode (Number 123) `shouldBe` True
isNumberNode (Number (IntValue 123)) `shouldBe` True
isNumberNode (String "123") `shouldBe` False
)
describe "isComplexNode" . works $
( do
isComplexNode (Number 123) `shouldBe` False
isComplexNode (Number (IntValue 123)) `shouldBe` False
isComplexNode
( Object
(V.singleton (ObjectKey (String "test", Number 1)))
(V.singleton (ObjectKey (String "test", Number (IntValue 1))))
)
`shouldBe` False
isComplexNode
( Object
( V.fromList
[ObjectKey (String "test", Number 1), ObjectKey (String "test", Number 1)]
[ ObjectKey (String "test", Number (IntValue 1))
, ObjectKey (String "test", Number (IntValue 1))
]
)
)
`shouldBe` True
isComplexNode (Array (V.fromList [String "test", Number 1])) `shouldBe` True
isComplexNode (Array (V.fromList [String "test", Number (IntValue 1)]))
`shouldBe` True
)
2 changes: 1 addition & 1 deletion test/Formatting/RulesSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ spec = do
lookupKey "NotAKey" allProperties `shouldBe` Nothing

describe "applyPadLogic" $ do
let fakeNode = Number 123
let fakeNode = Number (DecimalValue 123.0)
ruleSet =
fromList
[ (SomeKey PadAmount, SomeProperty PadAmount 7)
Expand Down
19 changes: 11 additions & 8 deletions test/FormattingSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import System.FilePath (takeBaseName, (</>))

numberSpec :: [(String, Node)]
numberSpec =
[ ("123", Number 123)
, ("123.123", Number 123.123)
, ("-123", Number (-123))
, ("-123.123", Number (-123.123))
, ("0", Number 0.0)
[ ("123", Number (IntValue 123))
, ("123.123", Number (DecimalValue 123.123))
, ("-123", Number (IntValue (-123)))
, ("-123.123", Number (DecimalValue (-123.123)))
, ("0", Number (IntValue 0))
]

stringSpec :: [(String, Node)]
Expand All @@ -37,7 +37,10 @@ singlelineCommentSpec = [("// test", Comment (InternalComment "test" False NextN

arraySpec :: [(String, Node)]
arraySpec =
[ ("[1, 2, 3]", Array (fromList [Number 1, Number 2, Number 3]))
[
( "[1, 2, 3]"
, Array (fromList [Number (IntValue 1), Number (IntValue 2), Number (IntValue 3)])
)
]

objectSpec :: [(String, Node)]
Expand All @@ -46,8 +49,8 @@ objectSpec =
( "{\"test\" : 1, \"test2\" : 2}"
, Object
( fromList
[ ObjectKey (String "test", Number 1)
, ObjectKey (String "test2", Number 2)
[ ObjectKey (String "test", Number (IntValue 1))
, ObjectKey (String "test2", Number (IntValue 2))
]
)
)
Expand Down
41 changes: 24 additions & 17 deletions test/Parsing/JbeamSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,18 @@ import JbeamEdit.Parsing.Jbeam
import SpecHelper
import Test.Hspec.Megaparsec
import Text.Megaparsec qualified as MP
import Text.Megaparsec.Byte.Lexer qualified as L (scientific)

numberSpec :: [(String, Node)]
numberSpec =
[ ("123", Number 123)
, ("123.123", Number 123.123)
, ("-123", Number (-123))
, ("-123.123", Number (-123.123))
, ("0", Number 0)
, ("0.0", Number 0.0)
, ("-0", Number 0)
, ("-0.0", Number 0.0)
[ ("123", Number (IntValue 123))
, ("123.123", Number (DecimalValue 123.123))
, ("-123", Number (IntValue (-123)))
, ("-123.123", Number (DecimalValue (-123.123)))
, ("0", Number (IntValue 0))
, ("0.0", Number (DecimalValue 0.0))
, ("-0", Number (IntValue 0))
, ("-0.0", Number (DecimalValue 0.0))
]

stringSpec :: [(String, Node)]
Expand Down Expand Up @@ -93,8 +94,14 @@ singlelineCommentSpec =

arraySpec :: [(String, Node)]
arraySpec =
[ ("[1,2,3]", Array (fromList [Number 1, Number 2, Number 3]))
, ("[1\n 2\n 3]", Array (fromList [Number 1, Number 2, Number 3]))
[
( "[1,2,3]"
, Array (fromList [Number (IntValue 1), Number (IntValue 2), Number (IntValue 3)])
)
,
( "[1\n 2\n 3]"
, Array (fromList [Number (IntValue 1), Number (IntValue 2), Number (IntValue 3)])
)
]

objectSpec :: [(String, Node)]
Expand All @@ -114,26 +121,26 @@ objectSpec =
, Object
( fromList
[ Comment (InternalComment "test" False NextNode False)
, ObjectKey (String "test", Number 1)
, ObjectKey (String "test2", Number 2)
, ObjectKey (String "test", Number (IntValue 1))
, ObjectKey (String "test2", Number (IntValue 2))
]
)
)
,
( "{\"test\" : 1, \"test2\" : 2}"
, Object
( fromList
[ ObjectKey (String "test", Number 1)
, ObjectKey (String "test2", Number 2)
[ ObjectKey (String "test", Number (IntValue 1))
, ObjectKey (String "test2", Number (IntValue 2))
]
)
)
,
( "{\"test\" : 1\n \"test2\" : 2}"
, Object
( fromList
[ ObjectKey (String "test", Number 1)
, ObjectKey (String "test2", Number 2)
[ ObjectKey (String "test", Number (IntValue 1))
, ObjectKey (String "test2", Number (IntValue 2))
]
)
)
Expand All @@ -152,7 +159,7 @@ invalidNumberSpec =
describe
"should fail parsing Number when there is space after the negative sign"
. works
$ parseNodesState numberParser "- 0.3"
$ parseNodesState (numberParser (Number . DecimalValue) L.scientific) "- 0.3"
`shouldFailWith` err 1 (utok (toWord8 ' ') <> elabel "digit")

topNodeSpec :: FilePath -> FilePath -> Spec
Expand Down
Loading