Package de.prob.voparser;

/*******************************************************************
 * Helpers                                                         *
 *******************************************************************/
Helpers
  small_letter = ['a'..'z'];
  capital_letter = ['A' .. 'Z'];
  letter = small_letter | capital_letter;
  digit = ['0' .. '9'];

  underscore = '_';

  line_break = [10 + 13];
  layout_char = [[[[0 .. 32] - line_break] + [127..160]] + [[8206 .. 8207] + [8232 .. 8233]]];
  white_space = line_break | layout_char+;

  l_paren = '(';
  r_paren = ')';

  opt_white_space = layout_char*; // note: no newline (so as not to disturb counting); no comments
  dot = '.';
  comma = ',';

  identifier_literal = (letter | underscore) (letter | underscore | digit | dot | comma)*;

/*******************************************************************
 * Tokens                                                          *
 *******************************************************************/
Tokens
  l_par = l_paren;
  r_par = r_paren;

  /* Boolean Operators */
  and = '&' | 0x2227 | 'and';
  or = 'or' | 0x2228 | '||';

  /* Sequential Operator*/
  sequential = ';';

  identifier_literal = identifier_literal;

  white_space = white_space;

/*******************************************************************
 * Ignored Tokens                                                  *
 *******************************************************************/
Ignored Tokens
  white_space;

/*******************************************************************
 * Productions                                                     *
 *******************************************************************/
Productions

  vo_formula {-> vo} =
    {and} [left]:vo_formula and [right]:vo_formula1 {-> New vo.and(left.vo, right.vo)} |
    {or} [left]:vo_formula or [right]:vo_formula1 {-> New vo.or(left.vo, right.vo)} |
    vo_formula1 {-> vo_formula1.vo};

  vo_formula1 {-> vo} =
    {sequential} [left]:vo_formula1 sequential [right]:vo_formula2 {-> New vo.sequential(left.vo, right.vo)} |
    vo_formula2 {-> vo_formula2.vo};

  vo_formula2 {-> vo} =
    {identifier} identifier_literal {-> New vo.identifier(identifier_literal)} |
    {par} l_par vo_formula r_par {-> vo_formula.vo};

/*******************************************************************
 * Abstract Syntax Tree                                            *
 *******************************************************************/

Abstract Syntax Tree
  vo =
   {and} [left]:vo [right]:vo |
   {or} [left]:vo [right]:vo |
   {sequential} [left]:vo [right]:vo |
   {identifier} identifier_literal;