Programming Praxis – Literate Programming

In today’s Programming Praxis exercise, our task is to write a program that converts K&R-style literate code to the resulting code listing. Let’s get started, shall we?

Some needed imports:

import Control.Applicative hiding (many, (<|>))
import Text.Parsec

The provided Scheme solution uses regular expressions. We will be using a parser-based approach instead. The idea is to store all the definitions in a list so we can then go in and make all the required substitutions. A definition can contain two types of lines: regular code or references to other definitions, in which case we also store the preceding indentation.

data Lit = Line String | Ref String String

The parser for this file format isn’t too complicated.

def = (,) <$> (many literate *> chunk <* char '=' <* literate)
          <*> sepEndBy1 line newline where
    rol = many (noneOf "\n")
    upto end = manyTill anyChar (try $ end)
    chunk = string "<<" *> many space *> upto (many space *> string ">>")
    literate = notFollowedBy chunk *> rol <* newline
    line = try (Ref <$> many space <*> chunk <* rol)
           <|> (Line <$> many1 (noneOf "\n"))

As mentioned earlier, the program parses all the definitions, stores them in a list and recursively substitutes all the references with their content.

tangle :: String -> String
tangle src = maybe "" (unlines . (f =<<)) $ lookup "*" defs where
    defs = either (error . show) id $ parse (many def) "" src
    f (Line s)  = [s]
    f (Ref n s) = map (n ++) . maybe [] (f =<<) $ lookup s defs

Let’s see if everything works:

main :: IO ()
main = putStrLn . tangle =<< readFile "tangle.txt"

Yep. Alternatively, just use a language with built-in literate programming, like Haskell 🙂

Tags: , , , , , ,

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: