10 #include "Teuchos_Grammar.hpp"
12 #include <Teuchos_Assert.hpp>
16 #include "Teuchos_vector.hpp"
21 int get_nnonterminals(Grammar
const& g) {
22 return g.nsymbols - g.nterminals;
25 bool is_terminal(Grammar
const& g,
int symbol) {
26 TEUCHOS_DEBUG_ASSERT(0 <= symbol);
27 TEUCHOS_DEBUG_ASSERT(symbol <= g.nsymbols);
28 return symbol < g.nterminals;
31 bool is_nonterminal(Grammar
const& g,
int symbol) {
32 return !is_terminal(g, symbol);
35 int as_nonterminal(Grammar
const& g,
int symbol) {
36 return symbol - g.nterminals;
39 int find_goal_symbol(Grammar
const& g) {
40 std::set<int> nonterminals_in_rhss;
41 for (
int i = 0; i < Teuchos::size(g.productions); ++i) {
42 const Grammar::Production& p = at(g.productions, i);
43 for (
int j = 0; j < Teuchos::size(p.rhs); ++j) {
44 const int s = at(p.rhs, j);
45 TEUCHOS_DEBUG_ASSERT(0 <= s);
46 if (is_nonterminal(g, s)) nonterminals_in_rhss.insert(s);
50 for (
int s = g.nterminals; s < g.nsymbols; ++s) {
51 if (!nonterminals_in_rhss.count(s)) {
53 "ERROR: there is more than one root nonterminal ("
54 << at(g.symbol_names, result) <<
" [" << result <<
"] and "
55 << at(g.symbol_names, s) <<
" [" << s <<
"]) in this grammar\n");
60 "ERROR: the root nonterminal is unclear for this grammar\n"
61 "usually this means all nonterminals appear in the RHS of a production\n"
62 "and can be fixed by adding a new nonterminal root2, root2 -> root\n");
66 void add_end_terminal(Grammar& g) {
67 for (
int i = 0; i < Teuchos::size(g.productions); ++i) {
68 Grammar::Production& prod = at(g.productions, i);
69 if (is_nonterminal(g, prod.lhs)) prod.lhs++;
70 for (
int j = 0; j < Teuchos::size(prod.rhs); ++j) {
71 int& rhs_symb = at(prod.rhs, j);
72 if (is_nonterminal(g, rhs_symb)) rhs_symb++;
75 g.symbol_names.insert(g.symbol_names.begin() + g.nterminals,
"EOF");
80 int get_end_terminal(Grammar
const& g) {
81 return g.nterminals - 1;
84 void add_accept_production(Grammar& g) {
85 int goal_symbol = find_goal_symbol(g);
86 Grammar::Production p;
88 p.rhs.push_back(goal_symbol);
89 g.productions.push_back(p);
90 g.symbol_names.push_back(
"ACCEPT");
94 int get_accept_production(Grammar
const& g) {
95 return Teuchos::size(g.productions) - 1;
98 int get_accept_nonterminal(Grammar
const& g) {
99 return g.nsymbols - 1;
102 std::ostream& operator<<(std::ostream& os, Grammar
const& g) {
104 for (
int i = 0; i < Teuchos::size(g.symbol_names); ++i) {
105 os << i <<
": " << at(g.symbol_names, i) <<
"\n";
107 os <<
"productions:\n";
108 for (
int i = 0; i < Teuchos::size(g.productions); ++i) {
109 const Grammar::Production& prod = at(g.productions, i);
110 os << i <<
": " << prod.lhs <<
" ::=";
111 for (
int j = 0; j < Teuchos::size(prod.rhs); ++j) {
112 int symb = at(prod.rhs, j);
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
Declares Teuchos::Parser, ParserFail and make_lalr1_parser.