//
// This is a demonstration grammar file with transformation rules for the
// new SableCC3 parser generator (rel sablecc-3-beta.3.altgen.20040327)
//
// Points to remember:
//
// * Why CST and AST? Due to limitations of parser technology the
// human described grammar does not represent the "perfect" abstract
// form of the language parsed. To get the AST transformations are done.
// (AST - Abstract Syntax Tree; CST - Concrete Syntax Tree)
//
// * The AST section must be complete, nothing from Productions is
// automatically placed there.
//
// * In curly braces are things related to AST, eg. we built the AST in
// those things, so everything is built/transformed from the leaves to
// root.
//
// * Transformation is divided into two parts - product transformation
// declaration that declares what the alternatives should be
// transformed to and alternatives transformations definitions that
// define how the transform is actually done.
//
// * A production can be transformed to multiple elements as seen in the
// 'random_x2' rule.
//
// * Productions with same structure as in the AST can be directly
// transformed to AST - see the 'textual' rule. What really happens is
// that for productions and alternatives without transform specification
// default transformation rules are generated. This also means that you
// could omit the transform declaration at exp rule.
//
// * Lists it seems are represented with brackets '[ elem1, elem2, .. ]' and
// not parenthesis as described in the doc. If element is also a list it
// is automatically expanded and used. Empty list is [].
//
// * The output we get from the parser is as described in the AST. We only
// have to work with that. The productions section is no longer used.
//
// * When you just want to get rid of a production declare and define
// it and its alternatives as {-> } or with the newer sablecc release
// you can just leave it without any rules. See the 'separator' rule.
//
// * You can't place null-s into lists. When the expression is null
// (either by ?) or directly set in transformation and is later added
// to a list - it is eliminated by SableCC.
//
// * With the latest sablecc release '?' and '+' are supported in
// the AST section. They are also enforced from productions.
// You'll see when errors start popping up.
//
// * In the product transformation declaration you can similarily use
// renaming in the style 'productname { .. [use_name]:name .. } = ..'
// This can be very useful when using multiple elements of the same type
// at transform. See the 'random_x2' rule for example.
//
// Written by Indrek Mandre in July-August 2003
// Example constructed from the SableCC docs/Kevin Agbakpem and
// Etienne Bergeron e-mail. http://www.mare.ee/indrek/sablecc/
//
Package expression;
Helpers
digit = ['0' .. '9'];
tab = 9;
cr = 13;
lf = 10;
eol = cr lf | cr | lf;
blank = (' ' | tab | eol)+;
Tokens
l_par = '(';
r_par = ')';
plus = '+';
minus = '-';
mult = '*';
div = '/';
semi = ';';
blank = blank;
number = digit+;
one = 'one';
two = 'two';
three = 'three';
random = 'random_digit';
Ignored Tokens
blank;
Productions
grammar = exp_list {-> New grammar ([exp_list.exp])}
;
exp_list {-> exp*} =
{list} exp_list separator exp {-> [exp_list.exp, exp.exp] }
| {single} exp {-> [exp.exp] }
;
exp {-> exp} =
{plus} exp plus factor {-> New exp.plus (exp.exp, factor.exp) }
| {minus} exp minus factor {-> New exp.minus (exp.exp, factor.exp) }
| {factor} factor {-> factor.exp }
;
factor {-> exp} =
{mult} factor mult term {-> New exp.mult (factor.exp, term.exp) }
| {div} factor div term {-> New exp.div (factor.exp, term.exp) }
| {term} term {-> term.exp }
;
term {-> exp} =
{number} number {-> New exp.number(number) }
| {exp} l_par exp r_par {-> exp.exp }
| {textual} textual+ {-> New exp.textual ([textual]) }
| {random_x2} random_x2 {-> New exp.random_x2 (random_x2.ran1, random_x2.ran2) }
;
textual =
{t1} one
| {t2} two
| {t3} three
;
random_x2 {-> [ran1]:random [ran2]:random} =
[ran1]:random [ran2]:random {-> ran1 ran2 }
;
separator {-> } =
{semicolon} semi {-> }
;
Abstract Syntax Tree
grammar = exp+
;
exp =
{plus} [l]:exp [r]:exp |
{minus} [l]:exp [r]:exp |
{div} [l]:exp [r]:exp |
{mult} [l]:exp [r]:exp |
{textual} textual+ |
{random_x2} [r1]:random [r2]:random |
{number} number
;
textual =
{t1} one
| {t2} two
| {t3} three
;
//
// A few words about this grammar itself:
// - It is supposed to be a little integer based calculator with a few odd
// extensions to demonstrate sablecc transformations
// - You can use textual words to build up numbers (two one three -> 213)
// I didn't really bother to specify all the decimal textual numbers
// - The random number rule is a bit superficial, it just expects user to
// type 'random_digit random_digit' and produces a two-digit random
// number. I didn't figure out any better way to make the multiple
// element transform rule "interesting" ;)
//
// Valid expressions:
// (1 + 14 / (3 + 4)) * 14 -> 42
// one + 3 - two -> 2
// two one + three -> 24
// random_digit random_digit -> ??
// random_digit random_digit + 1 -> ??
// 1 + 3 ; 1 ; 4 + 5 -> 4; 1; 9
//
// In the Calculate.java is the implementation of the tree visitor that
// calculates the values.
//