Teuchos - Trilinos Tools Package Version of the Day
Loading...
Searching...
No Matches
Teuchos_Grammar.cpp
1// @HEADER
2// *****************************************************************************
3// Teuchos: Common Tools Package
4//
5// Copyright 2004 NTESS and the Teuchos contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#include "Teuchos_Grammar.hpp"
11
12#include <Teuchos_Assert.hpp>
13#include <set>
14#include <iostream>
15
16#include "Teuchos_vector.hpp"
17#include "Teuchos_Parser.hpp"
18
19namespace Teuchos {
20
21int get_nnonterminals(Grammar const& g) {
22 return g.nsymbols - g.nterminals;
23}
24
25bool 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;
29}
30
31bool is_nonterminal(Grammar const& g, int symbol) {
32 return !is_terminal(g, symbol);
33}
34
35int as_nonterminal(Grammar const& g, int symbol) {
36 return symbol - g.nterminals;
37}
38
39int 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);
47 }
48 }
49 int result = -1;
50 for (int s = g.nterminals; s < g.nsymbols; ++s) {
51 if (!nonterminals_in_rhss.count(s)) {
52 TEUCHOS_TEST_FOR_EXCEPTION(result != -1, ParserFail,
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");
56 result = s;
57 }
58 }
59 TEUCHOS_TEST_FOR_EXCEPTION(result == -1, ParserFail,
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");
63 return result;
64}
65
66void 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++;
73 }
74 }
75 g.symbol_names.insert(g.symbol_names.begin() + g.nterminals, "EOF");
76 g.nterminals++;
77 g.nsymbols++;
78}
79
80int get_end_terminal(Grammar const& g) {
81 return g.nterminals - 1;
82}
83
84void add_accept_production(Grammar& g) {
85 int goal_symbol = find_goal_symbol(g);
86 Grammar::Production p;
87 p.lhs = g.nsymbols;
88 p.rhs.push_back(goal_symbol);
89 g.productions.push_back(p);
90 g.symbol_names.push_back("ACCEPT");
91 g.nsymbols++;
92}
93
94int get_accept_production(Grammar const& g) {
95 return Teuchos::size(g.productions) - 1;
96}
97
98int get_accept_nonterminal(Grammar const& g) {
99 return g.nsymbols - 1;
100}
101
102std::ostream& operator<<(std::ostream& os, Grammar const& g) {
103 os << "symbols:\n";
104 for (int i = 0; i < Teuchos::size(g.symbol_names); ++i) {
105 os << i << ": " << at(g.symbol_names, i) << "\n";
106 }
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);
113 os << ' ' << symb;
114 }
115 os << '\n';
116 }
117 os << '\n';
118 return os;
119}
120
121}
Declares Teuchos::Parser, ParserFail and make_lalr1_parser.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...