Not logged in. Login

Assignment 2 Quiz - Solutions

Consider the following grammar of the Pablum expression language.

<expr> ::= <term> | <expr> "OR" <term>
<term> ::= <factor> | <factor> "AND" <term> 
<factor> ::= "0" | "1" | <ident> | "(" <expr> ")"

where identifiers have syntax given by the following regular expression.

<ident> ::= [A-Za-z]+

Assume that the Pablum follows the normal free-format rules for programming languages:

  • White space may (blanks and newlines) may freely occur between tokens.
  • Tokens follow the longest-match rule, so that white space is necessary between identifiers and keywords.

Note: you may use the Haskell predicate function isAlpha to test for an alphabetic character ([A-Za-z]).

1. (1 mark) Write a Haskell algebraic data type definition for tokens of the language.

data Token = OR_t | AND_t | T_0 | T_1 | LP | RP | Id String | Bad   deriving Show
-- Short names are useful on exams

2. (1 mark) Write a Haskell algebraic data type definition suitable for representing Pablum ASTs (abstract syntax trees).

data AST = Or (AST, AST) | And (AST, AST) | Zero | One | Var String deriving Show

3. (1 mark) Write the Haskell type signature of a Pablum lexer function lex that converts a list of characters into a list of tokens.

lexer :: [Char] -> [Token]

4. (2 marks) Implement the Pablum lexer function lex in Haskell.

lexer [] = []
lexer (' ':more) = lexer more  -- skip blanks
lexer ('\n':more) = lexer more -- skip newlines (optional)
lexer ('(':more) = LP: (lexer more)
lexer (')':more) = RP: (lexer more)
lexer ('0':more) = T_0: (lexer more)
lexer ('1':more) = T_1: (lexer more)
lexer (c : more)
  | isAlpha c  = case (span isAlpha (c : more)) of
                     ("OR", after) -> OR_t : (lexer after)
                     ("AND", after) -> AND_t : (lexer after)
                     (id, after) -> (Id id): (lexer after)
  | otherwise = Bad : (lexer more)

5. (1 mark) Write the Haskell type signature of the three recursive descent parsing functions required by the grammar.

parseExpr :: [Token] -> Maybe (AST, [Token])
parseTerm :: [Token] -> Maybe (AST, [Token])
parseFactor :: [Token] -> Maybe (AST, [Token])

6. (1 mark) Implement the parseFactor function in Haskell.

parseFactor (T_0: more) = Just (Zero, more)
parseFactor (T_1: more) = Just (One, more)
parseFactor (Id id: more) = Just (Var id, more)
parseFactor (LP: after) =
   case parseExpr after of
      Just (e, RP:remaining) -> Just (e, remaining)
      _ -> Nothing
parseFactor _ = Nothing

7. (1 mark) Implement the parseTerm function in Haskell.

--Note: this is not left-recursive!
parseTerm s =
   case parseFactor(s) of
       Just(f, AND_t:more) ->
            case parseTerm(more) of
                Just(t, afterTerm2) -> Just(And(f, t), afterTerm2)
                _ -> Nothing
       Just(f, more) -> Just(f, more)
       _ -> Nothing

8. (2 marks) Implement the parseExpr function in Haskell.

parseExpr s =
    case parseTerm(s) of
        Just (t, after) -> extendExpr(t, after)
        _ -> Nothing

extendExpr(e, []) = Just(e, [])
extendExpr(e, OR_t:more) =
    case parseTerm(more) of
        Just(t, remain) -> extendExpr(Or(e, t), remain)
        _ -> Nothing
extendExpr(e, ts) = Just(e, ts)
Updated Thu Oct. 22 2015, 08:24 by cameron.