Language2
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.