More Parsing

module Main where
...
type Word = String
...
readLine :: String -> Nest

Parse either a single word or a nested brackets []. (We added more primitive parsers here.)

parseSingle :: Parser Nest
parseSingle = do
  spaces
  x <- (try parseFloat) <|>
       (try parseInt) <|>
       (try parseBool) <|>
       (try parseString) <|>
       (try parseWord) <|>
       (try parseNest)
  spaces
  return x

Parse a nested structure starting with [ and ending with ]

parseNest :: Parser Nest
parseInt :: Parser Nest

parseFloat :: Parser Nest
parseFloat = do
  I i <- parseInt
  char '.'
  I j <- parseInt
  res <- return $ (show i) ++ ['.'] ++ (show j)
  return $ W res       -- TODO: change W to what you defined for float.

Parse a simple word without any spaces or nesting between them.

parseWord :: Parser Nest

parseBool :: Parser Nest
parseBool = do
  b <- string "true" <|> string "false"
  return $ W (read b)       -- TODO: change W to what you defined for bool.

parseString :: Parser Nest
parseString = do
  char '''
  s <- many (noneOf "'")
  char '''
  return $ W s       -- TODO: change W to what you defined for string.

The tentative BNF notation for this language

A number is a sequence of digits

 | <digit>   ::= 0..9
 | <num>     ::= <digit>
 |             | <digit><num>

 | <letter>  ::= a..z | + | - | * | / | < | > | = | .

We define char to be either a letter or a number (non white space.)

 | <char>    ::= <letter>
 |             | <digit>

So that we can have words like dup2 that includes a number

 | <word>    ::= <letter>
 |             | <word> <char>

A nest is either a number or a word or an expression of the form [ .. ]

 | <nest>    ::= <num>
 |             | <word>
 |             | [ <nest>* ]

And of course our expression is just a list of nests

 | <expr>   ::= <nest>*

Can you define the data structure required for a larger abstract syntax?

Currently we have,

data Nest = W Word
          | I Int
          | Nested [Nest]
  deriving (Show)

This is somewhat limited, We should at least have a way to store real numbers (Float), strings like "hello world", and booleans like true and false.

  • Can you extend our data to add these things?
  • Once you have done that, can you change the portions commented with TODO to use these instead? (Hint, you can use (read x) to convert x to any of int, bool or float from a string)
  • What does the expression below give you if you execute on ghci after doing the above?
readLine  " 'hello world' 'hi' swap concat "

Remember, we are defining our abstract syntax here. So readLine now prints the abstract syntax of the line being read.