1 #include "Teuchos_Grammar.hpp"
3 #include <Teuchos_Assert.hpp>
7 #include "Teuchos_vector.hpp"
12 int get_nnonterminals(Grammar
const& g) {
13 return g.nsymbols - g.nterminals;
16 bool is_terminal(Grammar
const& g,
int symbol) {
17 TEUCHOS_DEBUG_ASSERT(0 <= symbol);
18 TEUCHOS_DEBUG_ASSERT(symbol <= g.nsymbols);
19 return symbol < g.nterminals;
22 bool is_nonterminal(Grammar
const& g,
int symbol) {
23 return !is_terminal(g, symbol);
26 int as_nonterminal(Grammar
const& g,
int symbol) {
27 return symbol - g.nterminals;
30 int find_goal_symbol(Grammar
const& g) {
31 std::set<int> nonterminals_in_rhss;
32 for (
int i = 0; i < size(g.productions); ++i) {
33 const Grammar::Production& p = at(g.productions, i);
34 for (
int j = 0; j < size(p.rhs); ++j) {
35 const int s = at(p.rhs, j);
36 TEUCHOS_DEBUG_ASSERT(0 <= s);
37 if (is_nonterminal(g, s)) nonterminals_in_rhss.insert(s);
41 for (
int s = g.nterminals; s < g.nsymbols; ++s) {
42 if (!nonterminals_in_rhss.count(s)) {
44 "ERROR: there is more than one root nonterminal ("
45 << at(g.symbol_names, result) <<
" [" << result <<
"] and "
46 << at(g.symbol_names, s) <<
" [" << s <<
"]) in this grammar\n");
51 "ERROR: the root nonterminal is unclear for this grammar\n"
52 "usually this means all nonterminals appear in the RHS of a production\n"
53 "and can be fixed by adding a new nonterminal root2, root2 -> root\n");
57 void add_end_terminal(Grammar& g) {
58 for (
int i = 0; i < size(g.productions); ++i) {
59 Grammar::Production& prod = at(g.productions, i);
60 if (is_nonterminal(g, prod.lhs)) prod.lhs++;
61 for (
int j = 0; j < size(prod.rhs); ++j) {
62 int& rhs_symb = at(prod.rhs, j);
63 if (is_nonterminal(g, rhs_symb)) rhs_symb++;
66 g.symbol_names.insert(g.symbol_names.begin() + g.nterminals,
"EOF");
71 int get_end_terminal(Grammar
const& g) {
72 return g.nterminals - 1;
75 void add_accept_production(Grammar& g) {
76 int goal_symbol = find_goal_symbol(g);
77 Grammar::Production p;
79 p.rhs.push_back(goal_symbol);
80 g.productions.push_back(p);
81 g.symbol_names.push_back(
"ACCEPT");
85 int get_accept_production(Grammar
const& g) {
86 return size(g.productions) - 1;
89 int get_accept_nonterminal(Grammar
const& g) {
90 return g.nsymbols - 1;
93 std::ostream& operator<<(std::ostream& os, Grammar
const& g) {
95 for (
int i = 0; i < size(g.symbol_names); ++i) {
96 os << i <<
": " << at(g.symbol_names, i) <<
"\n";
98 os <<
"productions:\n";
99 for (
int i = 0; i < size(g.productions); ++i) {
100 const Grammar::Production& prod = at(g.productions, i);
101 os << i <<
": " << prod.lhs <<
" ::=";
102 for (
int j = 0; j < size(prod.rhs); ++j) {
103 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.