Skip to content

Commit 98d2081

Browse files
committed
Docs + saner 'Show' instances
* Removed "pretty" 'Show' instances in favour of derived ones and new 'Pretty' instances * Updated examples * Be consistent: pretty print, not pretty-print * Spelling + grammar
1 parent 33d0542 commit 98d2081

File tree

22 files changed

+228
-200
lines changed

22 files changed

+228
-200
lines changed

.travis.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ sudo: true
33

44
# Add new environments to the build here:
55
env:
6-
- GHCVER=7.10.3 CABALVER=1.22
6+
- GHCVER=7.10.3 CABALVER=1.22
77
- GHCVER=8.0.2 CABALVER=1.24
8-
- GHCVER=8.2.1 CABALVER=2.0
8+
- GHCVER=8.2.2 CABALVER=2.0
9+
- GHCVER=8.4.1 CABALVER=head
910
- GHCVER=head CABALVER=head
1011

1112
# Allow for develop branch to break
1213
matrix:
1314
allow_failures:
15+
- env: GHCVER=8.4.1 CABALVER=head
1416
- env: GHCVER=head CABALVER=head
1517

1618
# Manually install ghc and cabal

ChangeLog.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# Revision history for language-rust
22

3-
## 0.1.0.0 -- YYYY-mm-dd
3+
## 0.1.0.26 -- 2018-03-01
44

5-
* First version. Released on an unsuspecting world.
65
* Parser module (using Alex and Happy)
7-
* Pretty-printing module (using Wadler's prettier)
6+
* Pretty printing module
87
* Resolving module for validating ASTs
98
* Unit testsuite
109
* Difference testsuite
11-
* Benchmarks
10+
* Allocation benchmarks
11+
* Timing benchmarks

README.md

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

3-
`language-rust` aspires to efficiently and accurately parse and pretty-print the [Rust language][0].
3+
`language-rust` aspires to efficiently and accurately parse and pretty print the [Rust language][0].
44
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.
5+
that `rustc`][10] itself uses.
76

87
A typical use looks like:
98

@@ -18,7 +17,7 @@ inp :: InputStream
1817
>>> let sourceFile = parse' @(SourceFile Span) inp
1918
sourceFile :: SourceFile Span
2019

21-
>>> -- Sample use of the pretty-printer
20+
>>> -- Sample use of the pretty printer
2221
>>> import Language.Rust.Pretty
2322
>>> pretty' sourceFile
2423
fn main() {
@@ -52,8 +51,10 @@ happy-1.19.8`.
5251

5352
## Evolution of Rust
5453

55-
As Rust evolves, so will `language-rust`. We will make a best effort to support unstable features
56-
from nightly as they come out, but in general will only target compatibility with stable.
54+
As Rust evolves, so will `language-rust`. A best effort will be made to support unstable features
55+
from nightly as they come out, but only compatibility with stable is guaranteed. The last component
56+
of the version number indicates the nightly Rust compiler version against which tests were run. For
57+
example, `0.1.0.26` is tested against `rustc 1.26.0-nightly`.
5758

5859
## Bugs
5960

@@ -62,7 +63,7 @@ Please report any bugs to the [github issue tracker][9].
6263
### Parser
6364

6465
Any difference between what is accepted by the `rustc` parser and the `language-rust` parser
65-
indicates
66+
indicates one of
6667

6768
* a bug in `language-rust` (this is almost always the case)
6869
* a bug in `rustc`
@@ -71,11 +72,11 @@ indicates
7172
If the AST/parser of `rustc` changes, the `rustc-tests` test suite should start failing - it
7273
compares the JSON AST debug output of `rustc` to our parsed AST.
7374

74-
### Pretty-printer
75+
### Pretty printer
7576

76-
For the pretty-printer, bugs are a bit tougher to list exhaustively. Suggestions for better layout
77+
For the pretty printer, bugs are a bit tougher to list exhaustively. Suggestions for better layout
7778
algorithms are most welcome! The [`fmt-rfcs`][6] repo is loosely used as the reference for "correct"
78-
pretty-printing.
79+
pretty printing.
7980

8081
[0]: https://www.rust-lang.org/en-US/
8182
[1]: https://docs.haskellstack.org/en/stable/README/

language-rust.cabal

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name: language-rust
2-
version: 0.1.0.0
2+
version: 0.1.0.26
33

44
synopsis: Parsing and pretty printing of Rust code
5-
description: Language Rust is a well tested library for converting Rust source code into
6-
and out of abstract syntax trees.
5+
description: Language Rust is a library for the analysis of Rust code. It includes a
6+
complete, well tested parser and pretty printer.
77

88
homepage: https://github.com/harpocrates/language-rust
99
license: BSD3
@@ -48,6 +48,7 @@ library
4848
Language.Rust.Parser
4949
Language.Rust.Parser.ParseMonad
5050
Language.Rust.Parser.Lexer
51+
Language.Rust.Parser.Internal
5152
Language.Rust.Pretty
5253
Language.Rust.Pretty.Internal
5354
Language.Rust.Data.Position
@@ -56,8 +57,7 @@ library
5657
if flag(enableQuasiquotes)
5758
exposed-modules: Language.Rust.Quote
5859

59-
other-modules: Language.Rust.Parser.Internal
60-
Language.Rust.Parser.Literals
60+
other-modules: Language.Rust.Parser.Literals
6161
Language.Rust.Parser.Reversed
6262
Language.Rust.Pretty.Resolve
6363
Language.Rust.Pretty.Literals

src/Language/Rust/Data/Ident.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ data Ident
3232
, hash :: {-# UNPACK #-} !Int -- ^ hash for quick comparision
3333
} deriving (Data, Typeable, Generic, NFData)
3434

35+
-- | Shows the identifier as a string (for use with @-XOverloadedStrings@)
3536
instance Show Ident where
36-
show = name
37+
show = show . name
3738

3839
instance IsString Ident where
3940
fromString = mkIdent

src/Language/Rust/Data/InputStream.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ Stability : experimental
88
Portability : portable
99
1010
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' for plain old
11+
wraps 'BS.ByteString' or 'String' depends on whether the @useByteStrings@ option is on or not (it is
12+
by default). Using 'BS.ByteString' means better handling of weird characters ('takeByte' for plain
1313
'String' fails badly if you try to take a byte that doesn't fall on a character boundary), but it
1414
means incurring a dependency on the [utf8-string](https://hackage.haskell.org/package/utf8-string)
1515
package.

src/Language/Rust/Data/Position.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ data Position = Position {
5656
| NoPosition
5757
deriving (Eq, Ord, Data, Typeable, Generic, NFData)
5858

59-
-- | Field names are shown
59+
-- | Field names are not shown
6060
instance Show Position where
6161
showsPrec _ NoPosition = showString "NoPosition"
6262
showsPrec p (Position a r c) = showParen (p >= 11)

src/Language/Rust/Parser.hs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,18 @@ Portability : GHC
1010
Selecting the right parser may require adding an annotation or using @-XTypeApplications@ to avoid
1111
an "Ambiguous type variable" error.
1212
13-
Using 'Control.Monad.void' (as in the examples below) uses the fact that most AST nodes are
13+
Using 'Control.Monad.void' (as in the examples below) exploits the fact that most AST nodes are
1414
instances of 'Functor' to discard the 'Span' annotation that is attached to most parsed AST nodes.
1515
Conversely, if you wish to extract the 'Span' annotation, the 'Language.Rust.Syntax.AST.Located'
1616
typeclass provides a 'Language.Rust.Syntax.AST.spanOf' method.
1717
18+
The examples below assume the following GHCi flags and imports:
19+
20+
>>> :set -XTypeApplications -XOverloadedStrings
21+
>>> import Language.Rust.Syntax.AST
22+
>>> import Control.Monad ( void )
23+
>>> import System.IO
24+
1825
-}
1926
{-# LANGUAGE FlexibleInstances #-}
2027

@@ -65,11 +72,11 @@ import System.IO ( Handle )
6572

6673
-- | Parse something from an input stream (it is assumed the initial position is 'initPos').
6774
--
68-
-- >>> :set -XOverloadedStrings -XTypeApplications
6975
-- >>> fmap void $ parse @(Expr Span) "x + 1"
70-
-- Right (Binary [] AddOp (PathExpr [] Nothing (Path False [PathSegment x Nothing ()] ()) ())
71-
-- (Lit [] (Int Dec 1 ()) ())
76+
-- Right (Binary [] AddOp (PathExpr [] Nothing (Path False [PathSegment "x" Nothing ()] ()) ())
77+
-- (Lit [] (Int Dec 1 Unsuffixed ()) ())
7278
-- ())
79+
--
7380
-- >>> fmap void $ parse @(Expr Span) "x + "
7481
-- Left (parse failure at 1:4 (Syntax error: unexpected `<EOF>' (expected an expression)))
7582
--
@@ -80,12 +87,12 @@ parse is = execParser parser is initPos
8087
-- intended for situations in which you are already stuck catching exceptions - otherwise you should
8188
-- prefer 'parse'.
8289
--
83-
-- >>> :set -XOverloadedStrings -XTypeApplications
84-
-- >>> void $ parse @(Expr Span) "x + 1"
85-
-- Binary [] AddOp (PathExpr [] Nothing (Path False [PathSegment x Nothing ()] ()) ())
86-
-- (Lit [] (Int Dec 1 ()) ())
90+
-- >>> void $ parse' @(Expr Span) "x + 1"
91+
-- Binary [] AddOp (PathExpr [] Nothing (Path False [PathSegment "x" Nothing ()] ()) ())
92+
-- (Lit [] (Int Dec 1 Unsuffixed ()) ())
8793
-- ()
88-
-- >>> void $ parse @(Expr Span) "x + "
94+
--
95+
-- >>> void $ parse' @(Expr Span) "x + "
8996
-- *** Exception: parse failure at 1:4 (Syntax error: unexpected `<EOF>' (expected an expression))
9097
--
9198
parse' :: Parse a => InputStream -> a
@@ -100,7 +107,7 @@ execParserTokens p toks = execParser (pushTokens toks *> p) (inputStreamFromStri
100107
--
101108
-- >>> writeFile "empty_main.rs" "fn main() { }"
102109
-- >>> fmap void $ withFile "empty_main.rs" ReadMode readSourceFile
103-
-- SourceFile Nothing [] [Fn [] InheritedV main
110+
-- SourceFile Nothing [] [Fn [] InheritedV "main"
104111
-- (FnDecl [] Nothing False ())
105112
-- Normal NotConst Rust
106113
-- (Generics [] [] (WhereClause [] ()) ())

src/Language/Rust/Parser/Internal.y

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,23 @@ ty_param_bound_mod :: { TyParamBound Span }
704704
-- Sort of like parse_opt_abi() -- currently doesn't handle raw string ABI
705705
abi :: { Abi }
706706
: str {% case unspan $1 of
707-
(LiteralTok (StrTok s) Nothing) -> maybe (parseError $1 {- "invalid ABI" -}) pure (readMaybe s)
707+
LiteralTok (StrTok "cdecl") Nothing -> pure Cdecl
708+
LiteralTok (StrTok "stdcall") Nothing -> pure Stdcall
709+
LiteralTok (StrTok "fastcall") Nothing -> pure Fastcall
710+
LiteralTok (StrTok "vectorcall") Nothing -> pure Vectorcall
711+
LiteralTok (StrTok "aapcs") Nothing -> pure Aapcs
712+
LiteralTok (StrTok "win64") Nothing -> pure Win64
713+
LiteralTok (StrTok "sysv64") Nothing -> pure SysV64
714+
LiteralTok (StrTok "ptx-kernel") Nothing -> pure PtxKernel
715+
LiteralTok (StrTok "msp430-interrupt") Nothing -> pure Msp430Interrupt
716+
LiteralTok (StrTok "x86-interrupt") Nothing -> pure X86Interrupt
717+
LiteralTok (StrTok "Rust") Nothing -> pure Rust
718+
LiteralTok (StrTok "C") Nothing -> pure C
719+
LiteralTok (StrTok "system") Nothing -> pure System
720+
LiteralTok (StrTok "rust-intrinsic") Nothing -> pure RustIntrinsic
721+
LiteralTok (StrTok "rust-call") Nothing -> pure RustCall
722+
LiteralTok (StrTok "platform-intrinsic") Nothing -> pure PlatformIntrinsic
723+
LiteralTok (StrTok "unadjusted") Nothing -> pure Unadjusted
708724
_ -> parseError $1 {- "invalid ABI" -}
709725
}
710726
| {- empty -} { C }
@@ -1728,19 +1744,19 @@ parseTraitItem :: P (TraitItem Span)
17281744
-- | Parser for token trees.
17291745
parseTt :: P TokenTree
17301746

1731-
-- | Parser for token streams
1747+
-- | Parser for token streams.
17321748
parseTokenStream :: P TokenStream
17331749

1734-
-- | Parser for lifetime definitions
1750+
-- | Parser for lifetime definitions.
17351751
parseLifetimeDef :: P (LifetimeDef Span)
17361752

1737-
-- | Parser for a type parameter
1753+
-- | Parser for a type parameter.
17381754
parseTyParam :: P (TyParam Span)
17391755

1740-
-- | Parser for a where clause
1756+
-- | Parser for a where clause.
17411757
parseWhereClause :: P (WhereClause Span)
17421758

1743-
-- | Parser for generics (although 'WhereClause' is always empty here)
1759+
-- | Parser for generics (although 'WhereClause' is always empty here).
17441760
parseGenerics :: P (Generics Span)
17451761

17461762
-- | Generate a nice looking error message based on expected tokens

src/Language/Rust/Pretty.hs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ advantages over printing plain old strings:
3737
* /Annotations/: Depending on the backend you are using to render the 'Doc', annotations can
3838
determine colours, styling, links, etc.
3939
40+
The examples below assume the following GHCi flag and import:
41+
42+
>>> :set -XOverloadedStrings
43+
>>> import Language.Rust.Syntax.AST
44+
4045
-}
4146
{-# OPTIONS_GHC -Wall -fno-warn-orphans #-}
4247

@@ -87,7 +92,7 @@ import Control.Exception ( throw )
8792
-- >>> pretty (Binary [] MulOp (Binary [] AddOp one two ()) three ())
8893
-- Right (1 + 2) * 3
8994
-- >>> pretty (Binary [] AddOp one bogusVar ())
90-
-- Left (invalid AST (identifier is a keyword))
95+
-- Left (invalid AST (identifier `let' is a keyword))
9196
--
9297
pretty :: (Resolve a, Pretty a) => a -> Either ResolveFail (Doc b)
9398
pretty = fmap prettyUnresolved . resolve
@@ -103,7 +108,7 @@ pretty = fmap prettyUnresolved . resolve
103108
-- >>> pretty' (Binary [] MulOp (Binary [] AddOp one two ()) three ())
104109
-- (1 + 2) * 3
105110
-- >>> pretty' (Binary [] AddOp one bogusVar ())
106-
-- *** Exception: invalid AST (identifier is a keyword))
111+
-- *** Exception: invalid AST (identifier `let' is a keyword))
107112
--
108113
pretty' :: (Resolve a, Pretty a) => a -> Doc b
109114
pretty' = either throw id . pretty
@@ -132,14 +137,14 @@ writeSourceFile hdl = renderIO hdl . PP.layoutPretty layout . prettyAnnotated'
132137

133138
-- | Given a handle to a file, write a 'SourceFile' in with a desired width of 100 characters.
134139
--
135-
-- The 'Span' associated with the tokens (if present) will be used as a hint to for spacing
136-
-- out the tokens.
140+
-- The 'Span' associated with the tokens (if present) will be used as a hint for laying out and
141+
-- spacing the tokens.
137142
writeTokens :: Handle -> [Spanned Token] -> IO ()
138143
writeTokens hdl = renderIO hdl . PP.layoutPretty layout . pretty' . Stream . map mkTT
139144
where layout = PP.LayoutOptions (PP.AvailablePerLine 100 1.0)
140145
mkTT (Spanned s t) = Tree (Token t s)
141146

142-
-- | Describes things that can be pretty printed
147+
-- | Describes things that can be pretty printed.
143148
class Pretty a where
144149
-- | Pretty print the given value without resolving it.
145150
prettyUnresolved :: a -> Doc b
@@ -149,6 +154,7 @@ instance Pretty BindingMode where prettyUnresolved = printBindingMode
149154
instance Pretty BinOp where prettyUnresolved = printBinOp
150155
instance Pretty Ident where prettyUnresolved = printIdent
151156
instance Pretty ImplPolarity where prettyUnresolved = printPolarity
157+
instance Pretty Suffix where prettyUnresolved = printLitSuffix
152158
instance Pretty LitTok where prettyUnresolved = printLitTok
153159
instance Pretty Mutability where prettyUnresolved = printMutability
154160
instance Pretty RangeLimits where prettyUnresolved = printRangeLimits

0 commit comments

Comments
 (0)