https://rentry.org/PPP2_p193

// Code derived from Stroustrup's PPP2 book
// § 6.4.1 A detour: English grammar
//  -and beginning on p 193

//------------------------------------------------------------------------------
/*
    via pp 193, 194                Parsing the sentence: birbs fly but fish swim
                                              (read from bottom up):

                                                      Sentence
                                                          ^
  A simple sentence grammar                               |
                                             -------------+--------------
                                             |            |             |
Sentence:                                Sentence         |         Sentence
    Noun Verb                                ^            |             ^
    Sentence Conjunction Sentence            |            |             |
                                             |            |             |
Conjunction:                                 |       Conjunction        |
    "and"                                    |            ^             |
    "or"                                     |            |             |
    "but"                               -----+-----       |        -----+-----
                                        |         |       |        |         |
Noun:                                  Noun       |       |       Noun       |
    "birbs"                             ^         |       |        ^         |
    "fish"                              |         |       |        |         |
    "C++"                               |         |       |        |         |
                                        |         |       |        |         |
Verb:                                   |        Verb     |        |        Verb
    "rules"                             |         ^       |        |         ^
    "fly"                               |         |       |        |         |
    "swim"                              |         |       |        |         |

                                      birbs      fly     but      fish      swim

*/
//------------------------------------------------------------------------------

#include <iostream>
#include <map>
#include <set>
#include <string>

using std::cerr;
using std::cin;
using std::cout;
using std::string;

//------------------------------------------------------------------------------

// Note: we're introducing a map<> for words + their types

// word strings classified by types (n, v, c, p)
const std::map<std::string, std::set<char>> all_words = {
    // noun
    {"birbs", {'n'}},
    {"fish", {'n'}},
    {"C++", {'n'}},

    // verb
    {"rules", {'v'}},
    {"fly", {'v'}},
    {"swim", {'v'}},

    // conjunction
    {"and", {'c'}},
    {"or", {'c'}},
    {"but", {'c'}},

    // punctuation
    {".", {'p'}},
    {"?", {'p'}},
    {"!", {'p'}},
    {";", {'p'}}};

// returns the type code of word (n, v, c, p)
char type_of(std::string word)
{
  if (auto it = all_words.find(word); it != all_words.end()) {
    return *it->second.begin();  // the first type code for this word

  } else {
    std::cerr << word << " word not found\n";
    return 'K';  // invalid
  }
}

//------------------------------------------------------------------------------

// a simple user-defined type
class Token {
 public:
  Token(char ch) : kind{ch} {}
  Token(char ch, std::string word) : kind{ch}, value{word} {}

  char   kind  = '0';  // 'n', 'v', 'c', 'p' codes
  string value = "";   // the word itself
};

//------------------------------------------------------------------------------

class Token_stream {
 public:
  Token_stream();  // make a Token_stream that reads from cin

  Token get();             // get a Token
  void  putback(Token t);  // put a Token back

 private:
  bool  full;    // is there a Token in the buffer?
  Token buffer;  // here is where we keep a Token put back using putback()
};

// The constructor just sets full to indicate that the buffer is empty:
Token_stream::Token_stream() : full{false}, buffer{0}  // no Token in buffer
{
}

Token Token_stream::get()
{
  if (full) {  // do we already have a Token ready?
    // remove token from buffer:
    full = false;
    return buffer;
  }

  string word;
  cin >> word;
  char ch = type_of(word);

  // clang-format off
  switch (ch) {
    case 'n': case 'v': case 'c': case 'p': {  // words & punctuations
      return Token{ch, word};
    }
    default:
      return Token{'K', "K"};  // invalid
  }
  // clang-format on
}

// The putback() member function puts its argument back into the Token_stream's
// buffer:
void Token_stream::putback(Token t)
{
  buffer = t;     // copy t to buffer
  full   = true;  // buffer is now full
}

//------------------------------------------------------------------------------

std::string sentence();
std::string conjunct();
std::string noun();
std::string verb();

Token_stream ts;  // provides get() and putback()

//------------------------------------------------------------------------------

// Note: this is an example to demonstrate simplistic parsing the expression of
// these six tokens:
//
//     birbs fly but fish swim ;
//
// -the idea for now is just to use the functions to print out the type of the
// words according to the grammar given above
// -but this basic system could be extended into a more powerful framework later

int main()
{
  cout << "enter:  birbs fly but fish swim ; (leave a space before ;)  \n";

  cout << sentence() << '\n';
}

std::string sentence()
{
  string left = "";

  Token t = ts.get();  // get the first Token from the Token stream

  while (true) {
    switch (t.kind) {  // see which kind of token it is
      case 'c':
        ts.putback(t);
        left += conjunct();
        break;
      case 'n':
        ts.putback(t);
        left += noun();
        break;
      case 'v':
        ts.putback(t);
        left += verb();
        break;
      case 'p': return "sentence:  " + left + t.value; break;
      default: std::cerr << "unknown type/word not found\n"; return left;
    }

    t = ts.get();  // get the next Token from the Token stream
  }
}

std::string conjunct()
{
  Token t = ts.get();
  cout << "c " << t.value << '\n';

  return t.value + ' ';
}

std::string noun()
{
  Token t = ts.get();
  cout << "n " << t.value << '\n';

  return t.value + ' ';
}

std::string verb()
{
  Token t = ts.get();
  cout << "v " << t.value << '\n';

  return t.value + ' ';
}

build & run:

g++ -std=c++20 -O2 -Wall -pedantic ./ch_06/main_p193.cpp && ./a.out

PrevUpNext

Edit
Pub: 16 Mar 2023 11:37 UTC
Edit: 02 May 2023 20:50 UTC
Views: 598