Astview is a little desktop program to be used by people that want
to investigate syntax trees, e.g. students and lecturers in compiler
construction courses. Given a parse function p :: String ->
a
, where a
is a member of haskell's Data
typeclass, astview can show syntax trees in a standard tree
widget.
The program evolved as a case study in a) generic programming and b) building graphical user interfaces in haskell.
We tried to make the user interface as common as possible by following the GNOME human interface guidelines closely. You can open a file by giving the filename at the CLI:
astview .../path/to/mysource.hsor simply open it via the file menu. The file's extension will determine the parser automaticall. When there are multiple parsers for one extension, the first one will be taken. Launching astview without any files will enable the "lines and words"-parser. Saving works as expected: Ctrl-S saves, Save-As has to be done via the menu. When the file was changed, the usual star appears in the title bar, next to the filename.
Cut-and-Paste functionality works as usual (Ctrl-C/P/X), allowing to copy-paste source code to or from other programs.
Astview uses the same syntax-higlighting sourceview widget as GNOME's standard editor gedit, so any language recognized there will be highlighted by astview. For syntax-highlighting, the language is determined by the name of the parser.
As noted above, the parser is chosen automatically when opening a file. When editing source code, one can change the parser using the parser menu issuing an immediate reparse. Ctrl-P reparses the source at any time.
Astview loads the available parsers at runtime using the GHC-API wrapper hint. In this section we show how to add custom parsers.
A parser is described by a 3-tuple
data Parser = Parser { name :: String , exts :: [String] , tree :: String -> Tree String}
The name> of the parser is shown in the parser menu and is used to determine syntax highlighting. The list of extensions exts is used to determine the parser when opening a file. Finally - the magic bit of the whole tool - the buildTree function constructs a tree of Strings (Data.Tree String) from a haskell value. Each node of this tree denotes a constructor. This tree can be constructed using the data2tree function from the SYB approach to generic programming (TODO: ref), which is delivered with astview. Here is an example:
haskell :: Parser haskell = Parser "Haskell" [".hs"] buildTreeHaskell buildTreeHaskell :: String -> Tree String buildTreeHaskell s = case parseHaskell s of Right ast -> flat $ data2tree (ast::HsModule) Left ParseError -> Node "ParseError" [] parseHaskell :: (Data a) => String -> Either ParseError a parseHaskell s = case parseModule s of ParseOk p -> unsafeCoerce $ Right p _ -> Left ParseError
You can simply put such a parser into the file
~/.cabal/share/astview-0.2/data/Parsers.hs
which exports a list of all parsers:
parsers :: [Parser] parsers = haskell:stdParserData
Here, the predefined list of parsers stdParserData
is
extended with the new haskell-parser.
If your Parser needs additional modules, these modules have either be exposed to GHC's package-management, or have to exist as source-file under the data-Directory of astview. Remember that these modules are linked in at runtime!
To test your parser consider the following ghci-session:
user@host:path$ cd ~/.cabal/share/astview-0.2/data user@host:~/.cabal/share/astview-0.2/data$ ghci Parsers.hs -- ghci package-messages stripped *Parsers> :info Parser data Parser = Parser {name :: !String, exts :: [String], tree :: String -> Tree String} -- show all registered parsers *Parsers> map name parsers ["Haskell","CSV","Expr","Java","IsoPascal","C","Glade","List"] -- get haskell parser *Parsers> let haskell = head parsers -- build a sample tree of strings *Parsers> let sample = tree haskell "main = putStrLn \"Hello World\"" -- draw the tree *Parsers> putStrLn $ Data.Tree.drawTree sample -- lengthy output follows
If drawString
works for your sourcecode, astview will
too, since ghci uses the parsers in interpreted mode just as astview
does.
Notes for Developers, Short Module descriptions, references to haddock (include haddock !?), code conventions, history, GTK things