define concrete type s_expression = // S-expressions a-la-mulisp
  Number of integer
| Symbol of integer
| List of list of s_expression;

expression : s_expression;
list : list of s_expression;

<expression> ::= number              { Number(string_to_integer($1.lexeme)) }
<expression> ::= symbol              { Symbol($1.lexeme) }
<expression> ::= openpar <list>      { List($2) }
<list>       ::= closepar            { [ ] }
<list>       ::= <expression> <list> { $1 :: $2 }

////////////////////////////////////////////////////////////////////////////

define synonym type expression_type = s_expression;
define synonym type list_type = list of expression_type;

////////////////////////////////////////////////////////////////////////////

define synonym type expression_type = type of (
  if false then
    Number(string_to_integer($1.lexeme))
  else if false then
    Symbol($1.lexeme)
  else
    List($2)
);

define synonym type list_type = type of (
  if false then
    [ ]
  else
    $1 :: $2
);
