Semantic error recovery once again requires judgment on the part of the
grammar-writer. For example, an assignment expression may be syntactically
defined as
        verb(
    expr '=' expr
        )
    The assignment operator's left-hand side must be a so-called
em(lvalue). An em(lvalue) is simply an addressable location, like a variable's
identifier, a dereferenced pointer expression or some other
address-expression. The right-hand side is a so-called em(rvalue): this may be
any value: any expression will do.

    A rule like the above leaves room for many different semantic errors:
    itemization(
    it() Since the rule's LHS equals tt(expr), em(any) expression is accepted
by the parser. E.g.,
        verb(
    3 = 12
        )
    So, the action associated with this rule should em(check) whether the
expression's left-hand side is actually an lvalue. If not, a em(semantic)
error should be reported;
    it() In a typed language (like bf(C++)), not all assignments are
possible. E.g., it is not acceptable to assign a bf(std:string) value
to a bf(double) variable. When conflicting types are used, a em(semantic)
error should be reported;
    it() In a language requiring variables to be defined or declared before
they are used (like bf(C++)) the parser should check whether a variable is
actually defined or declared when it is used in an expression. If not, a
em(semantic) error should be reported
    )
    A parser that should be able to detect semantic errors normally uses a
counter counting the number of semantic errors, e.g., tt(size_t
d_nSemanticErrors). It may be possible to test this counter's value once the
input has been parsed, calling tt(ABORT()) (see section ref(PRIVMEM)) if the
counter isn't zero anymore. When the grammar's start symbol itself has
multiple alternatives, it is probably easiest to augment the grammar with an
additional rule, becoming the augmented grammar's start symbol which simply
calls the former start symbol. For example, if tt(input) was the name of the
original start-symbol, augment the grammar as follows to ensure a
bf(PARSE_ABORT) return value of the tt(parse()) member when either syntactic
or semantic errors were detected:
        verb(
    semantic_input:                 // new start-symbol
        input
        {
            if (d_nSemanticErrors)  // return PARSE_ABORT
                ABORT();            // on semantic errors too.
        }
        )
    Returning from the parser's tt(parse()) member the number of syntactic
and semantic errors could then be printed, whereupon the program might
terminate. 
