Appendix A - A Grammar for Kenya


The grammar for Kenya for use with SableCC looks like:

Package minijava;

Helpers
  letter = ['A'..'Z'] | ['a'..'z'];
  digit = ['0'..'9'];
  cr = 13;
  lf = 10; 
  point = '.';
  not_cr_lf = [[32..127] - [cr + lf]];
  space = ' ';

Tokens
  boolean = 'boolean';
  char = 'char';
  int = 'int';
  real = 'real';
  string = 'string';
  void = 'void';

  klass = 'class';
  const = 'const';
  print = 'print';
  println = 'println';
  if = 'if';
  else = 'else';
  while = 'while';
  return = 'return';
  switch = 'switch';
  case = 'case';
  break = 'break';
  default = 'default';
  for = 'for';
  to = 'to';
  step = 'step';
  decreasing = 'decreasing';
  call = 'call';

  true = 'true';
  false = 'false';

  and = 'and';
  or = 'or';
  xor = 'xor';
  not = 'not';

  readint = 'readInt()';
  readreal = 'readReal()';
  readstring = 'readString()';

  identifier = letter (letter | digit)*;
  stringliteral = '"' [not_cr_lf - '"']* '"';

  l_parenthese = '(';
  r_parenthese = ')';
  l_brace = '{';
  r_brace = '}';
  l_bracket = '[';
  r_bracket = ']';
  semicolon = ';';
  colon = ':';
  comma = ',';
  dot = point;

  plus = '+';
  minus = '-';
  times = '*';
  divide = '/';
  power = '^';
  mod = '%';
  less = '<';
  lessequal = '<=';
  greater = '>';
  greaterequal = '>=';
  equal = '==';
  notequal = '!=';
  assign = '=';
  
  intnumber = digit+ ; 
  fpnumber = digit+ point digit+;

  new_line = cr | lf | cr lf;

  blank = space*;
 
  comment = '//' (letter | digit | space )* ( cr | lf | cr lf );

Ignored Tokens
  blank , new_line , comment;

Productions

 statements = 
    {list}  statement statements | 
    {empty} ;

  statement = 
    {dec} declaration |
    {functioncall} function_application semicolon | 
    {assignment} field_access assign expression semicolon |
    {if} if l_parenthese bool_expression r_parenthese [block1]:block else? [block2]:block? |
    {while} while l_parenthese bool_expression r_parenthese block |
    {return} return expression? semicolon |
    {switch} switch l_parenthese expression r_parenthese switch_block |
    {for} for decreasing? name assign [exp1]:expression to [exp2]:expression step? [exp3]:expression? block |
    {break} break semicolon |
    {print_str} print expression semicolon |
    {println_str} println expression semicolon;

  block = l_brace statements r_brace;

  function_application = call name l_parenthese actual_param_list r_parenthese;

  actual_param_list = {list} actual_param_list comma expression |
                      {exp} expression |
                      {empty};

  switch_block = l_brace possible_case* r_brace;

  possible_case = switch_label block;

  switch_label = 
    {case} case expression colon |
    {default} default colon;

  declaration =
    {class_dec} klass identifier l_brace declaration* r_brace |
    {func_dec}  type identifier l_parenthese formal_param_list? r_parenthese block |       
    {const_dec} const type identifier initialiser? semicolon |
    {var_dec}   type type_param? identifier array_access* initialiser? semicolon;	      
   
  formal_param_list = type_name comma_type_name*;

  type_name = type identifier;

  comma_type_name = comma type_name;

  initialiser = assign expression;

  booleanliteral = 
    {true} true | 
    {false} false;

/********************
       Types
********************/

  type =

    {basic_type}
        basic_type |

    {reference_type}
        reference_type;

   basic_type =

    {char}
        char |

    {int}
	int |

    {real}
	real |

    {string}
        string |

    {boolean}
        boolean |

    {void}
        void;

  reference_type =
    {class_type}
        class_type;

/********************
Variable Declarations
********************/

  type_param = less type_param_list greater;

  type_param_list = type comma_type*;

  comma_type = comma type;

/********************
  Expressions
********************/

  expression = 
    {boolexp} bool_expression;

  math_expression =
    {term} term |
    {plus} math_expression plus term |
    {minus} math_expression minus term ;

  term =
    {factor} factor |
    {mult} term times factor |
    {div} term divide factor |
    {mod} term mod factor |
    {power} term power factor;


  factor =
    {function} function_application |
    {number} number |
    {stringliteral} stringliteral |
    {readint} readint |
    {readreal} readreal |
    {readstring} readstring |
    {fieldaccess} field_access |
    {expression} l_parenthese bool_expression r_parenthese;
    
  number = {i} intnumber | 
           {f} fpnumber;	

  bool_expression = 
    {term} bool_term |
    {mathexp} math_expression |	
    {or} bool_expression or bool_term;

  bool_term =
    {factor} bool_factor |
    {and} bool_term and bool_factor;

  bool_factor =
    {literal} booleanliteral |
    {compare} [lhs]:math_expression comp_operator [rhs]:math_expression |
    {negate}  not l_parenthese bool_expression r_parenthese;
    

/********************
       Names
********************/

  field_access = 
    {array} name array_access+ |
    {scalar} name;

  name =

    {simple_name}
        simple_name |

    {qualified_name}
        qualified_name;

  simple_name =
    identifier; 

  qualified_name =
    field_access dot identifier;

  array_access = l_bracket math_expression r_bracket;