home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 8 Other
/
08-Other.zip
/
lr.zip
/
LR_GUIDE.INF
(
.txt
)
< prev
next >
Wrap
OS/2 Help File
|
1993-05-15
|
131KB
|
5,701 lines
ΓòÉΓòÉΓòÉ 1. QuickStart ΓòÉΓòÉΓòÉ
Example of how to compile and use a grammar.
1. Open an OS2 window and create a directory on your hard drive, preferably
C:\LR. Make this the current directory.
2. Copy the contents of the installation diskette into the current directory.
COPY A:*
assuming A: is the drive you are installing from.
3. From the command line, enter:
LRP LR_SQL.GR LR_SQL.SQL
This will compile the SQL grammar in LR_SQL.GR, and parse the SQL
statements in LR_SQL.SQL. The SQL grammar compilation takes 23 seconds on
a 486dx50 with 20M. Subsequently you may enter:
LRP LR_SQL.LRS LR_SQL.SQL
to reuse the compiled grammar in the .LRS file.
4. Enter:
EPM LR_SQL.PRS
to view the parse tree produced by LR. You may have to scroll down to see
it.
5. To create your own grammar, copy LR_SQL.GR to another .GR file and edit the
grammar rules. Optionally, place sample source statements into another
file. Rerun LRP, whose syntax is:
LRP <grammar.gr | grammar.lrs> [text]
a. Grammar file to be compiled (.GR) or compiled grammar (.LRS)
b. Optional text file containing source statements to be parsed.
6. Program LR_SQL.C (and its make file LR_SQL.MAK), show you how to request LR
processing from a program by:
a. Including the generated .STR and .CC files generated from your grammar
b. Specifying semantic routines for each nonterminal you wish to process
c. Filling out structure LRX_REQ to request a parse.
d. Invoking procedure lrx_req to perform a parse.
7. If you have wasted hours being frustrated by LEX and YACC, relax! You know
more than enough to use LR. Just remember, there is:
a. No lexical phase, as lexical analysis is handled by string non terminals
in the grammar, which concatenate their terminals to form lexical
tokens.
b. No semantic actions to be imbedded into the grammar
c. No generated C code to compile and link
d. No time wasted, - our largest grammar - SQL - compiles in 23 seconds!
8. Select this line to get addressability to the most useful chapters in this
guide.
9. Thank you for taking the time to examine LR. Non stop support,
maintenance, enhancements, and further development is all provided free via
your Transcendental Automation Support Representative: Phil Brenan, at
Compuserve 71022,3620.
10. Get free hardware everytime you sell a copy of LR! E-mail your techical
support representative for details.
ΓòÉΓòÉΓòÉ 2. Introduction. ΓòÉΓòÉΓòÉ
This guide discusses the production of an LR parser for a given language from
the context free grammar representing the language. A solution to the
difficult problem of designing a parser regardless of the source language or
target machine is presented. To make the guide self-contained a few basic
concepts are introduced, as well as the terminology of parser design. All
necessary language facilities, data structures, macros, procedures and
technical details required to parse your own language are presented in this
guide.
ΓòÉΓòÉΓòÉ 2.1. LR by Transcendental Automation ΓòÉΓòÉΓòÉ
LR may be used to build complete front-ends for programming language
compilation systems, partial front ends for recognizing key elements within a
language (for example: host variables within a SQL SELECT statement), as well
as text processors of many sorts from simple text editors to sophisticated
pattern recognition programs.
Designing a language to deliver the functionality of your product is well worth
the effort, as it gives your users a simple, flexible means to combine the
features of your products in an exponential number of ways.
ΓòÉΓòÉΓòÉ 2.2. LR(k) parser choice rational ΓòÉΓòÉΓòÉ
Their are a variety of technical reasons to use LR parsing:
o LR-parsers can be constructed for a wide range of languages whose syntactic
structure can be defined by a context-free grammar;
o The LR parsing method is more general than any of the other common
shift-reduce techniques, yet it can be implemented with the acceptable degree
of efficiency;
o LR-parsers can detect syntactic errors as soon as it is possible to do so on
a left-to-right scan of the input.
ΓòÉΓòÉΓòÉ 2.3. Brief overview of LR usage ΓòÉΓòÉΓòÉ
Usage of LR assumes following steps:
1. Source language grammar specification.
2. LR-parsing automaton construction.
3. Source text parsing with parse-tree construction.
4. Syntax-directed semantic processing of parse tree.
5. Error message interpretation as necesssary
ΓòÉΓòÉΓòÉ 2.4. LR-parser host language ΓòÉΓòÉΓòÉ
The host language for LR is at present C. The LR library, data structures,
macros and procedures needed for the use of LR are all in C, so you will need
to be familiar with the C language.
ΓòÉΓòÉΓòÉ 2.5. LR - (LEX+YACC) technologies comparison ΓòÉΓòÉΓòÉ
A brief comparison with the infamous LEX/YACC duo may serve to high light some
of the reasons for choosing to use LR instead, while providing an overview of
the key features of LR:
One phase LR does not have separate lexical and syntactic phases. It
is well known that context free grammars (YACC) can
represent regular expressions (LEX), so why have two
separate phases? Having only one representation to
maintain means less debugging of the resulting grammar.
LR(k) versus LALR(1) An LR(k) grammar is more powerful than an LALR(1) and
permits the poarsing of a wider class of languages.
No imbeds LR does not imbed semantic actions. This has multiple
benefits. It means that one grammar can drive several sets
of semantic actions, eliminating the need to maintain
multiple versions of the same grammar which are identical
except for their semantic actions.
No C Code LR does not produce C code. This means that you can
construct grammars dynamically if you wish and compile them
as necessary. The actual output of LR is a relocatable set
of tables which describe the actions of the parser.
Parse tree LR produces an in-memory parse tree. LR comes complete
with procedures for navigating the parse tree. One
immediate benefit, the parse tree can be printed, to show
you the syntactic structure of your input language
statements.
Analysis LR provides a detailed error analysis of a failing parse,
which can be decoded by a user supplied routine, or printed
via the standard error processing procedure.
ΓòÉΓòÉΓòÉ 3. Parsing brief overview ΓòÉΓòÉΓòÉ
This chapter introduces many of the basic concepts of LR parsing.
In order for LR to parse a language, it must be described by a context-free
grammar. This means that you specify one or more syntactic aggregations and
give rules for constructing them from their parts. For example, in the C
language, one kind of aggregation is called an expression. One rule for making
an expression might be, An expression can be made of a minus sign and another
expression. Another would be, An expression can be an integer. As you can
see, rules are often recursive, but there must be at least one rule which leads
out of the recursion.
The most common formal system for presenting such rules is Backus-Naur Form or
BNF. Any grammar expressed in BNF is a context-free grammar. The input to LR
is essentially machine-readable BNF.
Not all context-free languages can be handled by LR, only those that are LR(k).
In brief, this means that it must be possibly to tell how to parse any portion
of an input string with just a k character of look-ahead. See Reduce/Reduce
Conflicts, for more information on this.
In the formal grammatical rules for a language, each kind of syntactic unit or
aggregation is named by a symbol. Those which are built by aggregating smaller
constructs according to grammatical rules are called nonterminal symbols; those
which cannot be subdivided are called terminal symbols. We call a piece of
input corresponding to a single terminal symbol a token, and a piece
corresponding to a single nonterminal symbol an aggregation.
We can use the C language as an example of what symbols, terminal and
nonterminal, mean.
The terminal symbols of a grammar for C include the various keywords: if,
return, const, static, int, char and literals: asterisk, semicolon, open-paren,
close-paren, open-brace, close-brace and many more.
Here is a simple C function subdivided into tokens:
int // keyword int
square (x) // identifier, open-paren
// identifier, close-paren
int x; // keyword int, identifier, semicolon
{ // open-brace
return x * x; // keyword return, identifier
// asterisk, identifier, semicolon
} // close-brace
The syntactic aggregations of C include the identifier, the expression, the
statement, the declaration, and the function definition. These are represented
in the grammar of C by nonterminal symbols expression, statement, declaration
and function definition. The full grammar uses dozens of additional language
constructs, each with its own nonterminal symbol, in order to express the
meanings of these four. The example above is a function definition; it
contains one declaration, and one statement. In the statement, each x is an
expression and so is x * x.
Each nonterminal symbol must have grammatical rules showing how it is made out
of simpler constructs. For example, one kind of C statement is the return
statement; this would be described with a grammar rule which reads informally
as follows:
A statement can be made of a return keyword, an expression and a semicolon.
There would be many other rules for statement, one for each kind of statement
in C.
One nonterminal symbol must be distinguished as the special one which defines a
complete utterance in the language. It is called the start symbol. In a
compiler, this means a complete input program. In the C language, the
nonterminal symbol sequence of definitions and declarations plays this role.
For example, 1 + 2 is a valid C expression---a valid part of a C program---but
it is not valid as an entire C program. In the context-free grammar of C, this
follows from the fact that expression is not the start symbol.
The LR parser reads a sequence of tokens as its input, and groups the tokens
using the grammar rules. If the input is valid, the end result is that the
entire token sequence reduces to a single aggregation whose symbol is the
grammar's start symbol. If we use a grammar for C, the entire input must be a
sequence of definitions and declarations. If not, the parser reports a syntax
error.
A formal grammar is a mathematical construct. To define the language for LR,
you must write a file expressing the grammar in LR syntax: a LR grammar file .
A nonterminal symbol in the formal grammar is represented in LR input as an
identifier, like an identifier in C.
A terminal symbol is represented as a character literal, just like a C
character constant.
The grammar rules also have an expression in LR syntax. For example, here is
the LR rule for a C return statement. The semicolon in quotes is a terminal,
representing part of the C syntax for the statement.
stmt (return expr semicolon)
return ('return')
semicolon (';')
A formal grammar selects tokens only by their classifications: for example, if
a rule mentions the nonterminal symbol integer constant, it means that any
integer constant is grammatically valid in that position. The precise value of
the constant is irrelevant to how to parse the input: if x+4 is grammatical
then x+1 or x+3989 is equally correct.
The precise value is very important for what the input means once it is parsed.
Therefore, each token in a LR grammar has a semantic value.
The semantic value has all the rest of the information about the meaning of the
token, such as the value of an integer.
(A token such as ',' which is just punctuation doesn't need to have any
semantic value.)
When the parser accepts the token, it keeps track of the token's semantic
value.
Each aggregation can also have a semantic value as well as its nonterminal
symbol. For example, in a compiler for a programming language, an expression
typically has a semantic value that is a tree structure describing the meaning
of the expression.
In order to be useful, a program must do more than parse input: it must also
produce some output based on the input. In an LR grammar, a grammar rule can
have an action made up of a C procedure.
Most of the time, the purpose of an action is to compute the semantic value of
the whole construct from the semantic values of its parts. For example,
suppose we have a rule which says an expression can be the sum of two
expressions. When the parser recognizes such a sum, each of the subexpressions
has a semantic value which describes how it was built up. The action for this
rule should create a similar sort of value for the newly recognized larger
expression.
For example, here is a rule that says an expression can be the sum of two
subexpressions:
expr (expr plus expr1)
expr1 (expr)
plus ('+')
The action says how to produce the semantic value of the sum expression from
the values of the two subexpressions.
When you run LR, you give it an LR grammar file as input. The output is a
parsing table that enables you to parse the language described by the grammar.
This parsing table with the LR utility is called a LR parser that becomes part
of your program.
The job of the LR parser is to group tokens into aggregations according to the
grammar rules---for example, to build identifiers and operators into
expressions. As it does this, it creates a persistent parse tree which shows
the grammar rules which have been applied. Subsequently, this parse tree may
be traversed to drive semantic processing.
The LR parser work as follows:
As LR parser reads tokens, it pushes them onto a stack. The stack is called the
parser stack. Pushing a token is traditionally called shifting.
The stack does not always have an element for each token read. When the last
tokens and aggregations shifted match the components of a grammar rule, they
can be combined according to that rule. This is called reduction. Those
tokens and aggregations are replaced on the stack by a single aggregation whose
symbol is the result (left hand side) of that rule. The nonterminals on the
right hand-side are suspended from the nonterminal on the left hand side to
create a node in the persistant parse tree.
The parser tries, by shifts and reductions, to reduce the entire input down to
a single aggregation whose symbol is the grammar's start-symbol
This kind of parser is known in the literature as a bottom-up parser.
ΓòÉΓòÉΓòÉ 3.1. Context-free grammars ΓòÉΓòÉΓòÉ
A widely used technique to specify the syntactic structure of a language is a
context free grammar. A grammar gives a precise, yet easy to understand,
syntactic specification for the text of a statement in the language. An
efficient parser can be constructed automatically from a properly designed
grammar. A grammar imparts a structure to the text that is useful for deciding
the appropriate semantic processing and for the detection of errors.
LR supplies a special notation for defining context free grammars, it is called
"Grammar Definition Language" or GDL. (GDL).
Context free grammars consist of one or more productions.
The productions describe how a syntactically correct statement in the language
specified by the grammar, may be produced from the START symbol of the grammar.
Each productions has a left hand side (LHS) and a right hand side (RHS).
The left hand side of a production is a single nonterminal.
The right hand side of a production is either one or more nonterminals, or one
or more terminals.
It is customary to separate the LHS from the RHS side of a production by the
use of some arbitrary symbol like ->, although this is only to aid readability.
In GDL, the RHS is parenthesesed and placed after the LHS.
ΓòÉΓòÉΓòÉ 3.1.1. Productions ΓòÉΓòÉΓòÉ
The productions describe how a syntactically correct statement in the language
specified by the grammar, may be produced from the START symbol of the grammar.
Each productions have a left hand side (LHS) and a right hand side (RHS).
The left hand side of a production is a single nonterminal.
The right hand side of a production is either one or more nonterminals, or one
or more terminals.
It is customary to separate the LHS from the RHS side of a production by the
use of some arbitrary symbol like ->, although this is only to aid readability.
In GDL, the RHS is parenthesesed and placed after the LHS.
ΓòÉΓòÉΓòÉ 3.1.2. Right hand side of a production (RHS) ΓòÉΓòÉΓòÉ
The right hand side of a production is either one or more nonterminals, or one
or more terminals.
(It is possible to formulate context free grammars with RHS's consisting of a
mixture of nonterminals and terminals, however, there is no loss in generality
in making this slight restriction, and it does make processing the resulting
parse tree simpler.)
ΓòÉΓòÉΓòÉ 3.1.3. The left hand side of a production (LHS) ΓòÉΓòÉΓòÉ
The left hand side of a production is a single nonterminal.
The same nonterminal may occur as the LHS of several production.
ΓòÉΓòÉΓòÉ 3.1.4. Terminals ΓòÉΓòÉΓòÉ
Terminals are character constants describing the characters that may appear in
a given context. In GDL, terminals are always designated by quoted strings.
ΓòÉΓòÉΓòÉ 3.1.5. Nonterminals ΓòÉΓòÉΓòÉ
Nonterminal describe the class of constituents of the language. A nonterminal
is described in terms of other nonterminals and terminals. Such a description
of a nonterminal is called a production. In GDL, nonterminals are designated by
any sequence of symbols which does not contain quotes, blanks, or parenthesis.
In GDL, a given nonterminal may appear at most once in the RHS of a single
production. This is not a severe restriction, as you can use other productions
to generate several names for the same underlying nonterminal. This
restriction serves to simplify the processing of the parse trees constructed by
the parser.
One nonterminal is designated the start nonterminal. In GDL,this is the first
nonterminal encountered in the rules section.
ΓòÉΓòÉΓòÉ 3.1.6. Start nonterminal ΓòÉΓòÉΓòÉ
One nonterminal is selected as the start symbol, and it denotes the language of
your interest. In GDL, this is the first nonterminal encountered in the rules
section.
ΓòÉΓòÉΓòÉ 3.2. LR(k) parsing and parse trees ΓòÉΓòÉΓòÉ
The job of the LR parser is to group tokens into aggregations according to the
grammar rules---for example, to build identifiers and operators into
expressions. As it does this, it builds a persistant parse tree which may then
be traversed to drive semantic processing.
The LR parser work as follows:
As LR parser reads tokens, it pushes them onto a stack. Pushing a token is
traditionally called shifting.
But the stack does not always have an element for each token read. When the
last tokens and aggregations shifted match the components of a grammar rule,
they can be combined according to that rule. This is called reduction. Those
tokens and aggregations are replaced on the stack by a single aggregation whose
symbol is the result (left hand side) of that rule. The nonterminals on the
right hand-side are suspended from the nonterminal on the left hand side to
create a node in the persistant parse tree.
The parser tries, by shifts and reductions, to reduce the entire input down to
a single aggregation whose symbol is the grammar's start-symbol
On a logical level the output of the parsing of a source text is some
representation of a parse tree, that making explicit the hierarchical syntactic
structure of the source text that is implied by the grammar.
Each interior node of the parse tree corresponds to some nonterminal A and the
children of the node correspond, from left to right, to the symbols in the
right side of the production by which this A was replaced in the derivation.
For example, if A(X Y Z) is a production used at some step of a derivation,
then the parse tree for that derivation will have the subtree:
A
Γöé
ΓöîΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓö╝ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÉ
Γöé Γöé Γöé
X Y Z
A(X Y Z) parse tree graphical representation.
Sometimes another equivalent graphical representation for parse tree will be
used:
A
Γöé
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ X
Γö£ΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ Y
ΓööΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ Z
Another parse tree graphical representation.
ΓòÉΓòÉΓòÉ 3.3. Grammar conflicts ΓòÉΓòÉΓòÉ
A grammars that has certain ambiguities are not allowed in LR. Such ambiguities
are known as reduce/reduce conflicts.
A reduce/reduce conflict occurs if there are two or more rules that apply to
the same sequence of input. This usually indicates a serious error in the
grammar.
A situation, where either a shift or a reduction would be valid, is called a
shift/reduce conflict. LR is designed to resolve these conflicts by choosing to
shift, unless otherwise directed by SECONDARY declarations.
ΓòÉΓòÉΓòÉ 3.3.1. Shift/Reduce conflicts ΓòÉΓòÉΓòÉ
The LR parser does not always reduce immediately as soon as the last n tokens
and aggregatings match a rule. This is because such a simple strategy is
inadequate to handle most languages. Instead, when a reduction is possible,
the parser sometimes looks ahead at the next token in order to decide what to
do.
When a token is read, it is not immediately shifted; first it becomes the
look-ahead token, which is not on the stack. Now the parser can perform one or
more reductions of tokens and aggregatings on the stack, while the look-ahead
token remains off to the side. When no more reductions should take place, the
look-ahead token is shifted onto the stack. This does not mean that all
possible reductions have been done; depending on the token type of the
look-ahead token, some rules may choose to delay their application.
Here is a simple case where look-ahead is needed. These rules define
expressions which contain binary addition operators and postfix unary factorial
operators !, and allow parentheses for aggregating.
LR (
NAME('shf1')
TITLE('Shift/Reduce 1')
Struct
Print
Rules
(
expr (term plus expr)
( term )
term (op expr cl)
( term fct )
( NUMBER )
plus ('+')
op ('(')
cl (')')
fct ('!')
NUMBER ('123456789'(choice))
)
)
Suppose that the tokens 1 + 2 have been read and shifted; what should be done?
If the following token is ) , then the first three tokens must be reduced to
form an expr . This is the only valid course, because shifting the ) would
produce a sequence of symbols term ')', and no rule allows this. If the
following token is ! , then it must be shifted immediately so that 2 ! can be
reduced to make a term . If instead the parser were to reduce before shifting,
1 + 2 would become an expr. It would then be impossible to shift the ! because
doing so would produce on the stack the sequence of symbols expr'!'. No rule
allows that sequence.
For this grammar LR parser, if input text is 1+2! ,produce the following tree:
expr
Γö£ΓöÇterm
Γöé ΓööΓöÇNUMBERΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ1
Γö£ΓöÇplusΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ+
ΓööΓöÇexpr
ΓööΓöÇterm
Γö£ΓöÇterm
Γöé ΓööΓöÇNUMBERΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ2
ΓööΓöÇfctΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ!
Suppose we are parsing a language which has if-then and if-then-else
statements, with a of rules like this:
LR
(
NAME(IF_STMT)
TITLE('If-statement')
RULES
(
if_stmt0 ( if_stmt1 )
if_stmt0 ( if_stmt2 )
if_stmt1 (_IF expr _THEN stmt )
if_stmt2 (_IF expr _THEN stmt _ELSE stmt1 )
stmt ( stmt1 )
stmt1 ( operator )
( if_stmt0 )
operator ('operator'(MIXED))
_IF ( 'if' )
_THEN ( 'then' )
_ELSE ( 'else' )
expr (term plus expr)
( term )
term (op expr cl)
( term fct )
( NUMBER )
plus ('+')
op ('(')
cl (')')
fct ('!')
NUMBER ('123456789'(choice))
)
string ( _IF _THEN _ELSE )
mixed ( _IF _THEN _ELSE )
)
(Here we assume that _IF , _THEN and _ELSE are terminal symbols for specific
keyword tokens.)
When the _ELSE token is read and becomes the look-ahead token, the contents of
the stack (assuming the input is valid) are just right for reduction by the
first rule. But it is also legitimate to shift the _ELSE, because that would
lead to eventual reduction by the second rule.
This situation, where either a shift or a reduction would be valid, is called a
shift/reduce conflict. LR is designed to resolve these conflicts by choosing
to shift, unless otherwise directed by SECONDARY declarations.
Since the parser prefers to shift the _ELSE , the result is to attach the
else-clause to the innermost if-statement.
For input text:
if 1
then
if 2
then operator
else operator
LR parser produce the following tree:
if_stmt0
ΓööΓöÇif_stmt1
Γö£ΓöÇ_IFΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇif
Γö£ΓöÇexpr
Γöé ΓööΓöÇterm
Γöé ΓööΓöÇNUMBERΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ1
Γö£ΓöÇ_THENΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇthen
ΓööΓöÇstmt
ΓööΓöÇstmt1
ΓööΓöÇif_stmt0
ΓööΓöÇif_stmt2
Γö£ΓöÇ_IFΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇif
Γö£ΓöÇexpr
Γöé ΓööΓöÇterm
Γöé ΓööΓöÇNUMBERΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ2
Γö£ΓöÇ_THENΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇthen
Γö£ΓöÇstmt
Γöé ΓööΓöÇstmt1
Γöé ΓööΓöÇoperatorΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇoperator
Γö£ΓöÇ_ELSEΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇelse
ΓööΓöÇstmt1
ΓööΓöÇoperatorΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇoperator
But if the parser chose to reduce when possible rather than shift, the result
would be to attach the else-clause to the outermost if-statement:
if_stmt0
ΓööΓöÇif_stmt2
Γö£ΓöÇ_IFΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇif
Γö£ΓöÇexpr
Γöé ΓööΓöÇterm
Γöé ΓööΓöÇNUMBERΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ1
Γö£ΓöÇ_THENΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇthen
Γö£ΓöÇstmt
Γöé ΓööΓöÇstmt1
Γöé ΓööΓöÇif_stmt0
Γöé ΓööΓöÇif_stmt1
Γöé Γö£ΓöÇ_IFΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇif
Γöé Γö£ΓöÇexpr
Γöé Γöé ΓööΓöÇterm
Γöé Γöé ΓööΓöÇNUMBERΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ2
Γöé Γö£ΓöÇ_THENΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇthen
Γöé ΓööΓöÇstmt
Γöé ΓööΓöÇstmt1
Γöé ΓööΓöÇoperatorΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇoperator
Γö£ΓöÇ_ELSEΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇelse
ΓööΓöÇstmt1
ΓööΓöÇoperatorΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇoperator
The conflict exists because the grammar as written is ambiguous: either parsing
of the simple nested if-statement is legitimate. The established convention is
that these ambiguities are resolved by attaching the else-clause to the
innermost if-statement; this is what LR accomplishes by choosing to shift
rather than reduce. (It would ideally be cleaner to write an unambiguous
grammar, but that is very hard to do in this case.)
Another situation where shift/reduce conflicts appear is in arithmetic
expressions. Here shifting is not always the preferred resolution.
Consider the following ambiguous grammar fragment (ambiguous because the input
1+2*3 can be parsed in different ways):
LR
(
NAME(A_EXPR1)
TITLE('Arithmetic expressions 1.')
RULES
(
expr ( add_expr )
( mult_expr )
( number )
add_expr ( expr add_oprt expr1 )
mult_expr ( expr mult_oprt expr1 )
expr1 ( expr )
add_oprt ('+-' (choice))
mult_oprt ('*/' (choice))
number ('123456789'(choice))
)
)
Suppose the parser has seen the tokens 1+2 should it reduce them via the rule
for the addition operator? It depends on the next token. Of course, if the
next token is ), we must reduce; shifting is invalid because no single rule can
reduce the token sequence *2 or anything starting with that. But if the next
token is * or \ , we have a choice: either shifting or reduction would allow
the parse to complete, but with different results:
Firth way of parsing 1+2*3 for the grammar A_EXPR1:
expr
ΓööΓöÇadd_expr
Γö£ΓöÇexpr
Γöé ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ1
Γö£ΓöÇadd_oprtΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ+
ΓööΓöÇexpr1
ΓööΓöÇexpr
ΓööΓöÇmult_expr
Γö£ΓöÇexpr
Γöé ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ2
Γö£ΓöÇmult_oprtΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ*
ΓööΓöÇexpr1
ΓööΓöÇexpr
ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ3
Second way of parsing 1+2*3 for the grammar A_EXPR1:
expr
ΓööΓöÇmult_expr
Γö£ΓöÇexpr
Γöé Γö£ΓöÇadd_expr
Γöé Γö£ΓöÇexpr
Γöé Γöé ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ1
Γöé Γö£ΓöÇadd_oprtΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ+
Γöé ΓööΓöÇexpr1
Γöé ΓööΓöÇexpr
Γöé ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ2
Γö£ΓöÇmult_oprtΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ*
ΓööΓöÇexpr1
ΓööΓöÇexpr
ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ3
LR parsing algorithm built for input text 1+2*3+4*5 the following parse tree:
expr
ΓööΓöÇadd_expr
Γö£ΓöÇexpr
Γöé ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ1
Γö£ΓöÇadd_oprtΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ+
ΓööΓöÇexpr1
ΓööΓöÇexpr
ΓööΓöÇmult_expr
Γö£ΓöÇexpr
Γöé ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ2
Γö£ΓöÇmult_oprtΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ*
ΓööΓöÇexpr1
ΓööΓöÇexpr
ΓööΓöÇadd_expr
Γö£ΓöÇexpr
Γöé ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ3
Γö£ΓöÇadd_oprtΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ+
ΓööΓöÇexpr1
ΓööΓöÇexpr
ΓööΓöÇmult_expr
Γö£ΓöÇexpr
Γöé ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ4
Γö£ΓöÇmult_oprtΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ*
ΓööΓöÇexpr1
ΓööΓöÇexpr
ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ5
Clearly, then, the choice of shift or reduce should depend on the relative
precedence of the operators.
To resolve the operator precedence problem the grammar must be rewrite as
follows:
LR
(
NAME(A_EXP2)
TITLE('Arithmetic expressions 2.')
RULES
(
expr ( add_expr )
( mult_expr )
add_expr ( mult_expr add_oprt mult_expr1 )
( add_expr add_oprt mult_expr )
mult_expr ( mult_expr mult_oprt mult_expr1 )
( number )
mult_expr1 ( mult_expr )
add_oprt ('+-' (choice))
mult_oprt ('*/' (choice))
number ('123456789'(choice))
)
)
Now input text 1+2*3+3*5 will be parsed as follows:
expr
ΓööΓöÇadd_expr
Γö£ΓöÇadd_expr
Γöé Γö£ΓöÇmult_expr
Γöé Γöé ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ1
Γöé Γö£ΓöÇadd_oprtΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ+
Γöé ΓööΓöÇmult_expr1
Γöé ΓööΓöÇmult_expr
Γöé Γö£ΓöÇmult_expr
Γöé Γöé ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ2
Γöé Γö£ΓöÇmult_oprtΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ*
Γöé ΓööΓöÇmult_expr1
Γöé ΓööΓöÇmult_expr
Γöé ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ3
Γö£ΓöÇadd_oprtΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ+
ΓööΓöÇmult_expr
Γö£ΓöÇmult_expr
Γöé ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ4
Γö£ΓöÇmult_oprtΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ*
ΓööΓöÇmult_expr1
ΓööΓöÇmult_expr
ΓööΓöÇnumberΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ5
ΓòÉΓòÉΓòÉ 3.3.2. Reduce/Reduce conflicts ΓòÉΓòÉΓòÉ
A reduce/reduce conflict occurs if there are two or more rules that apply to
the same sequence of input. This usually indicates a serious error in the
grammar.
For example, here is an erroneous attempt to define a sequence of zero or more
word aggregatings.
LR
(
NAME(SQNS_1)
TITLE('Sequences 1.')
RULES
(
sequence ( word (zero))
( sequence word )
word ('123456789'(choice))
)
)
The error is an ambiguity: there is more than one way to parse a single word
into a sequence. It could be reduced directly via the first rule.
Alternatively, nothing-at-all could be reduced into a sequence via the first
rule, and this could be combined with the word using the second rule.
LR resolves a reduce/reduce conflict by choosing to use the rule that appears
first in the grammar, but it is very risky to rely on this.
LR not promise a grammar of the similar kind.
Sometimes reduce/reduce conflicts can occur that don't look warranted.
Here is an example:
LR
(
NAME(DEF)
TITLE('Definitions.')
RULES
(
def ( param_spec return_spec comma )
param_spec ( type )
( name_list colon type )
return_spec ( type )
( name colon type )
type ( ID )
name ( ID )
name_list ( name )
( name comma name_list )
comma ( ',' )
colon ( ':' )
ID ( 'abcd'(choice) )
)
)
It would seem that this grammar can be parsed with only a single token of
look-ahead: when a param_spec is being read, an ID is a name if a comma or
colon follows, or a type if another ID follows. In other words, this grammar
is LR(1).
In this grammar, two contexts, that after an ID at the beginning of a
param_spec and likewise at the beginning of a return_spec, are similar enough
that LR assumes they are the same. They appear similar because the same set of
rules would be active---the rule for reducing to a name and that for reducing
to a type. LR is unable to determine at that stage of processing that the rules
would require different look-ahead tokens in the two contexts, so it makes a
single parser state for them both. Combining the two contexts causes a
conflict later.
ΓòÉΓòÉΓòÉ 4. Source language grammar specification ΓòÉΓòÉΓòÉ
A text in any language can be viewed as a string of characters chosen from
some set, or alphabet, of characters. The rules that tell us whether a string
is a valid text of the language or not are called the syntax of the language.
Before all accordingly to LR the syntax of source language ( its grammar) must
be specified by Grammar definition language, that allows to specify any LR(k)
grammars.
ΓòÉΓòÉΓòÉ 4.1. Grammar definition language ΓòÉΓòÉΓòÉ
For definition of a context free grammar LR supply a special notation named as
Grammar Definition Language.
The facilities of GDL are represented in following chapters:
o Overall definition structure;
o Production definition;
o Nonterminal options;
o Terminal options;
o Global options;
o Comments.
ΓòÉΓòÉΓòÉ 4.1.1. Overall definition structure ΓòÉΓòÉΓòÉ
Each grammar definition has the following basic layout:
LR
(name (LR_SQL)
title ('SQL V2R3 - Structured Query Language')
path ('c:\mygr\')
save (c:\mygr\prs_tab.lrs)
print (\err\err.lr)
struct (mygr.inc)
rules
(
*here must be placed a production definitions
)
ignore(comma dot colon double)
string(VAR INTEGER STRING)
describe (VAR( 'variable' ))
)
LR The grammar must start with the word LR followed by the
grammar definition enclosed in parenthesis. The keywords
at this level are global in effect, most of them can be
overridden in the individual production definition.
NAME The name of the grammar. This name will be used to provide
the default prefix for file names (*.lrs, *.str, *.n, *.prs
and *.lr files), and for the structures and macros used to
map and navigate the parse tree produced from this grammar.
TITLE The title of the grammar. Used in comments generated by
the parser generator.
PATH The path to subdirectory where a results of parser
generating must be placed. This option is optional.If it is
not presented then results of parser generating is placed
in the default directory.
SAVE This option tells the parser generator where save the
created parsing table (*.lrs file).
PRINT This option tells the LR parser to create <<*.PRS>> file,
in which the parsed text and resulting parse tree is
printed. The name of the PRS-file can be defined in
parenthesis. If the name of the PRS-file is not defined
then the default name is used for it.
STRUCT This option tells the parser generator to create <<*.STR>>
and <<*.N>> files, which are C include files containing the
macro definitions needed for semantic processing of the
parse tree. The names of the STR- and N-files can be
defined in parenthesis. If names of the STR- and N-files
are not defined then default names are used for them.
RULES Here in parenthesis must be placed a few definitions of
productions comprising the grammar of your language.
DESCRIBE Description of a nonterminal. This description is used in
formatting error messages.
Here can be used any nonterminal option with brackets '()' following it. In
these brackets must be list of nonterminals. This usage means that mentioned
nonterminals have this option (attribute) e.g. : OPTIONAL (minus) means that
nonterminal 'minus' will be used as 'minus (optional)' always during
compilation of the grammar.
ΓòÉΓòÉΓòÉ 4.1.2. Production definition ΓòÉΓòÉΓòÉ
Production.
ΓòÉΓòÉΓòÉ 4.1.3. Nonterminal options ΓòÉΓòÉΓòÉ
As described in the previous section, the nonterminals may be followed by
keywords in parenthesis:
ZERO This occurrence of this nonterminal may be repeated zero or
more times.
REPEAT This occurrence of this nonterminal may be repeated one or
more times.
CHOICE Each production for this nonterminal must consist of only
one nonterminal. These nonterminals may be selected in any
order, but either zero or one times only.
IGNORE This occurrence of this nonterminal is not to be indexed in
the parse tree.
OPTIONAL This occurrence of this nonterminal is optional. This can
save writing productions with the same LHS's (sometimes).
SECONDARY This nonterminal is to be tested for expansion only after
all other possible non secondary nonterminals have been
tried. The productions for nonterminals which have been
defined as secondary may only contain terminals on the RHS.
STRING Nonterminals used to construct strings rather than parse
tree entries.
ΓòÉΓòÉΓòÉ 4.1.4. Terminal options ΓòÉΓòÉΓòÉ
Terminals may also be followed by keywords to provide additional information
about their purpose:
MIXED The characters in the terminal will match text in the
statement being parsed regardless of whether they are in
upper or lower case.
'select' (mixed)
would match
Select
SELecT
seLECt
amongst others.
CHOICE The CHOICE keyword allows you to compress definitions of
terminals:
'123456789' (choice)
is equivalent to:
'1'
'2'
'3'
'4'
'5'
'6'
'7'
'8'
'9'
NOT NOT behaves just like CHOICE, except all the characters not
presented in the string are used to generate terminal
definitions:
'''' (not)
Example of NOT terminal option
Defines terminals for every character except the single
quote character. (You may think that this leads to rather
a large number of terminals. LR uses various compression
techniques to overcome this potential problem.)
SEQUENCE This is the default, so you never have to use it unless you
are really picky.
ΓòÉΓòÉΓòÉ 4.1.5. Global options ΓòÉΓòÉΓòÉ
At level of grammar name definition can be used any nonterminal option with
parenthesis following it. In these parenthesis must be list of nonterminals.
This usage means that mentioned nonterminals have this option (attribute) e.g.
: OPTIONAL (minus) means that nonterminal 'minus' will be used as
'minus(optional)' during compilation of the grammar.
The following global nonterminal options are available:
ZERO Nonterminals which will always be repeated zero or more
times.
REPEAT Nonterminals which will always be repeated one or more
times.
CHOICE Rule choices for these nonterminals can be processed zero
or once each in any order.
IGNORE These nonterminals are not included in the parse tree.
OPTIONAL These nonterminals are optional.
SECONDARY These nonterminals are tried after all possible primary
nonterminals. Can only contain terminals on the RHS.
STRING Nonterminals used to construct strings rather than parse
tree nodes.
ΓòÉΓòÉΓòÉ 4.1.6. Comments ΓòÉΓòÉΓòÉ
To place a comment into a grammar definition file the comment control character
'*' must be used.
The * comment control character allows you to place a comment into your file.
The parser generator ignores any text on the same line as the comment control
character from the * character to the end of that line including the *
character. Example
* When the source file is compiled, the text on the
* comment line is ignored.
ΓòÉΓòÉΓòÉ 4.1.7. Grammar definition example 1 ΓòÉΓòÉΓòÉ
*
* In the beginning of grammar definition file must
* be three symbols: 'LR('
*
LR
(
*
* After opening bracket must be set of obligatory and facultative
* options.
*
*
* Option 'NAME' : specifies names (but not extensions) of the files
* that will be created during work of the parser.
*
NAME(SAMPLE)
*
* Option 'TITLE' : defines title for your grammar.
*
TITLE('Sample of grammar')
*
* Option 'STRUCT' : tells the parser to create
* STR-file and N-file.
*
STRUCT
*
* Option 'PRINT' : tells the parser to create LR-file.
*
PRINT
*
* Option 'RULES' : in brackets '()' that follow this option
* you must define your grammar using GDL.
*
RULES
(
* The first <<rule>> after opening bracket '(' is assumed as
* start nonterminal for this grammar
* S( DECLARATION(ZERO) ASSIGN(REPEAT) )
* Nonterminal options:
* ZERO - means that previous nonterminal may repeat
* 0, 1 or more times
* REPEAT - means that previous nonterminal may repeat
* 1 or more times
* Example:
* S ( ASSIGN ASSIGN )
* S ( DECLARATION DECLARATION ASSIGN )
*
S ( ASSIGNS )
*
* Here nonterminal ASSIGNS is defined two times it means that
* this nonterminal may be reduced as
* ( ASSIGNS ASSIGN ) or as ( ASSIGN ).
*
ASSIGNS ( ASSIGNS ASSIGN )
( ASSIGN )
ASSIGN ( IDENTIFIER assign_sign E semi )
E ( ADD )
( SUB )
( T )
ADD ( E plus T )
SUB ( E minus T )
T ( MUL )
( DIV )
( F )
MUL ( T mul F )
DIV ( T div F )
F ( NEG )
( IDENTIFIER )
( FLOAT )
( op E cp )
NEG ( minus F )
*
* Nonterminal options:
* SECONDARY - means that previous nonterminal must be reduced
* only when no other non-secondary nonterminals can
* be reduced.
*
IDENTIFIER ( ALPHA(SECONDARY) ALPHA_NUMERIC (ZERO) )
*
* Nonterminal options:
* OPTIONAL - means that preceding nonterminal may repeat
* 0 or 1 times.
* Example:
* F ( p(optional) q ) means F ( p q ) or F ( q )
*
FLOAT ( point(optional) DIGIT(repeat) EXP )
FLOAT ( DIGIT(repeat) point _DIGIT(zero) EXP )
EXP ( _e_ SIGN(optional) DIGIT(repeat) )
*
* Terminal options:
* CHOICE - means that preceding string (enclosed in '') must be
* replaced with one of it's component
* Example:
* SIGN ('+-'(CHOICE)) means SIGN ('+') or SIGN ('-')
*
SIGN ( '+-'(CHOICE))
ALPHA ( '_QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm'(Choice) )
ALPHA_NUMERIC ( '_QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm0123456789'(Choice) )
minus ( '-' )
plus ( '+' )
div ( '/' )
mul ( '*' )
semi ( ';' )
DIGIT ( '0123456789'(choice) )
_DIGIT ( DIGIT )
_e_ ( 'eE'(choice) )
point ( '.' )
op ( '(' )
cp ( ')' )
assign_sign ( '=' )
)
*
* Here can be used any NONTERMINAL option with brackets '()' following
* it. In these brackets must be list of nonterminals. This usage means
* that mentioned nonterminals have this option (attribute)
* e.g. : OPTIONAL (minus) means that nonterminal 'minus' will
* be used as 'minus(optional)' during compilation of the grammar.
*
IGNORE ( semi op cp assign_sign minus plus mul div mod)
STRING ( IDENTIFIER FLOAT )
OPTIONAL ( EXP )
)
Grammar example 1
ΓòÉΓòÉΓòÉ <hidden> STR-file and N-file ΓòÉΓòÉΓòÉ
#ifndef SQNS_1_PT_INC
#define SQNS_1_PT_INC
/*
______________________________________________________________________________
Nonterminal parse items for SQNS_1
______________________________________________________________________________
*/
typedef struct SQNS_1_PT
{LR_PT *l;
LR_P *p;
LR_PT *key[5];
} SQNS_1_PT;
#define SQNS_1_alpha(_T) ((_T).l = (_T).key[0])
#define SQNS_1_alpha_n 0
#define SQNS_1_end_of_seq(_T) ((_T).l = (_T).key[1])
#define SQNS_1_end_of_seq_n 1
#define SQNS_1_item(_T) ((_T).l = (_T).key[2])
#define SQNS_1_item_n 2
#define SQNS_1_omega(_T) ((_T).l = (_T).key[3])
#define SQNS_1_omega_n 3
#define SQNS_1_sequence(_T) ((_T).l = (_T).key[4])
#define SQNS_1_sequence_n 4
#define SQNS_1_n 5
#endif
For the grammar of a simple sequences the parser generator create following
N-file:
#ifndef SQNS_1_PT_N
#define SQNS_1_PT_N
/*
______________________________________________________________________________
Nonterminal parse items for SQNS_1
______________________________________________________________________________
*/
typedef struct SQNS_1_PT
{LR_PT *l;
LR_P *p;
LR_PT *key[5];
} SQNS_1_PT;
#define SQNS_1_n 5
#endif
ΓòÉΓòÉΓòÉ <hidden> Parse tree for the grammar of a simple sequences ΓòÉΓòÉΓòÉ
For the grammar of a simple sequences and input text abc1a2b3c. the LR parser
create the tree:
Grammar SQNS_1 on input:
abc1a2b3c.
sequence
Γö£ΓöÇalphaΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇa
Γö£ΓöÇitem
Γöé Γö£ΓöÇitem
Γöé Γöé ΓööΓöÇalphaΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇb
Γöé Γö£ΓöÇitem
Γöé Γöé ΓööΓöÇalphaΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇc
Γöé Γö£ΓöÇitem
Γöé Γöé ΓööΓöÇomegaΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ1
Γöé Γö£ΓöÇitem
Γöé Γöé ΓööΓöÇalphaΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇa
Γöé Γö£ΓöÇitem
Γöé Γöé ΓööΓöÇomegaΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ2
Γöé Γö£ΓöÇitem
Γöé Γöé ΓööΓöÇalphaΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇb
Γöé Γö£ΓöÇitem
Γöé Γöé ΓööΓöÇomegaΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ3
Γöé ΓööΓöÇitem
Γöé ΓööΓöÇalphaΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇc
ΓööΓöÇend_of_seqΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇ.
ΓòÉΓòÉΓòÉ <hidden> LR-file ΓòÉΓòÉΓòÉ
LR Parser: SQNS_2 - Sequences 2.
Severe errors
Line 12 : 0019 Zero production in rule 'sequence(1)'
Nonterminals: Total of 2
Nonterminals___ Reduce Attributes
sequence Normal
word Normal
Rules: Total of 3
Rule____________ No._____ LHS_____________ #NT_____ RHS
sequence 1 sequence 1 word(1 RO)
sequence 2 sequence 2 sequence(2) word(3)
word 3 word 0 123456789(4)
Parse structure
LR
NAME(SQNS_2)
SQNS_2
TITLE('Sequences 2.')
'Sequences 2.'
PATH
STRUCT
PRINT
RULES
sequence
word (zero )
zero
( sequence word )
sequence
word
word ('123456789'(choice))
'123456789'(choice)
choice
ΓòÉΓòÉΓòÉ <hidden> Automaton of example 2 grammar ΓòÉΓòÉΓòÉ
LR Parser: SQNS_1 - Sequences 1.
No errors detected
Nonterminals: Total of 5
Nonterminals___ Reduce Attributes
alpha String
end_of_seq String
item Normal
omega String
sequence Normal
Rules: Total of 8
Rule____________ No._____ LHS_____________ #NT_____ RHS
alpha 4 alpha 0 abcd(6)
end_of_seq 6 end_of_seq 0 .(8)
item 2 item 1 alpha(4)
item 3 item 1 omega(5)
omega 5 omega 0 123456789(7)
sequence 7 sequence 2 alpha(9) end_of_seq(10)
sequence 1 sequence 3 alpha(1) item(2 RO) end_of_seq(3)
States: Total of 16
Start state: 0
State 0 EXPANDED
Nonterminals
alpha(2) sequence(1)
Terminals 0
3 abcd
State 1 EXPANDED FINAL
State 2 EXPANDED
Nonterminals
alpha(7) end_of_seq(5) item(4) omega(8)
Terminals 0
6 .
9 123456789
10 abcd
Expand rule components: alpha(1) alpha(9)
State 3
Reduce by 0 rule alpha(4):
From____ To______ Push Nonterminal
0 2 1 alpha
State 4 EXPANDED
Nonterminals
alpha(7) end_of_seq(11) item(4) omega(14)
Terminals 0
12 .
15 123456789
16 abcd
Expand rule components: item(2)
State 5 EXPANDED
Reduce by 2 rule sequence(7):
From____ To______ Push Nonterminal
0 1 1 sequence
Expand rule components: end_of_seq(10)
State 6
Reduce by 0 rule end_of_seq(6):
From____ To______ Push Nonterminal
2 5 1 end_of_seq
State 7 EXPANDED
Reduce by 1 rule item(2):
From____ To______ Push Nonterminal
2 4 1 item
4 4 0 item
Expand rule components: alpha(4)
State 8 EXPANDED
Reduce by 1 rule item(3):
From____ To______ Push Nonterminal
2 4 1 item
Expand rule components: omega(5)
State 9
Reduce by 0 rule omega(5):
From____ To______ Push Nonterminal
2 8 1 omega
State 10
Reduce by 0 rule alpha(4):
From____ To______ Push Nonterminal
2 7 1 alpha
State 11 EXPANDED
Reduce by 3 rule sequence(1):
From____ To______ Push Nonterminal
0 1 1 sequence
Expand rule components: end_of_seq(3)
State 12
Reduce by 0 rule end_of_seq(6):
From____ To______ Push Nonterminal
4 11 1 end_of_seq
State 14 EXPANDED
Reduce by 1 rule item(3):
From____ To______ Push Nonterminal
4 4 0 item
Expand rule components: omega(5)
State 15
Reduce by 0 rule omega(5):
From____ To______ Push Nonterminal
4 14 1 omega
State 16
Reduce by 0 rule alpha(4):
From____ To______ Push Nonterminal
4 7 1 alpha
Parse structure
LR
NAME(SQNS_1)
SQNS_1
TITLE('Sequences 1.')
'Sequences 1.'
PATH
STRUCT
PRINT
RULES
sequence ( alpha item ( zero ) end_of_seq)
alpha
item ( zero )
zero
end_of_seq
item (alpha)
alpha
(omega)
omega
alpha ('abcd'(choice mixed))
'abcd'(choice mixed)
choice
mixed
omega ('123456789'(choice))
'123456789'(choice)
choice
end_of_seq ('.')
'.'
ΓòÉΓòÉΓòÉ <hidden> Error file of grammar of example 2 ΓòÉΓòÉΓòÉ
Text____
1abc1a2b3c
!
Nonterminals expected:
alpha
sequence
Terminals expected:
abcd
Stack at time error was detected
0
Text: 1abc1a2b3c
ΓòÉΓòÉΓòÉ 5. LR-parsing table construction ΓòÉΓòÉΓòÉ
When the grammar definition is written, LR-parsing table my be generated by:
o Usage of the parser generator within WorkFrame/2;
o Parser generator call from command line;
o Parser generator call from user program.
ΓòÉΓòÉΓòÉ 5.1. Usage of the parser generator within WorkFrame/2 ΓòÉΓòÉΓòÉ
To use the parser generator within WorkFrame/2 your must do following steps:
1. To create a make-project:
a. Set the project field 'Directory' with path of your grammar file;
b. Set the field 'Target file name' with name of LRS-file ( file where
parsing table will be placed ) <<NAME_OF_GRAMMAR>>.lrs;
c. Set the project field 'Make file name' with file name of makefile
similar to makefile in example.
2. Edit variables of this makefile LRP_DIR, TEXT, GR to tune it up for your
purposes.
Note: Results of making this project are the same as the results of working
<command line version of LRP>.
ΓòÉΓòÉΓòÉ 5.2. Parser generator call from command line ΓòÉΓòÉΓòÉ
After a syntax of input language have been described with GDL, it is necessary
to create parsing table that corresponds to the given grammar.
To create parsing-table using command line, you must type following command:
SYNTAX:
lrp.exe grammar_file
PARAMETERS:
"grammar_file" is a file containing GDL description of
grammar. The format of the name of the file is
<<NAME>> .GR.
EFFECT:
If errors have not been detected, The parser generator
creates parsing-table that will be written to
<<NAME>> .LRS, a file containing definition of NPS
and macros corresponding to the given grammar that
named <<NAME>> .STR ( a file <<NAME>> .N (that is
also created) is subset of <<NAME>> .STR and contains
only the definition of structure of NPS and constant
<<NAME>> _n that means number of nonterminals) and a
file named <<NAME>> .LR that contains protocol of
parsing-table construction and detected errors.
ΓòÉΓòÉΓòÉ 5.3. Parser generator call from user program ΓòÉΓòÉΓòÉ
Here described two functions that can be used for creation of compiler of
grammars (such as LRP.EXE):
lr_open Prepare a grammar for use by the parser;
lr_free Release the results of LR-parsing table construction.
ΓòÉΓòÉΓòÉ 5.3.1. lr_open Prepare a grammar for use by the parser ΓòÉΓòÉΓòÉ
SYNTAX:
void lr_open (char *NAME, char *grammar, LR **Lr);
PARAMETERS:
char *NAME
Name of grammar (in case the keyword NAME() was omitted
in grammar definition).
char *grammar
String that contains text of grammar definition.
LR **Lr
Pointer to pointer to LR-parsing table (the pointer to
created LR-parsing table is a procedure output).
'lr_open' allocates memory for it in itself. You can
release memory by lr_free
EFFECT:
1. Builds LR-parsing table using grammar definition 'grammar'.
2. Save condensed version of LR-parsing table in <<NAME>> .lrs if no
errors occurred (grammar.lrs if there was text "grammar" in NAME).
3. Creates <<NAME>>.str and <<NAME>>.n if necessary.
RETURN:
Nothing.
ΓòÉΓòÉΓòÉ 5.3.2. lr_free Release the results of LR-parsing table construction. ΓòÉΓòÉΓòÉ
Release the results of LR-parsing table construction.
SYNTAX:
void lr_free (LR *lr);
PARAMETERS:
LR *lr
Pointer to LR-parsing table.
EFFECT:
Releases memory allocated by lr_open
RETURN:
Nothing
ΓòÉΓòÉΓòÉ 5.4. Input data for parser generator ΓòÉΓòÉΓòÉ
Input data for parser generator are contained in GR file in which user defines
the grammar.
ΓòÉΓòÉΓòÉ 5.5. Output of parser generator ΓòÉΓòÉΓòÉ
o Parsing table file;
o N-file and STR-file;
o Error message file.
o Automaton description file.
ΓòÉΓòÉΓòÉ 5.5.1. Parsing table file ΓòÉΓòÉΓòÉ
The result of compiling grammar definition written on GDL is parsing table
file. This file is a binary file. The compiled grammar presented as
deterministic finite automaton in this file.
The name of parsing table file can be defined in grammar definition (e.g.
SAVE('PTF.BIN')) but if you ommited global option SAVE in the grammar
definition then the parsing table file name is constructed from the name (not
title) of the grammar and extension '.LRS'.
The parsing table file is used during source text parsing.
ΓòÉΓòÉΓòÉ 5.5.2. N-file and STR-file ΓòÉΓòÉΓòÉ
These files are created by parser generator if an overall option 'STRUCT' was
occurred in the grammar definition file.
The files contain a few C-structures, C-macros and C-constants that allow to
write a program that will process a parse trees.
Here <<NAME_OF_GRAMMAR>> may be considered as a macro that defines the grammar
name and <<NAME_OF_NONTERMINAL>> as a macro that defines the name of a
nonterminal of the defined grammar.
Structures:
struct <<NAME_OF_GRAMMAR>>_PT
The nonterminal pointer set for the defined grammar.
Fields:
LR_PT *l
Pointer to last selected node of parse tree.
LR_P *p
pointer to parse results.
LR_PT *key[<<NAME_OF_GRAMMAR>>_n]
Set of pointers to parse tree nodes
(nonterminals).
Note: The structure is almost equal to LRX_PT, so all
macros which work with LRX_PT will work with
<<NAME_OF_GRAMMAR>>_PT.
Constants:
<<NAME_OF_GRAMMAR>>_n
number of nonterminals.
<<NAME_OF_GRAMMAR>>_<<NAME_OF_NONTERMINAL>>_n
number of nonterminal named <<NAME_OF_NONTERMINAL>>.
Macros:
<<NAME_OF_GRAMMAR>>_<<NAME_OF_NONTERMINAL>>(<<NPS>>)
Select from <<NPS>> pointer to node contained in it
at key[<<NAME_OF_NONTERMINAL>>_n] and set l = this
value and return the value.
The difference N-file from STR-file:
N-file does not contain constants <<NAME_OF_GRAMMAR>>_<<NAME_OF_NONTERMINAL>>_n
and macros <<NAME_OF_GRAMMAR>>_<<NAME_OF_NONTERMINAL>>.
For grammar of the example 2 the parser generator create following STR-file
and N-file
ΓòÉΓòÉΓòÉ 5.5.3. Error message file ΓòÉΓòÉΓòÉ
Any errors that were detected during compilation of grammar are placed in LR
file.
See Error message file of the parser generator .
Error message format, Error explanation, Error removal.
ΓòÉΓòÉΓòÉ 5.5.4. Automaton description file ΓòÉΓòÉΓòÉ
An automaton description file has name of the grammar from which it was created
and '.LR' extension. In this file the deterministic finite automaton
description that corresponds to compiled grammar is stored. In this file are
listed :
o all nonterminals of grammar,
o all states of the deterministic finite automaton,
o all reduces that are used for transition from one state to another,
o all operations with nonterminal stack and parse structure of grammar.
See Automaton description file example┬╖
ΓòÉΓòÉΓòÉ 5.6. Parser generator error message list ΓòÉΓòÉΓòÉ
During parsing table construction the parser generator analyses input grammar
definition and reports all detected errors. Reported message matches one of
following kinds:
o Severe errors;
o Informational messages.
Any error message consists of error explanation and the following elements used
to locate an error in source grammar definition:
Line number
Line number of grammar definition text where the reported
error is detected.
Global
Detected error concerns the grammar definition entirely.
Terminal designator (<<TD>>)
The terminal itself as terminal designator is used.
Nonterminal designator (<<NTD>>)
Nonterminal designator consists of the nonterminal name
followed by a number in parenthesis.
Terminal option designator (<<TOD>>)
Terminal option itself as terminal designator is used.
Nonterminal option designator (<<NTOD>>)
Nonterminal option itself as nonterminal designator is
used.
Rule designator (<<RD>>)
Rule designator consists of the nonterminal name followed
by a number in parenthesis.
State designators (<<SD>>)
State designator is a number.
String designators (<<STRD>>)
String itself as string designator is used.
o S E V E R E E R R O R S
0001 Closing parentheses required in grammar source.
0002 Closing parenthesis ignored.
0003 Closing quote assumed.
0004 NAME missing.
0005 RULES missing.
0006 No start symbol.
0007 Start rule is a substring <<RD>>.
0008 Unable to save.
0009 Invalid terminal option <<TOD>> for terminal <<TD>>.
0010 Invalid nonterminal option <<NTOD>> for nonterminal <<NTD>>.
0011 Secondary rule <<RD>> contains a nonterminal.
0012 Rule <<RD>> specifies <<NTD>> as a secondary nonterminal, but <<NTD>>
contains a nonterminal.
0013 Undefined nonterminal <<NTD>>.
0010 Invalid nonterminal option <<NTOD>>.
0014 String <<NTD>> over string <<NTD>> in rule <<RD>>.
0015 Substring <<NTD>> over string <<NTD>> in rule <<RD>>.
0016 Normal <<NTD>> over substring <<NTD>> in rule <<RD>>.
0017 Reduce <<RD>> reduce <<RD>> at state <<SD>>.
0018 Mixed rule <<RD>>.
0019 Zero production in rule <<RD>>.
0020 Re-use of nonterminal <<NTD>> in rule <<RD>>.
0022 'Ignore' in definition of nonterminal <<NTD>> in rule <<RD>> conflicts
with 'No Ignore' in rule <<RD>>.
0024 Unable to locate next state from state <<SD>> on <<RD>> in rule <<RD>>.
0026 Terminal symbol overlap on <<RD>> in rule <<RD>> which affects state
<<SD>>.
o I N F O R M A T I O N A L M E S S A G E S
0027 TITLE missing.
0028 Unused nonterminal <<NTD>>.
0029 Undefined optional <<NTD>>.
0030 Undefined secondary <<NTD>>.
0031 Undefined string <<NTD>>.
0032 Undefined zero <<NTD>>.
0033 Undefined repeat <<NTD>>.
0034 Undefined choice <<NTD>>.
0035 Undefined ignore <<NTD>>.
0037 Reduce-shift conflict from state <<SD>>, shift text <<STRD>> or reduce
by <<RD>>.
ΓòÉΓòÉΓòÉ 6. Error messages of the parser generator ΓòÉΓòÉΓòÉ
Any errors that were detected during compilation of grammar are placed in LR
file.
See Error message file of the parser generator .
Error message format, Error explanation, Error removal.
ΓòÉΓòÉΓòÉ 6.1. Error N 0001 ΓòÉΓòÉΓòÉ
Error message format:
L: 0001 Closing parenthesis required in grammar
definition.
Error explanation:
There is opening parenthesis but no closing
parenthesis for the opening parenthesis in the
grammar definition.
Error removal:
Find place where must be the closing parenthesis
for the opening parenthesis and insert closing
parenthesis there.
Error example:
LR
(
NAME('E0001')
RULES
(
S('a')
)
ΓòÉΓòÉΓòÉ 6.2. Error N 0002 ΓòÉΓòÉΓòÉ
Error message format:
L: 0002 Closing parenthesis ignored.
Error explanation:
There is superfluous closing parenthesis in the
grammar definition.
Error removal:
Delete the superfluous closing parenthesis.
(Check the grammar definition very carefully because
this error usually invoked by careless grammar
creation.)
Error example:
LR
(
NAME ('E0002')
RULES
(
S( ''a' )
)
))
ΓòÉΓòÉΓòÉ 6.3. Error N 0003 ΓòÉΓòÉΓòÉ
Error message format:
L: 0003 Closing quote assumed.
Error explanation:
You have missed closing quote somewhere.
Error removal:
Locate error and insert closing quote.
Error example:
LR
(
NAME ('E0002')
RULES
(
S( 'a )
)
)
ΓòÉΓòÉΓòÉ 6.4. Error N 0004 ΓòÉΓòÉΓòÉ
Error message format:
G: 0004 NAME missing.
Error explanation:
You missed option <<NAME>> in the grammar definition.
Option <<NAME>>> must be in the grammar definition.
Error removal:
Insert Option <<NAME>> in the grammar definition.
Error example:
LR(
RULES
(
* NAME('E0004')
S('a')
)
)
ΓòÉΓòÉΓòÉ 6.5. Error N 0005 ΓòÉΓòÉΓòÉ
Error message format:
G: 0005 RULES missing.
Error explanation:
You missed option RULES in the grammar definition.
Error removal:
Insert option RULES in the grammar definition
Error example:
LR(
NAME ('E005')
)
ΓòÉΓòÉΓòÉ 6.6. Error N 0006 ΓòÉΓòÉΓòÉ
Error message format:
G: 0006 No start symbol.
Error explanation:
Your RULES option is empty!!! You MUST have at least
one rule!!!
Error removal:
Add rules in your <<RULES>> option.
Error example:
LR(
NAME('E0006')
RULES
(
)
)
ΓòÉΓòÉΓòÉ 6.7. Error N 0007 ΓòÉΓòÉΓòÉ
Error message format:
L: 0007 Start rule is a substring <<RD>>.
Error explanation:
Your <<start rule>> is a substring in some other
nonterminal.
Error removal:
Review your grammar!!! It is incorrect now.
Error example:
LR
(
NAME('E0007')
RULES
(
S('a')
A( S B )
B('s')
)
STRING( A )
)
ΓòÉΓòÉΓòÉ 6.8. Error N 0008 ΓòÉΓòÉΓòÉ
Error message format:
G: 0008 Unable to save.
Error explanation:
There was OS/2 error during saving some of output
files.
Error removal:
Free more space on your destination drive. If it will
not help then contact <<Transcedental Automation>> or
<<IBM>>.
Error example:
Make your minidisk write-protected, insert it in drive
A and redirect all your output files to A.
ΓòÉΓòÉΓòÉ 6.9. Error N 0009 ΓòÉΓòÉΓòÉ
Error message format:
L: 0009 Invalid terminal option <<TOD>> for terminal
<<TD>>.
Error explanation:
You use terminal with invalid option
Error removal:
Remove the option from terminal.
(This error is usually caused by misprints and
misthinkings).
Error example:
LR
(
name(E009)
TITLE('E009')
print
rules
(
S ('a'(string))
)
)
ΓòÉΓòÉΓòÉ 6.10. Error N 0010 ΓòÉΓòÉΓòÉ
Error message format:
L: 0010 Invalid nonterminal option <<NTOD>> for
nonterminal <<NTD>>.
Error explanation:
You use nonterminal with invalid option.
Error removal:
Remove the option from nonterminal.
(This error is usually caused by misprints and
misthinkings)
Error example:
LR
(
NAME(E0010)
TITLE('E0010')
RULES
(
S (A(mixed))
A ( B )
B ('a')
)
)
ΓòÉΓòÉΓòÉ 6.11. Error N 0011 ΓòÉΓòÉΓòÉ
Error message format:
L: 0011 Secondary rule <<RD>> contains a nonterminal.
Error explanation:
Secondary rule contains a nonterminal.
Error removal:
Rewrite rule changing nonterminals into terminals or
delete option secondary.
Error example:
LR
(
name(E0011)
TITLE('E0011')
print
rules
(
S (R A)
R (A)
A ('g')
)
secondary(R)
)
ΓòÉΓòÉΓòÉ 6.12. Error N 0012 ΓòÉΓòÉΓòÉ
Error message format:
L: 0012 Rule <<RD>> specifies <<NTD>> as a secondary
nonterminal,but <<NTD>> contains a nonterminal.
Error explanation:
Rule <<RD>> specifies <<NTD>> as a secondary
nonterminal,but <<NTD>> contains a nonterminal.
Error removal:
Rewrite rule changing nonterminals into terminals or
delete option secondary.
Error example:
LR
(
name(E0012)
TITLE('E0012')
print
rules
(
S (R(secondary) A)
R (A)
A ('g')
)
)
ΓòÉΓòÉΓòÉ 6.13. Error N 0013 ΓòÉΓòÉΓòÉ
Error message format:
L: 0013 Undefined nonterminal <<NTD>>.
Error explanation:
You have not defined nonterminal <<NTD>>, but have
used it somewhere.
Error removal:
Define nonterminal <<NTD>>.
Error example:
LR
(
name(E0013)
TITLE('E0013')
print
rules
(
S (R)
)
)
ΓòÉΓòÉΓòÉ 6.14. Error N 0014 ΓòÉΓòÉΓòÉ
Error message format:
L: 0014 String <<NTD1>> over string <<NTD2>> in rule
<<RD>>.
Error explanation:
In the grammar definition there is nonterminal that is
defined as STRING and definition of this nonterminal
there is one or more nonterminals that are defined as
string(s) too.
Error removal:
Review and reedit your grammar to avoid this conflict.
May be removing of STRING qualifier will solve the
problem. Or may be you must create a copy of <<NTD2>>
under unique name, then remove qualifier STRING from
the copy and rename <<NTD2>> in rule <<RD>> to the
unique name of the copy.
Error example:
Here string A over string B in rule A.
LR
(
name(E0014)
TITLE('E0014')
print
rules
(
S (A)
A (C B)
B (C)
C ('c')
)
string (A B)
)
ΓòÉΓòÉΓòÉ 6.15. Error N 0015 ΓòÉΓòÉΓòÉ
Error message format:
L: 0015 Substring <<NTD1>> over string <<NTD2>> in
rule <<RD>>.
Error explanation:
In rule <<RD>> of the grammar definition there is
nonterminal in <<RHS>> and this nonterminal is STRING.
But rule <<RD>> is SUBSTRING (it is used in <<RHS>> of
a rule that have been defined as STRING).
Error removal:
There are some ways to solve the problem. You can
simply remove STRING qualifier from <<NTD2>>. You can
create a copy of definition of nonterminal <<NTD2>>
with unique name and then rename <<NTD2>> in rule
<<RD>> to the unique name of the copy.
Error example:
Here is substring D over string B in rule D
LR
(
name(E0015)
TITLE('E0015')
print
rules
(
S(A)
A(C D)
D(B)
B(C)
C('z')
)
string (A B)
)
ΓòÉΓòÉΓòÉ 6.16. Error N 0016 ΓòÉΓòÉΓòÉ
Error message format:
L: 0016 Normal <<NTD1>> over substring <<NTD2>> in
rule <<RD>>.
Error explanation:
In rule <<RD>> there is nonterminal that has been
defined as part of a nonterminal that has been defined
as STRING, and this(first) nonterminal has been used
in <<RHS>> of nonSTRING nonterminal too.
Error removal:
You can simply remove STRING qualifier from the
nonterminal in which <<NTD2>> defined and so <<NTD2>>
no longer will be a substring. You can review your
grammar carefully(it is most likely your grammar is
incorrect). You can create a copy with unique name of
<<NTD2>> and rename <<NTD2>> in rule <<RD>> to the
unique name of the copy.
Error example:
Here is normal B over substring D in rule B
LR
(
name(E0016)
TITLE('E0016')
print
rules
(
S(A B)
A(C D)
D('s')
B(D)
C('z')
)
string (A)
)
ΓòÉΓòÉΓòÉ 6.17. Error N 0017 ΓòÉΓòÉΓòÉ
Error message format:
L: 0017 Reduce <<RD1>> reduce <<RD2>> at state <<SD>>.
Error explanation:
It is not clear what to reduce from state <<SD>>.
Error removal:
Review your grammar very carefully(it is most likely
your grammar is incorrect)
Error example:
Here it is not clear what to reduce from start state:
A or B. LR can reduce A as well as B and it has not
been given information what it must do.
LR
(
name(E0017)
TITLE('E0017')
print
rules
(
S(A)
(B)
A('a')
B('a')
)
)
ΓòÉΓòÉΓòÉ 6.18. Error N 0018 ΓòÉΓòÉΓòÉ
Error message format:
L: 0018 Mixed rule <<RD>>.
Error explanation:
In <<RHS>> of rule <<RD>> nonterminals used along with
terminals.
Error removal:
Create nonterminals that consist of one terminal from
the rule <<RD>>. E.g. in the example you can create
nonterminal LNT ('E'). And replace S(L 'L') with S(L
LNT).
Error example:
LR
(
name(E0018)
TITLE('E0018')
print
rules
(
S(L 'L')
L('E')
)
)
ΓòÉΓòÉΓòÉ 6.19. Error N 0019 ΓòÉΓòÉΓòÉ
Error message format:
L: 0019 Zero production in rule <<RD>>.
Error explanation:
It is clear from the grammar definition that the rule
<<RD>> can be empty (empty input string can be reduced
by this rule and so empty input string can be reduced
by example grammar to A A ... infinity times.)
Error removal:
Review your grammar carefully (it is most likely your
grammar is incorrect)
Error example:
LR
(
name(E0019)
TITLE('E0019')
print
rules
(
S(A(optional))
A('a')
)
)
ΓòÉΓòÉΓòÉ 6.20. Error N 0020 ΓòÉΓòÉΓòÉ
Error message format:
L: 0020 Re-use of nonterminal <<NTD>> in rule <<RD>>.
Error explanation:
The nonterminal <<NTD>> is occurred two times in
<<RHS>> in rule <<RD>>.
Error removal:
There are many ways to solve the problem. You can make
a copy of <<NTD>> with unique name and rename the
second occurrence of <<NYD>> in <<RD>> to the unique
name of copy.
Error example:
LR
(NAME(E0020)
TITLE(E0020)
PRINT
RULES
(S (A A)
A ('a')
)
)
ΓòÉΓòÉΓòÉ 6.21. Error N 0022 ΓòÉΓòÉΓòÉ
Error message format:
L: 0022 'Ignore' in definition of nonterminal <<NTD>>
in rule <<RD1>> conflicts with 'No Ignore' in rule
<<RD2>>.
Error explanation:
The nonterminal <<NTD>> is marked with IGNORE in rule
<<RD1>> and with NOIGNORE in rule <<RD2>>. It is not
clear does <<NTD>> marked with IGNORE or not.
Error removal:
Make decision and remove one of the markings.
Error example:
LR
(
name(E0022)
TITLE('E0022')
print
rules
(
S (A B)
A ( D(ignore))
B ( D )
D(Z E(repeat))
Z('a')
E('z')
)
string(D);
)
ΓòÉΓòÉΓòÉ 6.22. Error N 0023 ΓòÉΓòÉΓòÉ
Error message format:
L: 0023 'Secondary' in definition of nonterminal
<<NTD>> in rule <<RD1>> conflicts with 'Not Secondary'
in rule <<RD2>>.
Error explanation:
Error removal:
Make decision and remove one of the markings.
Error example:
ΓòÉΓòÉΓòÉ 6.23. Error N 0024 ΓòÉΓòÉΓòÉ
Error message format:
L: 0024 Unable to locate next state from state <<SD>>
on <<RD>> in rule <<RD>>.
Error explanation:
It is internal error of LR. If you encountered this
error then contact <<Transcedental Automation>> at ...
Error removal:
Contact <<Transcedental Automation>>
Error example:
ΓòÉΓòÉΓòÉ 6.24. Error N 0025 ΓòÉΓòÉΓòÉ
Error message format:
L: 0025 Double exit from state <<SD>> on nonterminal
<<NTD>>.
Error explanation:
*
Error removal:
*
Error example:
*
ΓòÉΓòÉΓòÉ 6.25. Error N 0026 ΓòÉΓòÉΓòÉ
Error message format:
L: 0026 Terminal symbol overlap on <<RD>> in rule
<<RD>> which affects state <<SD>>.
Error explanation:
This is internal error of LR. Please contact
<<Transcedental Automation>> if you encountered this
error.
Error removal:
Please contact <<Transcedental Automation>> if you
encountered this error.
Error example:
ΓòÉΓòÉΓòÉ 6.26. Error N 0027 ΓòÉΓòÉΓòÉ
Error message format:
G: 0027 TITLE missing.
Error explanation:
A overall option 'title' is missed.
Error removal:
Insert the option title
Error example:
LR(
NAME(W0027)
RULES(
S('a')
)
)
ΓòÉΓòÉΓòÉ 6.27. Error N 0028 ΓòÉΓòÉΓòÉ
Error message format:
L: 0028 Unused nonterminal <<NTD>>.
Error explanation:
<<NTD>> is defined but never used.
Error removal:
Check your grammar and remove <<NTD>> if it is not
necessary for your grammar.
Error example:
Unused nonterminal 'A'.
LR(
NAME(W0028)
Title('w0028')
RULES(
S('a')
A('b')
)
)
ΓòÉΓòÉΓòÉ 6.28. Error N 0029 ΓòÉΓòÉΓòÉ
Error message format:
L: 0029 Undefined optional <<NTD>>.
Error explanation:
<<NTD>> used but not defined.
Error removal:
Define <<NTD>> in your grammar definition.
Error example:
LR(
NAME(W0029)
Title('w0029')
RULES(
S('a')
)
optional(A)
)
ΓòÉΓòÉΓòÉ 6.29. Error N 0030 ΓòÉΓòÉΓòÉ
Error message format:
L: 0030 Undefined secondary <<NTD>>.
Error explanation:
<<NTD>> used but not defined.
Error removal:
Define <<NTD>> in your grammar definition
Error example:
LR(
NAME(W0030)
Title('w0030')
RULES(
S('a')
)
secondary(A)
)
ΓòÉΓòÉΓòÉ 6.30. Error N 0031 ΓòÉΓòÉΓòÉ
Error message format:
L: 0031 Undefined string <<NTD>>.
Error explanation:
<<NTD>> used but not defined.
Error removal:
Define <<NTD>> in your grammar definition.
Error example:
LR(
NAME(W0031)
Title('w0031')
RULES(
S('a')
)
string(A)
)
ΓòÉΓòÉΓòÉ 6.31. Error N 0032 ΓòÉΓòÉΓòÉ
Error message format:
L: 0032 Undefined zero <<NTD>>.
Error explanation:
<<NTD>> used but not defined.
Error removal:
Define <<NTD>> in your grammar definition.
Error example:
LR(
NAME(W0032)
Title('w0032')
RULES(
S('a')
)
zero(A)
)
ΓòÉΓòÉΓòÉ 6.32. Error N 0033 ΓòÉΓòÉΓòÉ
Error message format:
L: 0033 Undefined repeat <<NTD>>.
Error explanation:
<<NTD>> used but not defined.
Error removal:
Define <<NTD>> in your grammar definition.
Error example:
LR(
NAME(W0033)
Title('w0033')
RULES(
S('a')
)
repeat(A)
)
ΓòÉΓòÉΓòÉ 6.33. Error N 0034 ΓòÉΓòÉΓòÉ
Error message format:
L: 0034 Undefined choice <<NTD>>.
Error explanation:
<<NTD>> used but not defined.
Error removal:
Define <<NTD>> in your grammar definition.
Error example:
LR(
NAME(W0034)
Title('w0034')
RULES(
S('a')
)
choice(A)
)
ΓòÉΓòÉΓòÉ 6.34. Error N 0035 ΓòÉΓòÉΓòÉ
Error message format:
L: 0035 Undefined ignore <<NTD>>.
Error explanation:
<<NTD>> used but not defined.
Error removal:
Define <<NTD>> in your grammar definition.
Error example:
LR(
NAME(W0035)
Title('w0035')
RULES(
S('a')
)
ignore(A)
)
ΓòÉΓòÉΓòÉ 6.35. Error N 0036 ΓòÉΓòÉΓòÉ
Error message format:
L: 0036 Duplicate rule name <<RD>> within nonterminal
<<NTD>>.
Error explanation:
*
Error removal:
*
Error example:
*
ΓòÉΓòÉΓòÉ 6.36. Error N 0037 ΓòÉΓòÉΓòÉ
Error message format:
L: 0037 Reduce-shift conflict from state <<SD>>, shift
text <<STRD>> or reduce by <<RD>>.
Error explanation:
*
Error removal:
*
Error example:
ΓòÉΓòÉΓòÉ 7. Source text parsing ΓòÉΓòÉΓòÉ
To use LR from an application program, you can:
o either use lrx_req - the "do everything" procedure , located in LRX.C.
o or use the parsing primitives directly.
In either case, the steps to perform a parse are the same.
ΓòÉΓòÉΓòÉ 8. Syntax-directed semantic processing of parse tree ΓòÉΓòÉΓòÉ
A result of successful source text parsing is a parse tree. According to LR the
further processing of the parse tree is made within syntax-directed semantic
processing scheme. This scheme is useful because it allows the designer to
express the semantic processing directly in terms of the syntactic structure of
the source language. A syntax-directed processing scheme is merely a
context-free grammar in which a procedure called a semantic action is
associated with each production. Consider for instance semantic action b is
associated with production B ( C D E ) The semantic action b is executed
whenever the traversal of parse tree reach a tree-node corresponding to
nonterminal B .
The semantic action may involve the computation of values for variables
belonging to the user program (to the compiler for example), the printing of an
error diagnostic, or the placement of some value in a data structure. The
values computed by action b quite frequently are associated with the parse tree
nodes corresponding to the instance of nonterminal B .
About semantic actions and parse tree elements linkage see lrx_parse (parse
text with semantic actions).
To navigate parse tree there are several program primitives and data
structures:
o C-data structures for parse tree;
o Parse tree navigation primitives.
Example of program performing a parse tree navigation.
ΓòÉΓòÉΓòÉ 8.1. C-data structures for parse tree ΓòÉΓòÉΓòÉ
To navigate parse tree there are several data structures:
o LR_P - result parse tree;
o LR_PT - parse tree element;
o XL, Xl - arrival order list;
o LRX_PT - nonterminal pointer set.
ΓòÉΓòÉΓòÉ 8.1.1. LR_P Result parse tree ΓòÉΓòÉΓòÉ
Description:
Parse results
Fields:
LR2 *lr; - pointer parsing table
LR_PT *parse_tree; - pointer arse tree
char *text; - pointer text to be parsed
char *path; - pointer path to be used for file names
char *parse; - pointer file on which parse were printed
char *error; - pointer file on which errors were printed
long pts; - Number of parse tree elements
long errors; - Error count
char *error_text; - pointer position in text at which error was detected
XT EXPECTED; - Expected nonterminals at error
char *next; - pointer next characters
ΓòÉΓòÉΓòÉ 8.1.2. LR_PT Parse tree element ΓòÉΓòÉΓòÉ
Description:
Parse tree element.
Fields:
char *t; - pointer to source text (ASCIIZ).
If current nonterminal was not reduced from
terminal, it is NULL.
long chars,lines; - Amount of spacing between items
in parse tree.
char *k; - pointer to name of current nonterminal.
Xl Pl; - Arrival order.
XL PL; - Arrival order list.
ΓòÉΓòÉΓòÉ 8.1.3. XL+Xl Arrival order list ΓòÉΓòÉΓòÉ
Description:
Arrival order list
Type:
XL - List of pointers to void.
Fields:
f - pointer to the first element.
l - pointer to the last element.
d - pointer to the data associated with list.
Type:
Xl - element of XL.
Fields:
n - pointer to the next element
p - pointer to the previous element
u - pointer to the list(XL) that own this element.
d - pointer to data associated with this list element.
Usage in LR_PT:
When this structures are used in in LR_PT field 'd' of both of them points to
the begin of LR_PT structure than own those structures.
For example:
LR_PT *a,*b;
b = a->PL->f->d;// b - pointer to the first son of 'a'.
a = b->Pl->u->d;// a - pointer to the parent of 'b'
ΓòÉΓòÉΓòÉ 8.1.4. LRX_PT Nonterminal pointer set ΓòÉΓòÉΓòÉ
Nonterminal pointer set
Description:
Nonterminal pointer set.
Fields:
LR_PT *l; - Pointer to currently selected nonterminal
LR_P *p; - Pointer to parse results
LR_PT *key[]; - Array of pointers to nonterminals
ΓòÉΓòÉΓòÉ 8.2. Parse tree navigation primitives ΓòÉΓòÉΓòÉ
To navigate parse tree there are several program primitives : Parse tree
navigation primitives.
ΓòÉΓòÉΓòÉ 8.2.1. lrx_parse - parse text with semantic actions ΓòÉΓòÉΓòÉ
SYNTAX:
void lrx_parse(LR_P **p,void (**cmd)(), void
(**cmd2)(),LRX_PT *PT,LR2 *grammar,char *text,long
stack,void *sysp);
PARAMETERS:
LR_P **p if p != 0 after calling then *p is pointer to parse result else
function release memory allocated by a parser
void (**cmd)() vector of semantic action for prefix traversal.
The function with index i from this ( cmd ) and next ( cmd2 )
vectors will be called just as 'cmd[i](void *sysp,LRX_PT*
PT,LR_PT pt)', where 'sysp' and 'PT' are parameters of the
lrx_parse-call and 'pt' is a current parse tree node.
void (**cmd2)() vector of semantic action for postfix traversal. See void
(**cmd)() .
LRX_PT *PT pointer to a nonterminal pointer set.
LR2 *grammar the compiled grammar.
char *text text that will be parsed.
long stack size of stack of automaton.
void *sysp parameter passed to cmd[i].
EFFECT:
Parse text using grammar grammar with stack size stack. If
cmd !=0 do a prefix traversal of parse tree using it. If
cmd2 !=0 do a postfix traversal of parse tree using it. If
p != 0 ,set *p points to parse result else release memory
allocated by parse.
RETURN:
Nothing.
ΓòÉΓòÉΓòÉ 8.2.2. lrx_n - Returns number of nonterminal ΓòÉΓòÉΓòÉ
SYNTAX:
lrx_n ( LR_PT *_PT )
PARAMETERS:
_PT pointer to nonterminal (parse tree node)
EFFECT:
None
RETURN:
number of nonterminal *_PT.
ΓòÉΓòÉΓòÉ 8.2.3. lrx_loc - Places nonterminal into NPS ΓòÉΓòÉΓòÉ
SYNTAX:
lrx_loc ( <<NAME >>_PT _KEYS, LR_PT *_PT )
PARAMETERS:
_KEYS nonterminal pointer set
_PT pointer to nonterminal
EFFECT:
places _PT to nonterminal pointer set _KEYS using number of *_PT
RETURN:
None.
ΓòÉΓòÉΓòÉ 8.2.4. lrx_one - Returns pointer to singleton son of nonterminal ΓòÉΓòÉΓòÉ
SYNTAX:
lrx_one ( LR_PT *_PT )
PARAMETERS:
_PT pointer to nonterminal
EFFECT:
None
RETURN:
pointer to son of *_PT if *_PT has only one son or zero otherwise.
ΓòÉΓòÉΓòÉ 8.2.5. lrx_zero - Initializes NPS with information from parse results ΓòÉΓòÉΓòÉ
SYNTAX:
lrx_zero ( <<NAME >>_PT _KEYS, LR_P *_P )
PARAMETERS:
_KEYS nonterminal pointer set
_P pointer to parse results
EFFECT:
initializes _KEYS using information from *_P and bounds _KEYS with
*_P
RETURN:
None.
ΓòÉΓòÉΓòÉ 8.2.6. lrx_add - Places nonterminal and singleton sons of this nonterminal into NPS ΓòÉΓòÉΓòÉ
SYNTAX:
lrx_add ( <<NAME >>_PT _KEYS, LR_PT *_PT )
PARAMETERS:
_KEYS nonterminal pointer set
_PT pointer to nonterminal
EFFECT:
places _PT and all singleton sons of *_PT into _KEYS
RETURN:
None.
ΓòÉΓòÉΓòÉ 8.2.7. lrx_all - Places given nonterminal and all sons of this nonterminal ΓòÉΓòÉΓòÉ
SYNTAX:
lrx_all ( <<NAME >>_PT _KEYS, LR_PT *_PT )
PARAMETERS:
_KEYS nonterminal pointer set
_PT pointer to nonterminal
EFFECT:
places _PT and pointers to all sons of *_PT (until leaves) to
_KEYS
RETURN:
None.
ΓòÉΓòÉΓòÉ 8.2.8. lrx_zap - Initializes NPS with parse results and places all sons of given nonterminal and the nonterminal itself into NPS ΓòÉΓòÉΓòÉ
SYNTAX:
lrx_zap ( <<NAME >>_PT _KEYS, LR_P *_P, LR_PT *_PT )
PARAMETERS:
_KEYS nonterminal pointer set
_P pointer to parse results
_PT pointer to nonterminal
EFFECT:
initializes _KEYS with *_P (using lrx_zero()) and places _PT and
pointers to all sons of *_PT (until leaves) into _KEYS
RETURN:
None.
ΓòÉΓòÉΓòÉ 8.2.9. lrx_up - Scans parse tree up ΓòÉΓòÉΓòÉ
SYNTAX:
lrx_up ( <<NAME >>_PT _KEYS, LR_PT *_PT, expression _UNTIL )
PARAMETERS:
_KEYS nonterminal pointer set
_P pointer to parse results
_UNTIL expression (e.g. a+b%s<d->fr-87)
EFFECT:
looks up through parse tree from *_PT until top of the tree
encountered or expression _UNTIL becomes non zero, placing all
encountered nonterminals (including last) into _KEYS.
RETURN:
None.
ΓòÉΓòÉΓòÉ 8.2.10. lrx_copy - Copies one NPS to another NPS ΓòÉΓòÉΓòÉ
SYNTAX:
lrx_copy ( <<NAME >>_PT _KEYS, <<NAME >>_PT _FROM )
PARAMETERS:
_KEYS nonterminal pointer set
_FROM nonterminal pointer set
EFFECT:
copies _FROM to _KEYS
RETURN:
None.
ΓòÉΓòÉΓòÉ 8.2.11. lrx_list_do - Scans list associated with given nonterminal and passes control to user-routine on every iteration ΓòÉΓòÉΓòÉ
SYNTAX:
lrx_list_do ( LR_PT *_PT, Xl *_L, void *_pt)
PARAMETERS:
_PT head of list
_L pointer to current list element
_pt pointer to data associated with current list element
EFFECT:
scans all given nonterminal as list from begin to end of *_PT and
on every iteration places pointer to current list element into _L
and pointer to data field of current element into _pt. Used as
header for cycle (e.g.
lrx_list_do(Pnt,PCurElem,PCurData){process(PCurData);
clear(PCurElem);} )
RETURN:
None.
ΓòÉΓòÉΓòÉ 8.2.12. lrx_tree_do - Scans tree associated with given nonterminal and passes control to user-routine on every iteration ΓòÉΓòÉΓòÉ
SYNTAX:
lrx_tree_do ( LR_PT *_PT, Xt *_T, void *_pt)
PARAMETERS:
_PT head of tree
_T pointer to current tree element
_pt pointer to data associated with current tree element
EFFECT:
scans all given nonterminal as tree up-down and left-right to the
end of *_PT and on every iteration places pointer to current tree
element into _T and pointer to data field of current element into
_pt. Used as header for cycle (e.g.
lrx_tree_do(Pnt,PCurElem,PCurData){process(PCurData);
clear(PCurElem);})
RETURN:
None.
ΓòÉΓòÉΓòÉ 9. LRX_REQ - the "do everything" procedure. ΓòÉΓòÉΓòÉ
This section describes how to use lrx_req to accomplish a variety of parsing
tasks. It uses the sample program LR_SQL.C to format a request to lrx_req via
the LRX_REQ structure.
It will probably be easiest to explain how to use lrx_req if you perform the
following actions in WorkFrame/2 as you read this part of this guide.
Copy the LR_SQL.PRJ file from the source diskette into \IBMWF to create the
LR_SQL example project. It assumes that your working directory is C:\LR.
Change the project description and make-file if this not the case.
If you have not already compiled the SQL grammar, do so now by running the make
file for this project. There will be a delay of 30 plus seconds while the
grammar is compiled. Compilation will produce the following files:
LR_SQL.STR This file contains preprocessor constants, macros, and C structure
declarations which help you work with the parse tree.
LR_SQL.CC This file contains generated C code to help you get addressability
from one nonterminal to its immediate descendents.
LR_SQL.N An abbrieviated version of LR_SQL.STR
Examine program LR_SQL.C.
Line 1 Should be included all programs, it defines constants and data
structures need to perform a parse.
Lines 2-3 are the files generated from the SQL grammar.
Lines 4-5 are the definitions of semantic routines. The lrx_cmd
macro simplifies their declaration.
Line 7 Declares an instance r of the parsing request structure LRX_REQ. The
following paragraphs describe how to set up this structure so that
lrx_req will perform the desired processing. This structure is
completely described in: the LRX_REQ structure.
Line 8 Declares cmd. it consists of two arrays of function pointers, pre and
post, for each nonterminal in the grammar. The LR_SQL_STR file
contains preprocessor constants <<GRAMMAR>>_<<NON_TERMINAL>>_n, e.g.
LR_SQL_SELECT_n, which give the number of each nonterminal in this
grammar. The addresses of the semantic functions for each
nonterminal are placed in the cmd.pre, and cmd.post arrays indexed by
these numbers, as shown on lines 13-15. Entries which are not in use
should be set to 0, or a default procedure.
r.pre and r.post should address the appropriate function arrays as
shown on lines 11, 12. If an array is not being used, the r.pre, or
r.post (or both) pointers should be 0.
The semantic functions are called as LR traverses the persistent
parse tree built internally during the syntax phase. pre functions
are called before the pre functions for a non terminal's descendents
in the parse tree. post routines are called after the post
routines for a nonterminal's descendents have been processed. So for
a typical fragment of a parse tree:
A
+----+----+
B C F
+
+--+--+
D E
The calling sequence will be:
1. PRE A
2. PRE B
3. POST B
4. PRE C
5. PRE D
6. POST D
7. PRE E
8. POST E
9. POST C
10. PRE F
11. POST F
12. POST A
Line 9 LR_SQL_NPS is the generated Nonterminal Pointer Set (NPS) work area.
You need at least one to process a parse. Addressability to it should
be set in r.nps, as shown on line 13. An NPS is used by the parsing
primitives to get addressability to a related nonterminals in the
parse tree.
Line 14, 15 Sets the pre command area to the default print routine. Line 16
sets in a specific routine to handle the CREATE_TS_OPTIONS
nonterminal.
Lines 17-23 Complete the set up of r.
Line 17. Specifies the file containing the input text. You may parse
either a file, or a string. Line 20 sets the bit indicating that
the contents of the file are to be read during the parse.
Line 18. Specifies the .LRS file containing the compiled grammar. You can
of course compile the grammar from lrx_req. In this case we are
assuming that the grammar has already been prepared by running
LR_SQL.MAK, as descibed at the top of this section.
Lines 19-23. Specifies the processing actions required. In this case, the
grammar is to be loaded from the specified file, as is the text to
be parsed. A parse is required, during which the semantic
functions will be invoked. After parsing the parse tree will be
printed, by default to LR_SQL.PRS. Finally all resources will be
freed. You may retain resources to avoid having to reload them
for the next action.
Line 24. The call to lrx_req is on line 24. lrx_req carries out the required
actions. If errors are found, r.rc is set to a non zero value,
otherwise, the semantic action functions will be invoked.
In this program the semantic functions are:
Lines 27 to 29. Print the details of a nonterminal.
Lines 33 to 41. Process some of the create options for a tablespace.
Each semantic function has a standard parameter list:
REQ The request structure to lrx_req
PT Pointer to the current nonterminal
Lines 34,35 Demonstrates one way of obtaining access to the non terminals
beneath the current nonterminal. Each nonterminal has an associated,
generated structure declared in lr_sql.str, which names the
nonterminals that can appear beneath it. LR_SQL.CC contains
generated routines to load this structure from the current
nonterminal.
Line 34 shows how to declare such a structure, while line 35 shows
how to call the associated routine for locating the descendent non
terminals.
Try running the program under the C debugger. Set break points at //26 and
//35 to watch the processing of each nonterminal.
ΓòÉΓòÉΓòÉ 9.1. The LRX_REQ structure ΓòÉΓòÉΓòÉ
The LRX_REQ structure define in LRX.INC is used to request services from
procedure 'lrx_req', the "do everything" procedure. The LRX_REQ structure
contains the following fields:
long req Actions to be performed as per lrx_req_* constants - see below. You
must specify some action in this field. All subsequent fields are
either optional input fields to support the requested actions, or
output fields.
The following constants can be | together to request actions. They
are listed in the order that lrx_req performs them.
lrx_req_load_gdl Load GDL file. The loaded text will be addressed via gdl.
You will need to specify lrx_req_free_gdl on this or a future
action to free this memory. GDL must be loaded for a grammar to
be compiled.
lrx_req_compile_gdl Compile GDL to create grammar file. Assumes that gdl
points to the grammar text to be compiled. A successful compile
will result in the grammar_file being set to the file that
contains the compiled grammar, for subsequent use in a load
grammar request.
lrx_req_load_grammar Load grammar file. A grammar must be loaded before it
can be used to parse a string. You may have multiple grammars
loaded at the same time.
lrx_req_load_text Load text file. Reads the file whose name is pointed to
by text_file, and sets text to point to the loaded string.
Alternatively, you may supply your own string to be parsed, it may
contain new line characters and other whitespace. It should be 0
terminated.
lrx_req_strip_comments Remove *, -- comment lines from input text. It is
necessary to remove positional comments (i.e. a comment that is
independent of the syntactic position), before parsing.
lrx_req_parse Perform parse, invoking the pre and post procedures. A Non
terminal Pointer Set work area is also required. See how to use
lrx_req for an example of setting up pre and post commands, and
how to set up the NPS area.
lrx_req_print_parse Print parse tree to <<GRAMMAR>>.PRS. Assists in code
development by showing you an actual parse tree.
lrx_req_rescan Rescan the parse tree invoking the semantic routines.
lrx_req_free_parse Free parse tree, otherwise it is kept in memory.
lrx_req_free_grammar Free grammar loaded version of compoiled grammar,
otherwise it it is kept in memory.
lrx_req_free_gdl Free GDL source statements, otherwise the source of the
grammar is kept in memory.
lrx_req_free_text Free the text to be parsed, otherwise it is kept in
memory.
lrx_req_free_compile Free compilation results, otherwise they are kept in
memory.
lrx_req_free_all Equivalent to:
lrx_req_free_parse |
lrx_req_free_grammar |
lrx_req_free_gdl |
lrx_req_free_text |
lrx_req_free_compile
long rc Output return code as defined in lrx_req_rc_* constants.
The following constants are | together into the rc field to provide a
return code from lrx_req.
lrx_req_rc_ok 0 - Request performed successfully
lrx_req_rc_no_grammar No grammar supplied but parse requested
lrx_req_rc_no_grammar_file No grammar file supplied, but load grammar
requested
lrx_req_rc_bad_grammar_file Bad grammar file supplied - errors occurred
during read
lrx_req_rc_no_gdl No GDL text supplied, but compile grammar requested
lrx_req_rc_no_gdl_file No GDL file supplied, but load GDL file requested
lrx_req_rc_bad_gdl_file Bad GDL file, errors occurred during read
lrx_req_rc_no_text No input text to be parsed, but parse, or comment
strip requested
lrx_req_rc_no_text_file No input text file to be loaded, but load text
file requested
lrx_req_rc_bad_text_file Bad input text file, errors occurred during read
lrx_req_rc_compile_errors Compile errors occurred, check <<GRAMMAR>>.LR
lrx_req_rc_parse_errors Parse errors occurred, check <<GRAMMAR>>.ERR
lrx_req_rc_no_nps No Nonterminal Pointer Set work area supplied
lrx_req_rc_no_action No action specified
lrx_req_rc_no_name No grammar name supplied, but gramar compile
requested
lrx_req_rc_no_parse_to_free No parse to free per request
lrx_req_rc_no_text_to_free No text to free per request
lrx_req_rc_no_grammar_to_free No compiled grammar to free per request
lrx_req_rc_no_gdl_to_free No GDL to free per request
lrx_req_rc_no_compile_to_free No compilation results to free per request
lrx_req_rc_no_parse_tree No parse tree available for printing
char *name Input name of grammar - only required if you are compiling a
grammar
LR_P *P Output parse tree. Set by a successful parse
LR *lr Output GDL grammar compilation results. Set as a result of grammar
compilation
LR2 *grammar Output - Set as a result of a successful grammar load grammar
char *grammar_file Input - File containing compiled grammar to be used for
this parse. If you have compiled one or more grammars with this
request structure, the name of the file containing the last
successfully compiled grammar is automaticallly placed in this field.
char *gdl Input/Output. String containing source GDL for grammar. Set by GDL
load from file request, or you may set it yourself to the string
containing the grammar to be compiled.
char *gdl_file Input - File containing source GDL for grammar. Set this field
if you intend to compile a GDL file.
char *text Input/Output - Text to be parsed. Set by load text from file
request, or you may set it yourself.
char *text_file Input - File containing text to be parsed. Set this field if
you intend to request that the text to be parsed be read from a file.
void (**pre)() Input - Pointer to Pre commands. An array of function pointers,
one per nonterminal in the grammar. The number of each nonterminal
is declared for you as a preprocessor constant in <<GRAMMAR>>.str.
See using lrx_req
void (**post)() Input - Pointer to Post commands. An array of function
pointers, one per nonterminal in the grammar. The number of each
nonterminal is declared for you as a preprocessor constant in
<<GRAMMAR>>.str. See using lrx_req
void *nps Pointer to Nonterminal Pointer Set. A work area of size (void *) *
number of nonterminals in the grammar.
long stack Default parser stack, will be set to 4K unless you set it higher.
4K has always proven satisfactory.
void *sysp User parameter. You may use this pointer to chain additional user
data. The LRX_REQ structure is passed as a parameter to each pre and
post command invoked.
ΓòÉΓòÉΓòÉ 10. Direct usage of parsing primitives ΓòÉΓòÉΓòÉ
How to use LR from your application program directly ?
1. If you already have LR-parsing table go to step 4.
2. Compile grammar ( lr_open ).
3. Release memory allocated by it ( lr_free ).
4. Load LR-parsing table ( lr2_open ).
5. Parse input files ( lr_parse_open ).
6. Use results with lrx-functions (Parse tree navigation primitives).
7. Free memory used by this parse ( lr_parse_free ).
8. If you need parse another text go to step 5.
9. Free resources allocated by compiled grammar ( lr2_free ).
ΓòÉΓòÉΓòÉ 10.1. Usage of the LR-parser within WorkFrame/2 ΓòÉΓòÉΓòÉ
Usage of the LR-parser within WorkFrame/2 is like usage of the LR-parser within
WorkFrame/2 .
ΓòÉΓòÉΓòÉ 10.2. Input data for the LR parser ΓòÉΓòÉΓòÉ
Input data for the LR parser is the text file containing the grammar
definition. The grammar definition must be given on GDL
ΓòÉΓòÉΓòÉ 10.3. Call of LR parser by user program ΓòÉΓòÉΓòÉ
For call of LR parser by user program the following C-functions are presented:
lr2_open - open compiled grammar;
lr2_free - release resources allocated by compiled grammar;
lr_parse_open - perform a parse;
lr_print_parse - print parse results;
lr_parse_free - Release the results of a parse.
See also Example of program performing a parse tree navigation.
ΓòÉΓòÉΓòÉ 10.3.1. lr2_open - open compiled grammar ΓòÉΓòÉΓòÉ
SYNTAX:
int lr2_open (LR2 **lr, char *ds);
PARAMETERS:
LR2 **lr pointer to pointer to compiled grammar that will be loaded by
this function.
char* ds Name of file contained compiled grammar.
EFFECT:
Load compiled grammar to memory from file named 'ds' and
place pointer to it in '*lr'.
RETURN:
Nothing.
ΓòÉΓòÉΓòÉ 10.3.2. lr2_free - release resources allocated by compiled grammar. ΓòÉΓòÉΓòÉ
SYNTAX:
void lr2_free (LR2 *lr);
PARAMETERS:
LR2 *lr pointer to loaded compiled grammar.
EFFECT:
release resources allocated by lr2_open.
RETURN:
Nothing.
ΓòÉΓòÉΓòÉ 10.3.3. lr_parse_open - perform a parse ΓòÉΓòÉΓòÉ
Perform a parse
SYNTAX: void lr_parse_open(LR_P **P, LR2 *lr, char *text, char
*path, long stack_size);
PARAMETERS:
LR_P **P Pointer to pointer to parse result.
LR2 *lr Pointer to condensed version of LR-parsing table.
char *text Text to be parsed.
char *path Path where will be placed resulting files. If path is 0,
the files will be located in the current working
directory. Empty line implies root directory.
EFFECT: Parses text 'text' using LR-parsing table 'lr' with stack
size = 'stack_size' placing parse result in 'P' and file
<<NAME>>.prs placed in path 'path'.
RETURN: Nothing.
ΓòÉΓòÉΓòÉ 10.3.4. lr_print_parse - print parse results ΓòÉΓòÉΓòÉ
SYNTAX:
void lr_print_parse (LR_P *p);
PARAMETERS:
LR_P *p pointer to parse results.
EFFECT:
Print parse result p to file <<NAME>>.PRS
RETURN:
Nothing.
ΓòÉΓòÉΓòÉ 10.3.5. lr_parse_free - release the results of a parse ΓòÉΓòÉΓòÉ
Release the results of a parse
SYNTAX: void lr_parse_free (LR_P *P);
PARAMETERS:
LR_P *P pointer to parse results.
EFFECT: Releases memory allocated by 'lr_parse_open'.
RETURN: Nothing.
ΓòÉΓòÉΓòÉ <hidden> Parse tree navigation primitives ΓòÉΓòÉΓòÉ
To navigate parse tree there are several program primitives and data
structures:
o lrx_n
o lrx_loc
o lrx_one
o lrx_zero
o lrx_add
o lrx_all
o lrx_zap
o lrx_up
o lrx_copy
o lrx_list_do
o lrx_tree_do
ΓòÉΓòÉΓòÉ 11. Breakpoint Technique of LR ΓòÉΓòÉΓòÉ
ΓòÉΓòÉΓòÉ 11.1. Quick start into Breakpoint Technique of LR ΓòÉΓòÉΓòÉ
Quick Start to the Breakpoint Technique of LR.
What is breakpoint technique (BT)?
BT is the thing that allows you to process parse tree dynamically. What does it
mean? This means that you can control the parse process and the creation of the
parse tree during parsing.
Basic structure for breakpoint processing is breakpoint set (BS). BS is the set
various breakpoints and global semantic action (it will be will be discussed
later).
The breakpoints that are in BS fall into two categories : nonterminal
breakpoints and special breakpoints.
Nonterminal breakpoints are those invoked by construction of nonterminals. E.g.
when the LR-parser reduces something to a nonterminal it will look through BS
for the breakpoint that is bounded with this nonterminal ("bounding" with
nonterminal means that any nonterminal breakpoint has number that is equal with
the number of the nonterminal to which the breakpoint is "bounded" (see
STR-file and N-files about number of nonterminal)), if the semantic action for
this breakpoint exists the parser will execute the breakpoint and will continue
parsing, else the parser'll check is the breakpoint active or not, if yes then
the parser will try to do global semantic action but if it does not exist too
then the parser will do nothing, and after that all the parser will continue
parsing.
The second type of breakpoints is (as mentioned above) special breakpoints.
There are three special breakpoints :
o start breakpoint,
o end-of-file breakpoint,
o error breakpoint.
Start breakpoint will be executed in the beginning of parsing process.
End-of-file breakpoint will be executed when the parser will encounter the end
of input file.
Error breakpoint will be executed when a syntax error will be detected.
Now about breakpoint execution. I think you wonder what is the 'breakpoint
execution'. Every breakpoint (it does not matter either nonterminal or special)
has:
o pointer to the parse tree node where the breakpoint is being executed,
o pointer to a semantic action and switches.
The pointer to the parse tree node means : pointer to the parse tree node that
is the nonterminal to which the breakpoint was bounded (for nonterminal
breakpoints), or the parse tree node where start or end of file was encountered
or a syntax error was detected (for special breakpoints).
The pointer to a semantic action means pointer to the function with special
prototype (it is explained in the 'lr_bp_*' functions description) that will be
executed if the switches will be in definite states.
The switches. If stop switch is set on then the semantic action of this
breakpoint will be executed, else the semantic action will not be executed. If
stop switch is set on then the parsing process will be interrupted, continue
information will be written to BS and control will be returned to the caller of
'lr_bp_parse*' function.
Execution of a breakpoint means : checking switches and calling or not calling
the semantic action for the breakpoint (the pointer to the parse tree node will
be passed to the semantic action; see 'lr_bp_*' functions' description for
prototypes and examples) according to current states of the switches.
About global semantic action from BS. This semantic action will be executed for
invoked breakpoint if the breakpoint is active and has no own semantic action.
Now briefly repeat all of the above and add some additional information.
There is breakpoint set that contains set of user-defined nonterminal
breakpoints, special breakpoints and global semantic action.
A nonterminal breakpoint contains pointer, action and switches. By default
there is no semantic action in a created breakpoint, but user can define it
using 'lr_bp_*' functions. It is desirable to set switches to needed states (of
course using 'lr_bp_*' macros) because their default value may not satisfy you.
Note:
There is one remark about BS : when we say nonterminal we mean not the concrete
nonterminal but class of concrete parse tree nodes that are associated with,
for example nonterminal IF in grammar definition; so there may be only one
breakpoint associated with one nonterminal (so this breakpoint will be executed
on every just reduced parse tree node that was reduced to the nonterminal
marked with the breakpoint).
To use BT you must do following steps:
1. Create BS:
o lr_bp_init
2. Initialize needed breakpoints with switches and semantic actions:
o lr_bp_*_on;
o lr_bp_*_off;
o lr_bp_command_*;
o lr_bp_feed*;
o lr_bp_register_command.
3. Parse text:
o lr_bp_parse_open.
4. If control was returned to you (stop switches in some breakpoints were set
on) then you can do something and/or continue parsing and/or do nothing:
o lr_bp_next;
o lr_bp_start;
o lr_bp_reduce;
o lr_bp_go.
5. Free memory used by BS:
o lr_bp_free.
ΓòÉΓòÉΓòÉ <hidden> lr_bp_*_off ΓòÉΓòÉΓòÉ
o lr_bp_active_off;
o lr_bp_stop_off;
o lr_bp_start_off;
o lr_bp_eof_off;
o lr_bp_error_off;
o lr_bp_switch_off;
o lr_bp_command_off.
ΓòÉΓòÉΓòÉ <hidden> lr_bp_*_on ΓòÉΓòÉΓòÉ
o lr_bp_active_on;
o lr_bp_stop_on;
o lr_bp_start_on;
o lr_bp_eof_on;
o lr_bp_error_on;
o lr_bp_switch_on;
o lr_bp_command_on.
ΓòÉΓòÉΓòÉ <hidden> lr_bp_command_* ΓòÉΓòÉΓòÉ
o lr_bp_command_on;
o lr_bp_command_off;
o lr_bp_command_active;
o lr_bp_command_start;
o lr_bp_command_eof;
o lr_bp_command_err.
ΓòÉΓòÉΓòÉ <hidden> lr_bp_feed* ΓòÉΓòÉΓòÉ
o lr_bp_feed;
o lr_bp_feed_active.
ΓòÉΓòÉΓòÉ 11.2. Prototype of semantic action. ΓòÉΓòÉΓòÉ
Protoype of a semantic action:
An example of semantic action prototype:
void cmd(LR_BPT *);
An example of array of semantic actions:
void (**cmd_vec)(LR_BPT *);
ΓòÉΓòÉΓòÉ 11.3. Basic types of LR Breakpoint Technique. ΓòÉΓòÉΓòÉ
Basic types of LR Breakpoint Technique are:
LR_BPT - type of breakpoint (struct);
LR_BP - type of breakpoint set (struct);
EXAMPLES:
An example of semantic action prototype:
void cmd(LR_BPT *);
An example of array of semantic actions:
void (**cmd_vec)(LR_BPT *);
An example of pointer to a breakpoint:
LR_BPT *pBPT;
An example of pointer to a breakpoint set:
LR_BP *pBP;
ΓòÉΓòÉΓòÉ 11.4. lr_bp_field - direct write to breakpoint structure ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_field(LR_BP *_BP, long _n, _field, _value);
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint;
_field name of needed field;
_value value to send (by '='operation) to the specified field
('value' must have the same type as 'field');
EFFECT:
Write value '_value' in the field '_field' of a breakpoint
handler that is located in breakpoint set '*(_BP)' by
number '_n'.
RETURN:
Nothing.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.5. lr_bp_n - get number of breakpoint ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_n(LR_BPT *_BPT);
PARAMETERS:
_BPT pointer to a breakpoint;
EFFECT:
Obtain number of the breakpoint.
RETURN:
Number of the breakpoint.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.6. lr_bp_do - scan breakpoint set ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_do(LR_BP *_BP);
PARAMETERS:
_BP pointer to a breakpoint set;
EFFECT:
Scans breakpoint set '*(_BP)'. Work counter is
(_BP)->bptc.
RETURN:
Nothing.
EXAMPLE:
lr_bp_do(pTEST_BP)
{
lr_bp_field(pTEST_BP,pTEST_BP->bptc,isactive,1)
}
This example will scan all *(pTEST_BP) and will make all
breakpoints in it active.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.7. lr_bp_bpt - obtain pointer to predefined breakpoint ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_bpt(LR_BP *_BP, NAME );
PARAMETERS:
_BP pointer to breakpoint set;
_NAME one of this -> {start, eof, err};
EFFECT:
Obtain pointer to predefined breakpoint.
RETURN:
Pointer to the specified breakpoint handler.
EXAMPLE:
start_breakpoint = lr_bp_bpt(pTEST_BP,start);
This example will assign pointer to the start breakpoint
handler to 'start_breakpoint'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.8. lr_bp_active_on - set breakpoint switch 'active'on ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_active_on(LR_BP *_BP, long _n);
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in the breakpoint set;
EFFECT:
Turns on the 'isactive' switch in the breakpoint handler
number '_n' in '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_active_on(pTEST_BP, 34);
This example will turn on the 'isactive' switch in the
breakpoint handler number 34 in '*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.9. lr_bp_active_off - set breakpoint switch 'active'off ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_active_off(LR_BP *_BP, long _n);
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in the breakpoint set;
EFFECT:
Turns off the 'isactive' switch in the breakpoint handler
number '_n' in '*(_BP)'.
RETURN:
Nothing.
NOTES:
EXAMPLE:
lr_bp_active_off(pTEST_BP, 34);
This example will turn off the 'isactive' switch in the
breakpoint handler number 34 in '*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.10. lr_bp_stop_on - set breakpoint switch 'stop'on ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_stop_on(LR_BP *_BP, long _n);
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in the breakpoint set;
EFFECT:
Turn on the 'isstop' switch in the breakpoint handler
number '_n' in '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_stop_on(pTEST_BP, 34);
This example will turn on the 'isstop' switch in the
breakpoint handler number 34 in '*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.11. lr_bp_stop_off - set breakpoint switch 'stop'off ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_stop_off(LR_BP *_BP, long _n);
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in the breakpoint set;
EFFECT:
Turn off the 'isstop' switch in the breakpoint handler
number '_n' in '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_stop_off(pTEST_BP, 34);
This example will turn off the 'isstop' switch in the
breakpoint handler number 34 in '*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.12. lr_bp_start_on - set breakpoint switch 'start'on ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_start_on(LR_BP *_BP, long _n);
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in the breakpoint set;
EFFECT:
Turn on the 'isstart' switch in the breakpoint handler
number '_n' in '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_start_on(pTEST_BP, 34);
This example will turn on the 'isstart' switch in the
breakpoint handler number 34 in '*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.13. lr_bp_start_off - set breakpoint switch 'start'off ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_start_off(LR_BP *_BP, long _n);
PARAMETERS:
_BP pointer to a breakpoint set;
_n in the breakpoint set;
EFFECT:
Turn off the 'isstart' switch in the breakpoint handler
number '_n' in '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
Example of usage -
lr_bp_start_off(pTEST_BP, 34);
This example will turn off the 'isstart' switch in the
breakpoint handler number 34 in '*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.14. lr_bp_eof_on - set breakpoint switch 'eof'on ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_eof_on(LR_BP *_BP, long _n);
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in the breakpoint set;
EFFECT:
Turns on the 'iseof' switch in the breakpoint handler
number '_n' in '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_eof_on(pTEST_BP, 34);
This example will turn on the 'iseof' switch in the
breakpoint handler number 34 in '*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.15. lr_bp_eof_off - set breakpoint switch 'eof'off ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_eof_off(LR_BP *_BP, long _n);
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in the breakpoint set;
EFFECT:
Turns off the 'iseof' switch in the breakpoint handler
number '_n' in '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_eof_off(pTEST_BP, 34);
This example will turn off the 'iseof' switch in the
breakpoint handler number 34 in '*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.16. lr_bp_error_on - set breakpoint switch 'error'on ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_error_on(LR_BP *_BP, long _n);
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in the breakpoint set;
EFFECT:
Turns on the 'iserr' switch in the breakpoint handler
number '_n' in '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_error_on(pTEST_BP, 34);
This example will turn on the 'iserr' switch in the
breakpoint handler number 34 in '*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.17. lr_bp_error_off - set breakpoint switch 'error'off ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_error_off(LR_BP *_BP, long _n);
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in the breakpoint set;
EFFECT:
Turns off the 'iserr' switch in the breakpoint handler
number '_n' in '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_error_off(pTEST_BP, 34);
This example will turn off the 'iserr' switch in the
breakpoint handler number 34 in '*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.18. lr_bp_switch_on - set breakpoint switches 'active'and 'stop_here'on ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_switch_on(LR_BP *_BP, long _n);
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in the breakpoint set;
EFFECT:
Turns on the 'isactive' and 'stop_here' switches in the
breakpoint handler number '_n' in '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_switch_on(pTEST_BP, 34);
This example will turn on the 'isactive' and 'stop_here'
switches in the breakpoint handler number 34 in
'*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.19. lr_bp_switch_off - set breakpoint switches 'active'and 'stop_here'off ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_switch_off(LR_BP *_BP, long _n);
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in the breakpoint set;
EFFECT:
Turns off the 'isactive' and 'stop_here' switches in the
breakpoint handler number '_n' in '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_switch_off(pTEST_BP, 34);
This example will turn off the 'isactive' and 'stop_here'
switches in the breakpoint handler number 34 in
'*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.20. lr_bp_command_on - set semantic action to a breakpoint ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_command_on(LR_BP *_BP, long _n, void _cmd(LR_BPT
*));
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in given breakpoint set;
_cmd semantic action ;
EFFECT:
It will assign semantic action '_cmd' to breakpoint
handler by number '_n' in breakpoint set '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_command_on(pTEST_BP,34,cmd);
This example will set 'cmd' semantic action to the
breakpoint handler by number 34 that is located in
breakpoint set '*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.21. lr_bp_command_off - delete semantic action from a breakpoint ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_command_off(LR_BP *_BP, long _n);
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in given breakpoint set;
_cmd semantic action
EFFECT:
It will zero (set NULL pointer to) semantic action field
in to breakpoint handler by number '_n' in breakpoint set
'*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_command_off(pTEST_BP,34);
This example will set semantic action of breakpoint handler
by number 34 that is located in breakpoint set
'*(pTEST_BP)' to zero ( no semantic action will be executed
if breakpoint number 34 will be encountered ).
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.22. lr_bp_command_active - set semantic action to a breakpoint and makes the breakpoint active ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_command_active(LR_BP *_BP, long _n, void _cmd(LR_BPT
*));
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of needed breakpoint in given breakpoint set;
_cmd semantic action
EFFECT:
It will assign semantic action '_cmd' to breakpoint
handler by number '_n' in breakpoint set '*(_BP)' and make
this breakpoint active (by setting 'isactive' switch to 1).
RETURN:
Nothing.
EXAMPLE:
lr_bp_command_active(pTEST_BP,34,cmd);
This example will set semantic action 'cmd' to breakpoint
handler by number 34 that is located in breakpoint set
'*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.23. lr_bp_command_start - set semantic action to start breakpoint ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_command_start(LR_BP *_BP, void _cmd(LR_BPT *));
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of the needed breakpoint in given breakpoint set;
_cmd semantic action
EFFECT:
It will assign semantic action '_cmd' to the
start-breakpoint of breakpoint set '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_command_start(pTEST_BP,cmd);
This example will set semantic action 'cmd' to start
breakpoint handler that is located in breakpoint set
'*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.24. lr_bp_command_eof - set semantic action to eof breakpoint ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_command_eof(LR_BP *_BP, void _cmd(LR_BPT *));
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of the needed breakpoint in given breakpoint set;
_cmd semantic action
EFFECT:
It will assign semantic action '_cmd' to the
eof-breakpoint (end of file breakpoint) of breakpoint set
'*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_command_eof(pTEST_BP,cmd);
This example will set semantic action 'cmd' to eof
breakpoint handler that is located in breakpoint set
'*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.25. lr_bp_command_err - set semantic action to error breakpoint ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_command_err(LR_BP *_BP, void _cmd(LR_BPTT *));
PARAMETERS:
_BP pointer to a breakpoint set;
_n number of the needed breakpoint in given breakpoint set;
_cmd semantic action
EFFECT:
It will assign semantic action '_cmd' to the error
breakpoint of breakpoint set '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_command_off(pTEST_BP,cmd);
This example will set semantic action 'cmd' to error
breakpoint handler that is located in breakpoint set
'*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.26. lr_bp_feed - feed array of semantics into breakpoint set ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_feed(LR_BP *_BP, void (**_CMDS)(LR_BPT *));
PARAMETERS:
_BP pointer to a breakpoint set;
_CMDS an array of semantic actions
EFFECT:
'lr_bp_feed' will assign semantic actions to all
breakpoints in '*(_BP)'. The semantic actions will be taken
from array '_CMDS'. The semantic action (_CMDS)[0] will be
assigned to the breakpoint number 0, the semantic action
(_CMDS)[1] will be assigned to the breakpoint number 1 etc.
If number of breakpoints is larger than number of defined
elements in '_CMDS' then junk will be written instead of
semantic actions in last breakpoints.
RETURN:
Nothing.
EXAMPLE:
lr_bp_feed(pTEST_BP, SActions);
This example will assign actions from 'SActions' to all
breakpoints from breakpoint set '*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.27. lr_bp_feed_active - feed array of semantics into breakpoint set and make all fed breakpoints active ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_feed_active(LR_BP *_BP, void (**_CMDS)(LR_BPT *));
PARAMETERS:
_BP pointer to a breakpoint set;
_CMDS an array of semantic actions
EFFECT:
'lr_bp_feed_active' will do the same action as
'lr_bp_feed' but in addition it will make all breakpoints
in '*(_BP)' active (by setting 'isactive' switch to 1).
RETURN:
Nothing.
EXAMPLE:
lr_bp_feed_active(pTEST_BP, SActions);
This example will assign actions from 'SActions' to all
breakpoints from breakpoint set '*(pTEST_BP)' and will make
all breakpoints in '*(pTEST_BP)' active.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.28. lr_bp_register_command - register global semantic ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_register_command(LR_BP *_BP, void _cmd(LR_BPT *));
PARAMETERS:
_BP pointer to a breakpoint set;
_cmd semantic action
EFFECT:
It will register semantic action '_cmd' as global semantic
action for breakpoint set '*(_BP)'.
RETURN:
Nothing.
EXAMPLE:
lr_bp_register_command(pTEST_BP, GlobalAction);
This example will register semantic action 'GlobalAction'
as global semantic action for breakpoint set '*(pTEST_BP)'.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.29. lr_bp_go - go until needed breakpoint will be encountered ΓòÉΓòÉΓòÉ
SYNTAX:
lr_bp_go(LR_BPT *_BPT_S, long _n);
PARAMETERS:
_BPT_S pointer to a breakpoint;
_n number of the breakpoint; where to stop;
EFFECT:
It will start parsing from the breakpoint '*(_BPT_S)' to
the breakpoint with the number '_n'
RETURN:
Nothing.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.30. lr_bp_init - create breakpoint set ΓòÉΓòÉΓòÉ
SYNTAX:
LR_BP *lr_bp_init(char *grammar2);
PARAMETERS:
grammar2 name of file containing condensed grammar;
EFFECT:
Creates a new breakpoint set and initializes it with a
condensed grammar that is located in file 'grammar2'.
RETURN:
Pointer to the initialized breakpoint set, or 0 (zero) if
the specified file can not be opened.
NOTES:
By default, no breakpoint has a semantic. Predefined
breakpoints 'bpt_start', 'bpt_eof' and 'bpt_err' are
active. 'bpt_eof' and 'bpt_err' are stop breakpoints.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.31. lr_bp_start - start parsing from specified position using breakpoint set ΓòÉΓòÉΓòÉ
SYNTAX:
LR_BPT *lr_bp_start(LR_BP *bp, char *text);
PARAMETERS:
bp pointer to a breakpoint set;
text ASCIIZ (null terminated) character string of text to be
parsed;
EFFECT:
It will start parsing of 'text' using breakpoint set
'*(bp)'and stop on first active stop breakpoint from
'*(bp)'
RETURN:
Pointer to the breakpoint which stopped the parsing.
NOTES:
If there were the results of previous parsing (field
bp->lp is nonzero), the function at first releases them.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.32. lr_bp_reduce - perform single reduction ΓòÉΓòÉΓòÉ
SYNTAX:
LR_BPT *lr_bp_reduce(LR_BP *bp, LR2_S **S, char **C, char
**c, char *sc, LR_BPTS s, long n);
PARAMETERS:
bp pointer to a breakpoint set;
S address of pointer to current LR-automaton state;
C pointer to text at which reduction starts;
c pointer to text at which reduction stops;
sc text parsed from the previous break;
s breakpoint state;
n breakpoint reduction counter;
EFFECT:
Performs a single reduction considering breakpoint set.
RETURN:
Pointer to encountered breakpoint, or 0 (zero) if the
reduction doesn't lead to break (correspondent breakpoint
is inactive).
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.33. lr_bp_next - continue parsing until next breakpoint ΓòÉΓòÉΓòÉ
SYNTAX:
LR_BPT *lr_bp_next(LR_BPT *bpt);
PARAMETERS:
bpt pointer to a breakpoint;
EFFECT:
It will continue the parsing from the breakpoint 'bpt'
until next breakpoint.
RETURN:
Returns pointer to the next encountered breakpoint.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.34. lr_bp_free - delete breakpoint set from memory ΓòÉΓòÉΓòÉ
SYNTAX:
void lr_bp_free(LR_BP *bp);
PARAMETERS:
bp pointer to a breakpoint set;
EFFECT:
Deletes breakpoint set '*(bp)' from memory.
RETURN:
Nothing.
NOTES:
After this function 'bp' will point to undefined place!!!
So BE CAREFULL!!!
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.35. lr_bp_error - default error semantic ΓòÉΓòÉΓòÉ
SYNTAX:
void lr_bp_error(LR_BPT *bpt);
PARAMETERS:
bpt pointer to error breakpoint handler;
EFFECT:
It will print parse errors to <<GRAMMAR_NAME>>.ERR file
where <<GRAMMAR_NAME>> is the name of the grammar according
to which the input text file was parsed. It is default
error breakpoint semantics.
RETURN:
Nothing.
NOTES:
This routine is recommended to be used in run-time
semantics.
EXAMPLE:
lr_bp_command_err(bp, lr_bp_error);
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 11.36. lr_bp_parse_open - perform parsing of a text using a grammar ΓòÉΓòÉΓòÉ
SYNTAX:
LR_P *lr_bp_parse_open(char *grammar2,char *text,char
*file);
PARAMETERS:
grammar2 name of file where condensed grammar is located;
text pointer to an area in memory where text to be parsed is
located;
file name of file from where the 'text' was loaded (used in
construction of names of .PRS etc. files);
EFFECT:
Reads grammar from file with name stored in 'grammar2',
parses text from 'text' using the loaded grammar and
outputs results in file with name stored in 'file'
RETURN:
Pointer to parse results (parse tree), or 0 (zero) if the
file with the condensed grammar can not be opened.
Basic LR Breakpoint Technique types.
ΓòÉΓòÉΓòÉ 12. Technical Support ΓòÉΓòÉΓòÉ
Technical Support may be obtained by contacting:
Philip R Brenan at Compuserve 71022, 3620
ΓòÉΓòÉΓòÉ 13. Grammar of a simple sequences ΓòÉΓòÉΓòÉ
This grammar defines the syntax of a simple sequences.
LR
(
NAME(SQNS_1)
TITLE('Sequences 1.')
PATH
STRUCT
PRINT
RULES
(
sequence ( alpha item ( zero ) end_of_seq)
item (alpha)
(omega)
alpha ('abcd'(choice mixed))
omega ('123456789'(choice))
end_of_seq ('.')
)
)
Grammar definition of a simple sequences.
See also
o Parsing tree of a simple sequence ,
o STR-file and N-file .
ΓòÉΓòÉΓòÉ 14. Example of usage of "do everything" procedure (lr_sql.c) ΓòÉΓòÉΓòÉ
/*
______________________________________________________________________________
Example LR processing
Philip R Brenan, Transcendental Automation, 1993, CompuServe 71022,3620
______________________________________________________________________________
*/
#include "lrx.inc" //01 Include this file in all parsing programs
#include "lr_sql.str" //02 Generated declarations for SQL
#include "lr_sql.cc" //03 Generated load procedures for SQL
lrx_cmd(lr_sql_print); //04 Generic print routine for any non terminal
lrx_cmd(lr_sql_ts_options); //05 Print routine for create tablespace options
/*
_______________________________________________________________________________
Parse the sql in LR_SQL.SQL and print each non terminal
_______________________________________________________________________________
*/
int main(void) //06 Main procedure
{LRX_REQ r; //07 Request structure to lrx_req
LR_SQL_cmd cmd; //08 Procedures to implement non terminals for SQL
LR_SQL_NPS nps; //09 Non terminal work area for SQL
int i, j; //10 Counters
r.pre = cmd.pre; //11 Initialize pointer to pre commands for SQL
r.post = 0; //12 No post commands
r.nps = &nps; //13 Initialize pointer to Non terminal Pointer Set work area for SQL
/*
_______________________________________________________________________________
Load print routine into each non terminal's pre command - must initialize each
semantic routine pointer, or set to zero. r.post will be zero and hence ignored.
_______________________________________________________________________________
*/
for(i = 0; i < LR_SQL_n; ++i) //14 For each non terminal in SQL
{cmd.pre[i] = lr_sql_print; //15 Set print routine as semantic action
}
cmd.pre[LR_SQL_CREATE_TS_OPTIONS_n] = lr_sql_ts_options;
//16 Load semantic action for specific non terminal
/*
_______________________________________________________________________________
Request parse of the sql in LR_SQL.SQL and print each non terminal
_______________________________________________________________________________
*/
r.text_file = "lr_sql.sql"; //17 Name the input filer
r.grammar_file = "lr_sql.lrs"; //18 Name grammar file
r.req = lrx_req_load_grammar | //19 Load grammar
lrx_req_load_text | //20 Load text
lrx_req_parse | //21 Parse text with grammar
lrx_req_print_parse | //22 Print parse tree
lrx_req_free_all; //23 Free all parse resources
/*
_______________________________________________________________________________
Perform parse and exit
_______________________________________________________________________________
*/
lrx_req(&r); //24 Perform requests
}
/*
_______________________________________________________________________________
Generic Semantic action
REQ - request list
PT - Non terminal pointer
_______________________________________________________________________________
*/
lrx_cmd(lr_sql_print) //25 Generic print
{printf("%s", PT->k); //26 Print non terminal name
if (PT->t) //27 If non terminal has a value
printf(" = %s", PT->t); //28 Print associated value
printf("\n"); //29 New line
}
/*
_______________________________________________________________________________
Put a non terminal - lrx_concat concatenates all the text under the given
non terminal
_______________________________________________________________________________
*/
void lr_sql_put(LR_PT *pt) //30 Put a non terminal
{char c[256]; //31 Character buffer
if (pt) printf("%s ", lrx_concat(c, pt)); //32 Print non terminal if present
}
/*
_______________________________________________________________________________
CREATE_TS_OPTIONS semantic action.
Get addressability to non terminals beneath current non terminal, and print them
REQ - request list - from main procedure
PT - Non terminal pointer
_______________________________________________________________________________
*/
lrx_cmd(lr_sql_ts_options) //33 Process CREATE_TS_OPTIONS non terminal
{LR_SQL_NT_CREATE_TS_OPTIONS a; //34 Pointers to this non terminal's immediate decendents
LR_SQL_LOAD_NT_CREATE_TS_OPTIONS(&a, PT); //35 Get addressability to non terminals dependents
lr_sql_put(a.FREEPAGE); //36 Print FREEPAGE
lr_sql_put(a.PCTFREE); //37 Print PCTFREE
lr_sql_put(a.BUFFERPOOL3); //38 Print BUFFERPOOL
lr_sql_put(a.LOCKSIZE); //39 Print LOCKSIZE
lr_sql_put(a.CLOSE); //40 Print CLOSE
printf("\n"); //41 New line
}
ΓòÉΓòÉΓòÉ 15. Sample of LR application ΓòÉΓòÉΓòÉ
#include "sample.h"
/*
ΓòöΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòù
Γòæ Copyright (C) Transcendental Automation, 1993. Γòæ
ΓòƒΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓòó
Γòæ SAMPLE.C - The main file of project. Γòæ
ΓòƒΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓòó
Γòæ This file contains next functions: Γòæ
Γòæ Γòæ
Γòæ void main(void) Γòæ
Γòæ void InitAll(char *s) - Initialize all resources and load file passed as Γòæ
Γòæ first argument of prgram or (if nothing was passed Γòæ
Γòæ to programm) 'sample.txt'. Γòæ
Γòæ Γòæ
Γòæ void FreeAll(void) - Rlease all resources Γòæ
ΓòƒΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓòó
Γòæ Description of program: Γòæ
Γòæ This program is an interpreter of simple grammar. Γòæ
Γòæ First program initialize stack of float , vartable ,load compiled grammar Γòæ
Γòæ and so on. Then it launch parsing of the text contained in file passed as Γòæ
Γòæ argument or 'sample.txt'.Then program free all allocated resources. Γòæ
ΓòÜΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓò¥
Requred files:
TABLE.C
COMMANDS.C
SAMPLE.H
SAMPLE.MAK
SAMPLE.GR
*/
LRSAF cmd[SAMPLE_n];
SAMPLE_PT NTPS; // nonterminal pointer set
LR2 *grammar; // Pointer to compiled grammar
void InitAll(char *);
void FreeAll();
char *text; // text to parse
/*
___________________________________________________________________________
The main function
___________________________________________________________________________
*/
int main(int e,char **s)
{puts("Copyright (C) Transcendental Automation, 1993.");
if(s[1]==0)
puts("Usage : sample [input_file]");
InitAll(s[1]);
puts("Processing..."); /**/
lrx_parse(0,0,cmd,(LRX_PT*)&NTPS,grammar,text,STACK_SIZE,0);//launch parsing of text
//then semantics action. /**/
FreeAll();
}
/*
______________________________________________________________________________
This function initializes all needed resources.
______________________________________________________________________________
*/
void InitAll(char *name)
{//initialize internal tables.
InitTable (); // initializing vartable.
InitFloatStack (); // initializing stack of floats.
InitCmdTable (); // initializing table of semantic actions. /**/
lr2_open(&grammar,"sample.lrs"); //open compiled grammar
text = u_load_ds( name ? name : "sample.txt" );//load file to memory /**/
printf("Input file : %s\n",name ? name : "sample.txt");
if(!text)
{puts("Error : unable to open input file.");
exit(3452);
}
puts("Input text :");
puts(text);
}
/*
______________________________________________________________________________
This function releases all allocated resources.
______________________________________________________________________________
*/
void FreeAll(void) /**/
{u_free_ds(text); // free alocated memory
lr2_free(grammar); // release compiled grammar /**/
FreeTable (); // free vartable.
FreeFloatStack (); // freestack of floats
}
ΓòÉΓòÉΓòÉ <hidden> Sample_h ΓòÉΓòÉΓòÉ
#ifndef __SAMPLE_H
#define __SAMPLE_H
/*
ΓòöΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòù
Γòæ Copyright (C) Transcendental Automation, 1993. Γòæ
ΓòƒΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓòó
Γòæ SAMPLE.H Γòæ
ΓòƒΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓòó
Γòæ This file is used by all modules and contains all necessary definitions Γòæ
Γòæ and declarations Γòæ
ΓòÜΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓò¥
*/
#include <io.h>
#include <lrx.inc>
#include <process.h>
#include "sample.str"
#define STACK_SIZE 1000 // size of stack of automaton.
typedef void(*LRSAF)(void*,SAMPLE_PT*,LR_PT*);// type of semantic action.
extern LRSAF cmd[SAMPLE_n]; //table of semantic action(LRSAF - LR Semantic Action Function).
void InitCmdTable(); //initialization of this table
extern SAMPLE_PT NTPS; // nonterminal pointer set
extern LR2 *grammar; // Pointer to compiled grammar
void InitTable (void); // see table.c for more information about these
float LookUp (char*); // functions.
void SetItem (char*,float);
void FreeTable (void);
void InitFloatStack (void);
void pushFloat (float);
float popFloat (void);
void FreeFloatStack (void);
#endif
ΓòÉΓòÉΓòÉ <hidden> Sample_str ΓòÉΓòÉΓòÉ
#ifndef SAMPLE_PT_INC
#define SAMPLE_PT_INC
/*
______________________________________________________________________________
Nonterminal parse items for SAMPLE grammar
______________________________________________________________________________
*/
typedef struct SAMPLE_PT
{LR_PT *l;
LR_P *p;
LR_PT *key[29];
} SAMPLE_PT;
#define SAMPLE_ADD(_T) ((_T).l = (_T).key[0])
#define SAMPLE_ADD_n 0
#define SAMPLE_ALPHA(_T) ((_T).l = (_T).key[1])
#define SAMPLE_ALPHA_n 1
#define SAMPLE_ALPHA_NUMERIC(_T) ((_T).l = (_T).key[2])
#define SAMPLE_ALPHA_NUMERIC_n 2
#define SAMPLE_ASSIGN(_T) ((_T).l = (_T).key[3])
#define SAMPLE_ASSIGN_n 3
#define SAMPLE_ASSIGNS(_T) ((_T).l = (_T).key[4])
#define SAMPLE_ASSIGNS_n 4
#define SAMPLE_DIGIT(_T) ((_T).l = (_T).key[5])
#define SAMPLE_DIGIT_n 5
#define SAMPLE_DIV(_T) ((_T).l = (_T).key[6])
#define SAMPLE_DIV_n 6
#define SAMPLE_E(_T) ((_T).l = (_T).key[7])
#define SAMPLE_E_n 7
#define SAMPLE_EXP(_T) ((_T).l = (_T).key[8])
#define SAMPLE_EXP_n 8
#define SAMPLE_F(_T) ((_T).l = (_T).key[9])
#define SAMPLE_F_n 9
#define SAMPLE_FLOAT(_T) ((_T).l = (_T).key[10])
#define SAMPLE_FLOAT_n 10
#define SAMPLE_IDENTIFIER(_T) ((_T).l = (_T).key[11])
#define SAMPLE_IDENTIFIER_n 11
#define SAMPLE_MUL(_T) ((_T).l = (_T).key[12])
#define SAMPLE_MUL_n 12
#define SAMPLE_NEG(_T) ((_T).l = (_T).key[13])
#define SAMPLE_NEG_n 13
#define SAMPLE_S(_T) ((_T).l = (_T).key[14])
#define SAMPLE_S_n 14
#define SAMPLE_SIGN(_T) ((_T).l = (_T).key[15])
#define SAMPLE_SIGN_n 15
#define SAMPLE_SUB(_T) ((_T).l = (_T).key[16])
#define SAMPLE_SUB_n 16
#define SAMPLE_T(_T) ((_T).l = (_T).key[17])
#define SAMPLE_T_n 17
#define SAMPLE__DIGIT(_T) ((_T).l = (_T).key[18])
#define SAMPLE__DIGIT_n 18
#define SAMPLE__e_(_T) ((_T).l = (_T).key[19])
#define SAMPLE__e__n 19
#define SAMPLE_point(_T) ((_T).l = (_T).key[27])
#define SAMPLE_point_n 27
#define SAMPLE_n 29
#endif
ΓòÉΓòÉΓòÉ <hidden> Table_c ΓòÉΓòÉΓòÉ
#include "sample.h"
#include <malloc.h>
/*
ΓòöΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòù
Γòæ Copyright (C) Transcendental Automation, 1993. Γòæ
ΓòƒΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓòó
Γòæ TABLE.C Γòæ
Γòæ This file contains sourse code of functions: Γòæ
ΓòƒΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓòó
Γòæ Work with table of variables Γòæ
Γòæ void InitTable (void) - initialize vartable. Γòæ
Γòæ float LookUp (char* nm) - search in vartable variable with name Γòæ
Γòæ 'nm' if not found create new variabe inΓòæ
Γòæ vartable and set it with zero. Γòæ
Γòæ Γòæ
Γòæ void AddItem (char*t,float f) - add new var named 'nm'to vartableΓòæ
Γòæ and set it with 'f'. Γòæ
Γòæ void SetItem (char* t,float f) - set var named 'nm' with 'f'. Γòæ
Γòæ void FreeTable (void) - free resources allocated by Γòæ
Γòæ vartable Γòæ
ΓòƒΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓòó
Γòæ Work with stack of floats Γòæ
Γòæ void pushFloat (float f) - put 'f' to stack Γòæ
Γòæ float popFloat (void) - get 'f' from stack Γòæ
Γòæ void FreeFloatStack () - free stack Γòæ
Γòæ void InitFloatStack () - initialize stack Γòæ
ΓòÜΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓò¥
*/
/*
_____________________________________________________________________________
VARTABLE SECTION
_____________________________________________________________________________
*/
/*
_____________________________________________________________________________
The structure 'VarTableItem' represents element of vartable.
_____________________________________________________________________________
*/
struct VarTableItem
{char* name; // the name of variable
float val; // the value of variable
struct VarTableItem *next; // pointer to next variable
};
static struct VarTableItem* FList; //pointer to the first variable in the table.
/*
______________________________________________________________________________
Initialize vartable
______________________________________________________________________________
*/
void InitTable (void)
{FList = 0;
}
void AddItem (char*t,float f);
/*
_____________________________________________________________________________
Look up variable in the vartable and return its value if found or
add variable with value 0 to vartable and return 0.
_____________________________________________________________________________
*/
float LookUp (char* nm)
{struct VarTableItem *cur;
cur = FList;
while ( cur && stricmp(cur->name,nm) )
cur = cur -> next;
if ( cur == 0)
{AddItem(nm,0);
return 0;
}
else
return cur->val;
}
/*
_____________________________________________________________________________
Add item to vartable.
_____________________________________________________________________________
*/
void AddItem (char*t,float f)
{struct VarTableItem *cur = malloc(sizeof(struct VarTableItem));
cur->next = FList;
cur->name = strdup(t);
strupr(cur->name);
cur->val = f;
FList = cur;
}
/*
_____________________________________________________________________________
Set item named 't' with f
_____________________________________________________________________________
*/
void SetItem (char* t,float f)
{struct VarTableItem *cur = FList;
while ( cur && stricmp(cur->name,t) ) cur = cur -> next;
if ( cur == 0)
AddItem(t,f);
else
cur->val = f;
}
/*
_____________________________________________________________________________
Release memory allocated by vartable and print results of calculations
_____________________________________________________________________________
*/
void FreeTable (void)
{struct VarTableItem *cur = FList ,*x;
puts("Calculations has been finished.");
puts("Results:");
puts("Name Value.");
while ( cur )
{x=cur;
cur = cur -> next;
printf("%-12.12s %g\n",x->name,x->val);
free (x);
}
FList = 0;
}
/*
_____________________________________________________________________________
FLOAT STACK SECTION
_____________________________________________________________________________
*/
/*
_____________________________________________________________________________
The structure represent a item of float stack.
_____________________________________________________________________________
*/
static struct FLOAT_EL
{float val; // value of the item
struct FLOAT_EL *next; // pointer to the next item
} *FStack; // pointer to the top of the stack
/*
______________________________________________________________________________
Initialize the stack of floats
______________________________________________________________________________
*/
void InitFloatStack ()
{FStack = 0;
}
/*
______________________________________________________________________________
Push float 'f' to the stack.
______________________________________________________________________________
*/
void pushFloat (float f)
{struct FLOAT_EL *cur = malloc(sizeof(struct FLOAT_EL));
cur->next = FStack;
cur->val = f;
FStack = cur;
}
/*
______________________________________________________________________________
Pop float from the stack.
______________________________________________________________________________
*/
float popFloat (void)
{if(FStack)
{struct FLOAT_EL *cur;
float r;
r=FStack->val;
cur = FStack->next;
free(FStack);
FStack = cur;
return r;
}
puts("\'popFloat\':The Stack is empty");
exit(666);
return 0;
}
/*
_____________________________________________________________________________
if the stack is not empty free it.
_____________________________________________________________________________
*/
void FreeFloatStack ()
{struct FLOAT_EL *cur = FStack ,*x;
while ( cur )
{x=cur;
cur = cur -> next;
free (x);
}
FStack = 0;
}
ΓòÉΓòÉΓòÉ <hidden> Commands_c ΓòÉΓòÉΓòÉ
/*
ΓòöΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòù
Γòæ Copyright (C) Transcendental Automation, 1993. Γòæ
ΓòƒΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓòó
Γòæ COMMANDS.C Γòæ
ΓòƒΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓòó
Γòæ This module contains the function that initializes semantic actions' tableΓòæ
Γòæ and functions which define this semantic actions.All semantics action Γòæ
Γòæ work in the time of postfix traversal. Γòæ
ΓòÜΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓò¥
*/
#include "sample.h"
#include <stdio.h>
void ASSIGN_func (void*,SAMPLE_PT*,LR_PT*);
void DIV_func (void*,SAMPLE_PT*,LR_PT*);
void MUL_func (void*,SAMPLE_PT*,LR_PT*);
void ADD_func (void*,SAMPLE_PT*,LR_PT*);
void SUB_func (void*,SAMPLE_PT*,LR_PT*);
void NEG_func (void*,SAMPLE_PT*,LR_PT*);
void FLOAT_func (void*,SAMPLE_PT*,LR_PT*);
void IDENTIFIER_func (void*,SAMPLE_PT*,LR_PT*);
/*
_____________________________________________________________________________
Initialize table of semantic actions
_____________________________________________________________________________
*/
void InitCmdTable()
{int i;
for(i=0;i<SAMPLE_n;i++) cmd [i] = 0;
cmd[SAMPLE_ASSIGN_n] = ASSIGN_func;
cmd[SAMPLE_DIV_n] = DIV_func;
cmd[SAMPLE_MUL_n] = MUL_func;
cmd[SAMPLE_ADD_n] = ADD_func;
cmd[SAMPLE_SUB_n] = SUB_func;
cmd[SAMPLE_NEG_n] = NEG_func;
cmd[SAMPLE_FLOAT_n] = FLOAT_func;
cmd[SAMPLE_IDENTIFIER_n] = IDENTIFIER_func;
}
/*
______________________________________________________________________________
The function realize semantics of assign
_____________________________________________________________________________
*/
static void ASSIGN_func (void* sysp, SAMPLE_PT* NPS, LR_PT* pt)
{LR_PT* zt = pt->PL.f->d; // the RHS of rule ASSIGN contain 3 nonterminals
// so the first son always exists.
// 'pt->PL.f->d' means pointer to first son.
if(zt->t && lrx_n(zt) == SAMPLE_IDENTIFIER_n) //test if first son is identifier
{SetItem(zt->t,popFloat()); // the top of stack is value of expression
popFloat(); // the top of stack is value of identifier before
// calculation.
}
}
/*
______________________________________________________________________________
The function realize semantics of division.
_____________________________________________________________________________
*/
static void DIV_func (void* sysp, SAMPLE_PT* NPS, LR_PT* pt)
{float a = popFloat();
if(a==0)
{puts("Divide by zero.");
exit(4);
}
pushFloat(popFloat()/a);
}
/*
______________________________________________________________________________
The function realize semantics of multiplication
_____________________________________________________________________________
*/
static void MUL_func (void* sysp, SAMPLE_PT* NPS, LR_PT* pt)
{pushFloat( popFloat() * popFloat() );
}
/*
______________________________________________________________________________
The function realize semantics of addition
_____________________________________________________________________________
*/
static void ADD_func (void* sysp, SAMPLE_PT* NPS, LR_PT* pt)
{pushFloat( popFloat() + popFloat() );
}
/*
______________________________________________________________________________
The function realize semantics of subtraction
_____________________________________________________________________________
*/
static void SUB_func (void* sysp, SAMPLE_PT* NPS, LR_PT* pt)
{pushFloat( - popFloat() + popFloat() );
}
/*
______________________________________________________________________________
The function realize semantics of negation
_____________________________________________________________________________
*/
static void NEG_func (void* sysp, SAMPLE_PT* NPS, LR_PT* pt)
{pushFloat( - popFloat());
}
/*
______________________________________________________________________________
The function realize semantics of constant
_____________________________________________________________________________
*/
static void FLOAT_func (void* sysp, SAMPLE_PT* NPS, LR_PT* pt)
{pushFloat(atof(pt->t));
}
/*
______________________________________________________________________________
The function realize semantics of identifier
_____________________________________________________________________________
*/
static void IDENTIFIER_func (void* sysp, SAMPLE_PT* NPS, LR_PT* pt)
{pushFloat(LookUp(pt->t));
}
ΓòÉΓòÉΓòÉ <hidden> Sample_mak ΓòÉΓòÉΓòÉ
#ΓòöΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòù
#Γòæ Copyright (C) Transcendental Automation ,1993. Γòæ
#ΓòƒΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓòó
#Γòæ SAMPLE.MAK Γòæ
#ΓòƒΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓöÇΓòó
#Γòæ This makefile create program 'sample.exe' which is an example of Γòæ
#Γòæ usage of LR. Sample.exe is a simple interpreter. The syntax of input Γòæ
#Γòæ language of it is discribed in file sample.gr. Γòæ
#ΓòÜΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓò¥
# You must set true path to include files of LR - package instead C:\LR\INCLUDE
CC = ICC -c -Ss -IC:\LR\INCLUDE
LINK = LINK386 /W /PM:NOVIO
# You must set true path to LRP instead C:\LR\BIN
LRP = C:\LR\BIN\LRP
# You must set true path to libraries of LR - package instead C:\LR\LIB\
SAMPLE.EXE : SAMPLE.OBJ TABLE.OBJ COMMANDS.OBJ
$(LINK) SAMPLE.OBJ+TABLE.OBJ+COMMANDS.OBJ, SAMPLE.EXE, NUL,C:\LR\LIB\LR.LIB;
SAMPLE.OBJ : SAMPLE.C SAMPLE.H
$(CC) SAMPLE.C
TABLE.OBJ : TABLE.C SAMPLE.H
$(CC) SAMPLE.C
COMMANDS.OBJ : COMMANDS.C SAMPLE.H SAMPLE.STR
$(CC) COMMANDS.C
SAMPLE.STR : SAMPLE.GR
&(LRP) SAMPLE.GR
ΓòÉΓòÉΓòÉ <hidden> Makefile ΓòÉΓòÉΓòÉ
#-----------------------------------------------------------------------------
# MAKEFILE - Make file to make grammars
#
# Copyright (C) Transendental Automation, 1993.
#
# Type 'make.exe' or 'nmake.exe' to use it or use another tools that can work
# with make files ( for example IBM WorkFrame/2 ).
# See notes below for understanding of work of this make file.
# We hope there is all that you need for compiling your grammars and parsing
# your text no more no less.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# PART 1 - define grammar and text
#
# Edit this part when choosing another grammar
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Grammar name - if absents, no make at all.
#
# This name will be used as name + '.' + extension of input and
# output files. So,in this case, the GDL file is 'sample.gr'
# compiled grammar will be named as 'sample.lrs' and parse results
# will be named as 'sample.prs', this name also will be used in
# names of structures and constants in 'sample.str' and 'sample.n'
# files
#-----------------------------------------------------------------------------
GR = sample
#-----------------------------------------------------------------------------
# Text name - if commented out by #, then only compile grammar
# You can also set it with any name of file that you want to parse.
# For example :
# TEXT = ASD.YYT
#-----------------------------------------------------------------------------
TEXT = $(GR).txt
#-----------------------------------------------------------------------------
# PART 2 - path to LRP compiler/parser
#
# Edit this part when installing LRP
# Here must be full path without '\' at end where is placed program 'lrp.exe'
# that is used to compile grammar and parse input files .
#-----------------------------------------------------------------------------
LRP_DIR = C:\LR\BIN
#-----------------------------------------------------------------------------
# PART 3 - making grammar and/or parse text
#
# Do not edit this part
#-----------------------------------------------------------------------------
!CMDSWITCHES +S
!IFDEF LRP_DIR
┬╖SUFFIXES: .gr .lrs .prs
{.}.gr.lrs:
$(LRP_DIR)\LRP.EXE $*.gr
!IFDEF GR
!IFDEF TEXT
$(GR).prs: $(GR).lrs $(TEXT)
$(LRP_DIR)\LRP.EXE $**
!ENDIF
$(GR).lrs: $(GR).gr
!ENDIF
!ELSE
ERR:
echo Fatal error U1050: failed to find path to LRP compiler/parser
!ENDIF
ΓòÉΓòÉΓòÉ <hidden> ΓòÉΓòÉΓòÉ
Here you must replace <<NAME>> with the name of your grammar. E.g. where we had
<<NAME>>.LRS we will have SAMPLE.LRS if we compiled Sample grammar.