Checking proper English sentences of user's input with grammar using C++ Write a program that checks if a sentence is correct according to the
  “English” grammar in §6.4.1. Assume that every sentence is terminated
  by a full stop (.) surrounded by whitespace. For example, birds fly
  but the fish swim . is a sentence, but birds fly but the fish swim
  (terminating dot missing) and birds fly but the fish swim. (no space
  before dot) are not. For each sentence entered, the program should
  simply respond “OK” or “not OK.” Hint: Don’t bother with tokens; just
  read into a string using >>.


#include &lt;string&gt;
#include &lt;iostream&gt;
using namespace std;

string str;

void putback(string s) {
    str = s;
}

string verb() {
    if (str == "rules" || str == "fly" || str == "swim") {
        return str + ' ';
    }
    else 
        return "";
}

string noun() {
    if (str == "birds" || str == "fish" || str == "C++") {
        return str + ' ';
    }
    else 
        return "";
}

string article() {
    if (str == "the") {
        string temp = str;
        cin &gt;&gt; str;
        return temp + ' ';
    }
    else 
        return "";
}

string conjunction() {
    if (str == "and" || str == "or" || str == "but") {
        return str + ' ';
    }
    else 
        return "";
}

string l;
string sentence() {
    l += article();
    if (noun() == "") {
        cerr &lt;&lt; "NOT OK";
        return "";
    }
    else {
        l += noun();
        cin &gt;&gt; str;
        string temp = verb();
        if (temp == "") {
            cerr &lt;&lt; "NOT OK";
            return "";
        }
        else {
            l += temp;
            cin &gt;&gt; str;
            if (str == "") {
                cerr &lt;&lt; "NOT OK";
                return " ";
            }
            else if (str == ".") {
                l += ".";
                return l;
            }
            else {
                if(conjunction() == "") {
                    cerr &lt;&lt; "NOT OK";
                }
                else {
                    l += str + ' ';
                    cin &gt;&gt; str;
                }
                return sentence();
            }
        }
    }
}

int main() 
try 
{
    string sen = " ";
    while (cin) {
        cin &gt;&gt; str;
        sen = sentence();
        if (str == ".") {
            cout &lt;&lt; sen &lt;&lt; '\n';
        }
    }
    //keep_window_open();
}
catch (exception&amp; e) 
{
    cerr &lt;&lt; "error: " &lt;&lt; e.what() &lt;&lt; '\n';
    //keep_window_open();
    return 1;
}
catch (...) 
{
    cerr &lt;&lt; "Oops: unknown exception!\n";
    //keep_window_open();
    return 2;
}



The Grammar:
Sentence:
          Noun Verb                                   // e.g., C++ rules
          Article Noun Verb
          Sentence Conjunction Sentence   // e.g., Birds fly but fish swim
Conjunction:
          "and"
          "or"
          "but"
Article:
          "the"
Noun:
          "birds"
          "fish"
          "C++"
Verb:
          "rules"
          "fly"
          "swim"



This is perfectly working code. Is there anything I can improve on for my code? Do you think using global variables in this case is okay? Even for whether I have proper variable names is worth commenting. This question is from this webpage, exercise 6 at the very bottom.
You could learn how to use bison. It designed specifically for this.

Boiler plate for flex/bison project:

Eng.l

%option c++

%{
#define IN_EXPR_LEXER
#include "EngYac.hpp"
%}

SpaceChar     [ \t]
Space         {SpaceChar}+
SpaceTerm     {SpaceChar}|&lt;&lt;EOF&gt;&gt;
FullStop      {SpaceChar}\.{SpaceTerm}

%%

and                     {return yy::parser::token::Conjunction;}
or                      {return yy::parser::token::Conjunction;}
but                     {return yy::parser::token::Conjunction;}

the                     {return yy::parser::token::Article;}

birds                   {return yy::parser::token::Noun;}
fish                    {return yy::parser::token::Noun;}
C\+\+                   {return yy::parser::token::Noun;}

rules                   {return yy::parser::token::Verb;}
fly                     {return yy::parser::token::Verb;}
swim                    {return yy::parser::token::Verb;}

{FullStop}              {return yy::parser::token::FullStop;}

{Space}                 {/*Ignore*/}
.                       {std::cerr &lt;&lt; "Error unknown character\n";}

%%

int yyFlexLexer::yywrap(void)
{
    return 1;
}


int yylex(int* /*type*/, yyFlexLexer&amp; lexer)
{
    return lexer.yylex();
}


Eng.y

%{
    #ifndef IN_EXPR_LEXER
    #include &lt;FlexLexer.h&gt;
    #endif
    int yylex(int* type, yyFlexLexer&amp; lexer);
%}
%skeleton "lalr1.cc"
%defines
%parse-param {yyFlexLexer&amp; lexer}
%lex-param   {yyFlexLexer&amp; lexer}

%token      Noun
%token      Verb
%token      Article
%token      Conjunction
%token      FullStop

%%
Input:      Sentence FullStop    

Sentence:   Noun Verb
        |   Article Noun Verb
        |   Sentence Conjunction Sentence


%%

void yy::parser::error(yy::location const&amp;, std::string const&amp; msg)
{
    std::cerr &lt;&lt; "Error: " &lt;&lt; msg &lt;&lt; "\n";
}


main.cpp

#include &lt;FlexLexer.h&gt;
#include "EngYac.hpp"

int main()
{
    yyFlexLexer     lexer(&amp;std::cin, &amp;std::cout);
    yy::parser      parser(lexer);

    std::cout &lt;&lt; (parser.parse() ? "FAIL" : "OK") &lt;&lt; "\n";
}


Makefile

FLEX_SRC    = $(wildcard *.l)
BISON_SRC   = $(wildcard *.y)
FLEX_CPP    = $(patsubst %.l, %Lex.cpp, $(FLEX_SRC))
BISON_CPP   = $(patsubst %.y, %Yac.cpp, $(BISON_SRC))

SRC         = $(filter-out $(BISON_CPP), $(filter-out $(FLEX_CPP), $(wildcard *.cpp))) $(FLEX_CPP) $(BISON_CPP)
OBJ         = $(patsubst %.cpp,%.o,$(SRC))


eng:       $(OBJ)
    g++ -o eng -O3 -Wall -Wextra -Werror $(OBJ)

clean:
    rm EngLex.cpp EngYac.cpp EngYac.hpp location.hh position.hh stack.hh $(OBJ) expr


$(OBJ): $(FLEX_CPP) $(BISON_CPP)

%Lex.cpp:       %.l
    flex -o $*Lex.cpp $^

%Yac.cpp:       %.y
    bison -o $*Yac.cpp $^


Usage:

&gt; make
&gt; echo "birds rules but fish swim." | ./eng

OK
&gt; echo "A test of English." | ./eng 
A test of English
Error: syntax error
FAIL