//
// A grammar example taken from Appel's book:
//   Modern Compiler Design and Implementation in ML
//

//
// Author: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
// Time: February, 2009
//

//
// How to compile:
//   atscc -o grammar_example_3_15 \
//     grammar_example_3_15.dats grammar.sats grammar.dats
//

(* ****** ****** *)

staload "grammar.sats"

(* ****** ****** *)

local

#define K 0

in

val eof = symbol_make_string_int ("$", K+0)

val id = symbol_make_string_int ("id", K+1)
val num = symbol_make_string_int ("num", K+2)
val lparen = symbol_make_string_int ("(", K+3)
val rparen = symbol_make_string_int (")", K+4)

val add = symbol_make_string_int ("+", K+5)
val sub = symbol_make_string_int ("-", K+6)
val mul = symbol_make_string_int ("*", K+7)
val div = symbol_make_string_int ("/", K+8)

val theTermLst = $lst (
  eof, id, num, lparen, rparen, add, sub, mul, div
)

end // end of [local]

(* ****** ****** *)

local

#define K 256

in

val S = symbol_make_string_int ("S", K+0)
val E = symbol_make_string_int ("E", K+1)
val E' = symbol_make_string_int ("E'", K+2)
val T = symbol_make_string_int ("T", K+3)
val T' = symbol_make_string_int ("T'", K+4)
val F = symbol_make_string_int ("F", K+5)

val theNontermLst = $lst (S, E, E', T, T', F)

end // end of [local]

(* ****** ****** *)

val rule_S = RULE ("rule_S", S, alpha) where {
  val alpha = array0_make_arrsz $arrsz {symbol_t} (E, eof)
} // end of [val]

val rule_E = RULE ("rule_E", E, alpha) where {
  val alpha = array0_make_arrsz $arrsz {symbol_t} (T, E')
} // end of [val]

val rule_E'_1 = RULE ("rule_E'_1", E', alpha) where {
  val alpha = array0_make_arrsz $arrsz {symbol_t} (add, T, E')
} // end of [val]

val rule_E'_2 = RULE ("rule_E'_2", E', alpha) where {
  val alpha = array0_make_arrsz $arrsz {symbol_t} (sub, T, E')
} // end of [val]

val rule_E'_3 = RULE ("rule_E'_3", E', alpha) where {
  val alpha = array0_make_arrsz $arrsz {symbol_t} ()
} // end of [val]

val rule_T = RULE ("rule_T", T, alpha) where {
  val alpha = array0_make_arrsz $arrsz {symbol_t} (F, T')
} // end of [val]

val rule_T'_1 = RULE ("rule_T'_1", T', alpha) where {
  val alpha = array0_make_arrsz $arrsz {symbol_t} (mul, F, T')
} // end of [val]

val rule_T'_2 = RULE ("rule_T'_2", T', alpha) where {
  val alpha = array0_make_arrsz $arrsz {symbol_t} (div, F, T')
} // end of [val]

val rule_T'_3 = RULE ("rule_T'_3", T', alpha) where {
  val alpha = array0_make_arrsz $arrsz {symbol_t} ()
} // end of [val]

val rule_F_1 = RULE ("rule_F_1", F, alpha) where {
  val alpha = array0_make_arrsz $arrsz {symbol_t} (id)
} // end of [val]

val rule_F_2 = RULE ("rule_F_2", F, alpha) where {
  val alpha = array0_make_arrsz $arrsz {symbol_t} (num)
} // end of [val]

val rule_F_3 = RULE ("rule_F_3", F, alpha) where {
  val alpha = array0_make_arrsz $arrsz {symbol_t} (lparen, E, rparen)
} // end of [val]

(* ****** ****** *)

val grammar_3_15 = '{
  termlst= theTermLst, nontermlst= theNontermLst, rules= rules
} where {
  val rules = $lst (
    rule_S
  , rule_E
  , rule_E'_1, rule_E'_2, rule_E'_3
  , rule_T
  , rule_T'_1, rule_T'_2, rule_T'_3
  , rule_F_1, rule_F_2, rule_F_3
  )
} // end of [val]

(* ****** ****** *)

dynload "grammar.dats"

(* ****** ****** *)

implement main () = let
  val () = print "The rules of the Grammar 3.15 are given as follows:\n"
  val () = print_grammar (grammar_3_15)
  val () = compute_nullable_first_follow_tables (grammar_3_15)
in
  print_nullable_first_follow_tables (grammar_3_15)
end // end of [main]

(* ****** ****** *)

(* end of [grammar_example_3_15.dats] *)