MSc Thesis by Niklas Martinsson, Chalmers, Göteborg, 2001.
Tuesday seminar at OGI on 10 June, 2003 by Thomas Hallgren.
There are so many already!
|
|
|
Grammar:
expr ::= expr + term
| expr - term
| term
|
term ::= term * factor
| term / factor
| factor
|
factor ::= number
| ( expr )
|
Package SimpleMath;
Tokens
l_paren = '(';
r_paren = ')';
plus = '+';
minus = '-';
mult = '*';
div = '/';
number = ['0'..'9']+;
blank = [' ' 9 12 8 11 13 10];
Ignored Tokens
blank;
Productions
expr = {term} term
| {plus} expr plus term
| {minus} expr minus term ;
term = {factor} factor
| {mult} term mult factor
| {div} term div factor ;
factor = {number} number
| {expr} l_paren expr r_paren ;
.blank = [" \t\f\b\v\r\n"]
.number :: Int = ['0'..'9']+
expr :: Expr
= .. ::= term
| Add.. ::= expr '+' term
| Sub.. ::= expr '-' term ;
term
= .. ::= factor
| Mul.. ::= term '*' factor
| Div.. ::= term '/' factor ;
factor
= Number.. ::= number
| .. ::= '(' expr ')'
From the 13 lines of code on the previous slice, Cactus generates
| Haskell back-end | C back-end |
|---|---|
|
show for abstract syntax trees.
|
The user needs to supply a function for
converting the number strings to Int.
.blank = [" \t\f\b\v\r\n"]
.number :: Int = ['0'..'9']+
expr :: Expr
= term ::= term
| Add(expr1,term1) ::= expr '+' term
| Sub(expr,term) ::= expr '-' term ;
term
= $1 ::= factor
| Mul($1,$3) ::= term '*' factor
| Div($1,$3) ::= term '/' factor ;
factor
= Number($1) ::= number
| $2 ::= '(' expr ')'
%data Expr
= Add(Expr, Expr)
| Sub(Expr, Expr)
| Mul(Expr, Expr)
| Div(Expr, Expr)
| Number(Int)
Cactus can infer many thing automatically:
| Category | Can be inferred | Can be given explicitly |
|---|---|---|
| Types of nonterminals | by type inference | yes |
| Names of types | from names of nonterminals | yes |
| Names of data constructors | no | yes |
| Types of data constructors | from their use | yes |
| Keywords | from use in concrete syntax | yes |
| Abstract syntax | yes... | yes |
.blank = [" \t\f\b\v\r\n"]
.number :: Int = ['0'..'9']+
%left.6 = '+', '-'
%left.7 = '*', '/'
expr
= Add.. ::= expr '+' expr
| Sub.. ::= expr '-' expr
| Mul.. ::= expr '*' expr
| Div.. ::= expr '/' expr
| Number.. ::= number
| .. ::= '(' expr ')' ;
.blank = [" \t\f\b\v\r\n"]
.number :: Int = ['0'..'9']+
%left.6 = '+', '-'
%left.7 = '*', '/'
expr
= Op.. ::= expr op expr
| Number.. ::= number
| .. ::= '(' expr ')' ;
%expand op ::= '+' | '-' | '*' | '/' ;
%expand directive can be used to avoid conflicts in LR
parsers that can arise when refactoring the grammar.
exp+ (repetition, one or more)
exp* (repetition, zero or more)
exp? (optional part)
exp (',' exp)* (parentheses with several parts)
Cactus supports several ways to refer to parts of the syntax tree when specifying the abstract syntax.
| By position | List($2:$3.2) ::= '[' exp (',' exp)+ ']'
|
|---|---|
| By name+position | List(exp1:exp2) ::= '[' exp (',' exp)+ ']'
|
| By explicit names | List(e1:e2) ::= '[' exp:e1 (',' exp:e2)+ ']'
|
| Automatically | List.. ::= '[' exp:e1 (',' exp:e2)+ ']'
|
(In this example, $3 would work instead of $3.2)