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)