Please send questions to
st10@humboldt.edu .
another CFG:
S -> 0S1 | epsilon
* for an epsilon production, you replace the non-terminal
with the empty string -- (you don't type the epsilon in
the derivation step result...!) (nor a space)
...essentially, replace the non-terminal with nothing
* for example, here is a derivation using this CFG:
S => 0S1
=> 00S11
=> 000S111
=> 000111
...this grammar describes the language
{w | w is 0^n1^n } where n >= 0
(a number of 0's followed by that same number of 1's)
(which is a CFL that is not a regular language...)
Backus-Naur Form (BNF)
* in the 1950's, while linguists were studying
CFG's, computer scientists began to describe
programming languages using BNF,
(Hopcroft, Ullman, p. 78) "which is the context-free
grammar notation with minor changes in format and some
shorthand"
* BIG step in simplifying the definition and
description of programming language syntax!
BNF is a meta-language
(language describing a language)
(named after Backus, Naur in their work describing
Algol-58, Algol-60)
* syntactic categories of strings -> non-terminals
write angle brackets around a descriptive name
for the synactic category
<decimal fraction>
<while-statement>
<statement>
<identifier>
<named constant>
you follow the syntactic category you are describing
(or one rule in its description) with
::=
can be read as, "is defined as"
and on the right-hand-side (RHS) of the ::=,
you concatenate the terminals and syntactic categories
used in that definition, if you will
And | can be used to "condense" two rules into one
with the same LHS
<integer> ::= +<unsigned integer> | -<unsigned integer>
| <unsigned integer>
* here, + and - are terminals
consider <unsigned integer>
* <unsigned integer> ::= <digit> | <digit><unsigned integer>
<digit> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
* describing an expression in a simple language...
<expr> ::= <expr> + <expr> |
<expr> * <expr> |
<expr> - <expr> |
<expr> / <expr> |
(<expr>) |
<id>
<expr> => <expr> + <expr>
=> (<expr>) + <expr>
=> (<expr> * <expr>) + <expr>
=> (<id> * <expr>) + <expr>
=> (<id> * <id>) + <expr>
=> (<id> * <id>) + <id>
another form of a derivation is a derivation tree
(sometimes called a parse tree)
root: is the start non-terminal
(label the root node with the desired start
non-terminal)
for each node in the tree,
if that node is labeled with the non-terminal A,
then its children could be X1 X2 ... Xn
only if there is a rule A -> X1 X2 ... Xn
note that, when you do this,
eventually you'll see that the leaves of the
resulting derivation tree are terminals,
all the interior nodes are non-terminals,
and if you read the leaves left-to-right,
that's a string in the language defined by
that grammar;