Skip to content

Commit 9496df9

Browse files
committed
Rejig/minimize imports, paper cuts
... and a bunch of pre-release bikeshedding.
1 parent ba44e8d commit 9496df9

24 files changed

+291
-208
lines changed

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Parser and pretty-printer for Rust [![Build Status][4]][5] [![Windows build status][7]][8]
22

33
`language-rust` aspires to efficiently and accurately parse and pretty-print the [Rust language][0].
4-
The underlying AST structures are also intended to be as similar as possible to the `libsyntax` AST
5-
`rustc` uses itself. When `language-rust` and `rustc` have diverging AST, the divergence should be
6-
detailed in the documentation.
4+
The underlying AST structures are also intended to be as similar as possible to the [`libsyntax` AST
5+
`rustc`][10] uses itself. When `language-rust` and `rustc` have diverging AST, the divergence should
6+
be detailed in the documentation.
77

88
A typical use looks like:
99

@@ -15,7 +15,7 @@ A typical use looks like:
1515
>>> import Language.Rust.Parser
1616
>>> let inp = inputStreamFromString "fn main () { println!(\"Hello world!\"); }"
1717
inp :: InputStream
18-
>>> Right sourceFile = parse @(SourceFile Span) inp
18+
>>> let Right sourceFile = parse @(SourceFile Span) inp
1919
sourceFile :: SourceFile Span
2020

2121
>>> -- Sample use of the pretty-printer
@@ -46,7 +46,9 @@ With the [Stack][1] tool installed, run
4646
stack build
4747

4848
The second command is responsible for pulling in all of the dependencies (including executable
49-
tools like [Alex][2], [Happy][3], and GHC itself) and then compiling everything.
49+
tools like [Alex][2], [Happy][3], and GHC itself) and then compiling everything. If Stack complains
50+
about the version of Happy installed, you can explicitly install a recent one with `stack install
51+
happy-1.19.8`.
5052

5153
## Evolution of Rust
5254

@@ -85,3 +87,4 @@ pretty-printing.
8587
[7]: https://ci.appveyor.com/api/projects/status/um8dxklqmubvn091/branch/master?svg=true
8688
[8]: https://ci.appveyor.com/project/harpocrates/language-rust/branch/master
8789
[9]: https://github.com/harpocrates/language-rust/issues
90+
[10]: https://github.com/rust-lang/rust/blob/master/src/libsyntax/ast.rs

get-rust-sources.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
#!/bin/sh
22

3+
# Exit if anything goes wrong
4+
set -e
5+
36
# Usage info
47
if ! [ $# = 1 ]
58
then

language-rust.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ library
5151
Language.Rust.Pretty
5252
Language.Rust.Pretty.Internal
5353
Language.Rust.Data.Position
54+
Language.Rust.Data.Ident
5455
Language.Rust.Data.InputStream
5556
if flag(enableQuasiquotes)
5657
exposed-modules: Language.Rust.Quote
@@ -62,7 +63,6 @@ library
6263
Language.Rust.Pretty.Literals
6364
Language.Rust.Pretty.Util
6465
Language.Rust.Syntax.AST
65-
Language.Rust.Syntax.Ident
6666
Language.Rust.Syntax.Token
6767

6868
other-extensions: FlexibleContexts

src/Language/Rust/Syntax/Ident.hs renamed to src/Language/Rust/Data/Ident.hs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{-|
2-
Module : Language.Rust.Syntax.Ident
2+
Module : Language.Rust.Data.Ident
33
Description : Identifiers
44
Copyright : (c) Alec Theriault, 2017
55
License : BSD-style
@@ -9,19 +9,22 @@ Portability : portable
99
1010
Data structure behind identifiers.
1111
-}
12-
{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, DeriveAnyClass #-}
12+
{-# LANGUAGE DeriveDataTypeable #-}
13+
{-# LANGUAGE DeriveGeneric #-}
14+
{-# LANGUAGE DeriveAnyClass #-}
1315

14-
module Language.Rust.Syntax.Ident (Ident(..), mkIdent, Name) where
16+
module Language.Rust.Data.Ident (Ident(..), mkIdent, Name) where
1517

16-
import GHC.Generics (Generic)
17-
import Data.Data (Data)
18-
import Data.Typeable (Typeable)
19-
import Control.DeepSeq (NFData)
18+
import GHC.Generics ( Generic )
2019

21-
import Data.List (foldl')
22-
import Data.Char (ord)
23-
import Data.String (IsString(..))
24-
import Data.Semigroup
20+
import Control.DeepSeq ( NFData )
21+
import Data.Data ( Data )
22+
import Data.Typeable ( Typeable )
23+
24+
import Data.List ( foldl' )
25+
import Data.Char ( ord )
26+
import Data.String ( IsString(..) )
27+
import Data.Semigroup ( Semigroup(..) )
2528

2629
-- | An identifier
2730
data Ident

src/Language/Rust/Data/InputStream.hs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ Maintainer : alec.theriault@gmail.com
77
Stability : experimental
88
Portability : portable
99
10-
These are the only functions that need to be implemented in order to use the parser. Whether this wraps 'ByteString' or 'String' depends on whether the @useByteStrings@ option is on or not (it is by default). Using 'ByteString' means better handling of weird characters ('takeByte' fails badly if you try to take a byte that doesn't fall on a character boundary), but it means incurring a dependency on the [utf8-string](https://hackage.haskell.org/package/utf8-string) package.
10+
These are the only functions that need to be implemented in order to use the parser. Whether this
11+
wraps 'ByteString' or 'String' depends on whether the @useByteStrings@ option is on or not (it is
12+
by default). Using 'ByteString' means better handling of weird characters ('takeByte' fails badly
13+
if you try to take a byte that doesn't fall on a character boundary), but it means incurring a
14+
dependency on the [utf8-string](https://hackage.haskell.org/package/utf8-string) package.
1115
-}
1216
{-# LANGUAGE CPP #-}
1317

@@ -26,12 +30,12 @@ module Language.Rust.Data.InputStream (
2630
inputStreamToString,
2731
takeByte,
2832
takeChar,
29-
takeChars,
33+
peekChars,
3034
) where
3135

32-
import Data.Word (Word8)
33-
import Data.Coerce (coerce)
34-
import Data.String (IsString(..))
36+
import Data.Word ( Word8 )
37+
import Data.Coerce ( coerce )
38+
import Data.String ( IsString(..) )
3539
import System.IO
3640

3741
#ifdef USE_BYTESTRING
@@ -43,16 +47,19 @@ import qualified Data.Char as Char
4347

4448
-- | Read a file into an 'InputStream'
4549
readInputStream :: FilePath -> IO InputStream
50+
{-# INLINE readInputStream #-}
4651

4752
-- | Read an 'InputStream' from a 'Handle'
4853
hReadInputStream :: Handle -> IO InputStream
54+
{-# INLINE hReadInputStream #-}
4955

5056
-- | Convert 'InputStream' to 'String'
5157
inputStreamToString :: InputStream -> String
5258
{-# INLINE inputStreamToString #-}
5359

5460
-- | Convert a 'String' to an 'InputStream'
5561
inputStreamFromString :: String -> InputStream
62+
{-# INLINE inputStreamFromString #-}
5663

5764
instance IsString InputStream where fromString = inputStreamFromString
5865

@@ -70,12 +77,13 @@ takeChar :: InputStream -> (Char, InputStream)
7077
inputStreamEmpty :: InputStream -> Bool
7178
{-# INLINE inputStreamEmpty #-}
7279

73-
-- | Returns the first @n@characters of the given input stream, without removing them.
74-
takeChars :: Int -> InputStream -> String
75-
{-# INLINE takeChars #-}
80+
-- | Returns the first @n@ characters of the given input stream, without removing them.
81+
peekChars :: Int -> InputStream -> String
82+
{-# INLINE peekChars #-}
7683

7784
-- | Returns the number of text lines in the given 'InputStream'
7885
countLines :: InputStream -> Int
86+
{-# INLINE countLines #-}
7987

8088
#ifdef USE_BYTESTRING
8189

@@ -84,7 +92,7 @@ newtype InputStream = IS BS.ByteString
8492
takeByte bs = (BS.head (coerce bs), coerce (BS.tail (coerce bs)))
8593
takeChar bs = maybe (error "takeChar: no char left") coerce (BE.uncons (coerce bs))
8694
inputStreamEmpty = BS.null . coerce
87-
takeChars n = BE.toString . BE.take n . coerce
95+
peekChars n = BE.toString . BE.take n . coerce
8896
readInputStream f = coerce <$> BS.readFile f
8997
hReadInputStream h = coerce <$> BS.hGetContents h
9098
inputStreamToString = BE.toString . coerce
@@ -100,7 +108,7 @@ takeByte (IS ~(c:str))
100108
| otherwise = error "takeByte: not a latin-1 character"
101109
takeChar (IS ~(c:str)) = (c, IS str)
102110
inputStreamEmpty (IS str) = null str
103-
takeChars n (IS str) = take n str
111+
peekChars n (IS str) = take n str
104112
readInputStream f = IS <$> readFile f
105113
hReadInputStream h = IS <$> hGetContents h
106114
inputStreamToString = coerce

src/Language/Rust/Data/Position.hs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Copyright : (c) Alec Theriault, 2017
55
License : BSD-style
66
Maintainer : alec.theriault@gmail.com
77
Stability : experimental
8-
Portability : portable
8+
Portability : GHC
99
1010
Everything to do with describing a position or a contiguous region in a file.
1111
-}
@@ -35,15 +35,15 @@ module Language.Rust.Data.Position (
3535
Located(..),
3636
) where
3737

38-
import GHC.Generics (Generic)
38+
import GHC.Generics ( Generic )
3939

40-
import Data.Data (Data)
41-
import Data.Typeable (Typeable)
42-
import Control.DeepSeq (NFData)
40+
import Control.DeepSeq ( NFData )
41+
import Data.Data ( Data )
42+
import Data.Typeable ( Typeable )
4343

44-
import Data.List.NonEmpty (NonEmpty(..))
45-
import Data.Monoid (Monoid(..))
46-
import Data.Semigroup (Semigroup(..))
44+
import Data.List.NonEmpty ( NonEmpty(..) )
45+
import Data.Monoid ( Monoid(..) )
46+
import Data.Semigroup ( Semigroup(..) )
4747

4848

4949
-- | A position in a source file. The row and column information is kept only for its convenience

src/Language/Rust/Parser.hs

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ Copyright : (c) Alec Theriault, 2017
55
License : BSD-style
66
Maintainer : alec.theriault@gmail.com
77
Stability : experimental
8-
Portability : portable
8+
Portability : GHC
99
1010
Selecting the right parser may require adding an annotation to avoid an 'Ambiguous type variable'
1111
error.
@@ -19,30 +19,52 @@ inp :: InputStream
1919
sourceFile :: SourceFile Span
2020
2121
-}
22-
{-# LANGUAGE FlexibleInstances, DeriveDataTypeable #-}
22+
{-# LANGUAGE FlexibleInstances #-}
23+
{-# LANGUAGE DeriveDataTypeable #-}
2324

2425
module Language.Rust.Parser (
2526
-- * Parsing
26-
parse, parse', readSourceFile, readTokens, Parse(..), P, execParser, execParserTokens, initPos, Span,
27+
parse,
28+
parse',
29+
readSourceFile,
30+
readTokens,
31+
Parse(..),
32+
P,
33+
execParser,
34+
execParserTokens,
35+
initPos,
36+
Span,
37+
2738
-- * Lexing
28-
lexToken, lexNonSpace, lexTokens, translateLit,
39+
lexToken,
40+
lexNonSpace,
41+
lexTokens,
42+
translateLit,
43+
2944
-- * Input stream
30-
readInputStream, inputStreamToString, inputStreamFromString,
45+
readInputStream,
46+
inputStreamToString,
47+
inputStreamFromString,
48+
3149
-- * Error reporting
32-
lexicalError, parseError, ParseFail,
50+
lexicalError,
51+
parseError,
52+
ParseFail,
3353
) where
3454

3555
import Language.Rust.Syntax
36-
import Language.Rust.Data.InputStream (InputStream, readInputStream, inputStreamToString, inputStreamFromString)
37-
import Language.Rust.Data.Position (Position, Span, Spanned, initPos, prettyPosition)
56+
57+
import Language.Rust.Data.InputStream ( InputStream, readInputStream, inputStreamToString, inputStreamFromString )
58+
import Language.Rust.Data.Position ( Position, Span, Spanned, initPos, prettyPosition )
59+
3860
import Language.Rust.Parser.Internal
39-
import Language.Rust.Parser.Lexer (lexToken, lexNonSpace, lexTokens, lexicalError)
40-
import Language.Rust.Parser.Literals (translateLit)
41-
import Language.Rust.Parser.ParseMonad (P, execParser, parseError, pushToken)
61+
import Language.Rust.Parser.Lexer ( lexToken, lexNonSpace, lexTokens, lexicalError )
62+
import Language.Rust.Parser.Literals ( translateLit )
63+
import Language.Rust.Parser.ParseMonad ( P, execParser, parseError, pushToken )
4264

43-
import Data.Typeable (Typeable)
44-
import Control.Exception (Exception, throw)
45-
import Data.Foldable (traverse_)
65+
import Control.Exception ( Exception, throw )
66+
import Data.Foldable ( traverse_ )
67+
import Data.Typeable ( Typeable )
4668

4769
-- | Parse something from an input stream (it is assumed the initial position is 'initPos')
4870
parse :: Parse a => InputStream -> Either (Position,String) a

src/Language/Rust/Parser/Internal.y

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Copyright : (c) Alec Theriault, 2017
66
License : BSD-style
77
Maintainer : alec.theriault@gmail.com
88
Stability : experimental
9-
Portability : portable
9+
Portability : GHC
1010

1111
The parsers in this file are all re-exported to 'Language.Rust.Parser' via the 'Parse' class. The
1212
parsers are based off of:
@@ -24,27 +24,47 @@ To get information about transition states and such, run
2424
[2]: https://doc.rust-lang.org/grammar.html
2525
-}
2626
{-# OPTIONS_HADDOCK hide, not-home #-}
27-
{-# LANGUAGE OverloadedStrings, OverloadedLists, PartialTypeSignatures #-}
27+
{-# LANGUAGE OverloadedStrings #-}
28+
{-# LANGUAGE OverloadedLists #-}
29+
{-# LANGUAGE PartialTypeSignatures #-}
2830

2931
module Language.Rust.Parser.Internal (
3032
-- * Parsers
31-
parseLit, parseAttr, parseTy, parsePat, parseStmt, parseExpr, parseItem, parseSourceFile,
32-
parseBlock, parseImplItem, parseTraitItem, parseTt, parseTokenStream, parseTyParam,
33-
parseGenerics, parseWhereClause, parseLifetimeDef,
33+
parseAttr,
34+
parseBlock,
35+
parseExpr,
36+
parseGenerics,
37+
parseImplItem,
38+
parseItem,
39+
parseLifetimeDef,
40+
parseLit,
41+
parsePat,
42+
parseSourceFile,
43+
parseStmt,
44+
parseTokenStream,
45+
parseTraitItem,
46+
parseTt,
47+
parseTy,
48+
parseTyParam,
49+
parseWhereClause,
3450
) where
3551

3652
import Language.Rust.Syntax
53+
54+
import Language.Rust.Data.Ident ( Ident(..), mkIdent )
3755
import Language.Rust.Data.Position
56+
3857
import Language.Rust.Parser.Lexer ( lexNonSpace, lexShebangLine )
3958
import Language.Rust.Parser.ParseMonad ( pushToken, getPosition, P, parseError )
4059
import Language.Rust.Parser.Literals ( translateLit )
4160
import Language.Rust.Parser.Reversed
4261

4362
import Data.Foldable ( toList )
4463
import Data.List ( (\\), isSubsequenceOf )
45-
import Text.Read ( readMaybe )
4664
import Data.Semigroup ( (<>) )
4765

66+
import Text.Read ( readMaybe )
67+
4868
import Data.List.NonEmpty ( NonEmpty(..), (<|) )
4969
import qualified Data.List.NonEmpty as N
5070
}

0 commit comments

Comments
 (0)