$Id: ProgrammingGuide_eng.tex,v 1.6 2001/05/21 10:10:24 vaa Exp $
YaYacc - abridgment for Yet Another Yacc.
The program was created as a syntactical analyzer, which is compatible with original yacc| citeyacc ([1] - good tutorial) on algorithm analysis and perceived language LALR(1), and it generates the code by C++ language but not by C language as original yacc.
YYProperties.h ), in which class of generator's properties syntactical analysis must be defined. The properties are:
YYTag
The following public fields must be defined in the class:
struct MyGrammarTag
{
typedef int YYType;
const initStackSize = 100;
const maxStackSize = 1000;
};
The following conditions must be fulfil for correct work of generated syntactical analyzer:
YYType is the class with constructor by default, which can copy and bind itself (i.e. Copyable, Assignable and DefaultConstructable)
Lexer<MyGrammarTag>, and contain the following methods:
int readToken(); - must read next lexeme and return its code.
typename MyGrammarTag::YYType yylval() cosnt - must return the last terminal symbol, corresponding this lexeme.
class MyLexer: public GradSoft::YYLexer<MyGrammarTag>
{
private:
istream& in_();
public:
Lexer(istream& in)
:in_(in) {}
~Lexer() {}
int readToken();
MyGrammarTag::YYTag yylval() const;
};
-n MyGrammarTag (in detail look to a part "options")
template<>
class YYParser<MyGrammarTag>
{
....
public:
YYParser(YYLexer<MyGrammarTag>& lexer);
~YYParser();
int parse();
typename MyGrammarTag::YYType getResult() const;
void setDebugLevel(int debugLevel);
};
This class is defined in generated title file <y.tab.h>
Parser<MyGrammarTag>
parse.
Thus, general situation can be expresses the following scheme:
Let's go to detail examination of process working yayacc. So, at beginning - parameters of grammar.
subsectionYYType
Terminal grammar type. It has semantics the same as YYTYPE in standard yacc has: i.e. MyGrammarTag::YYType is used in that place, where traditionally YYTYPE situates; YYType must obtain the following properties:
If in your comprehension the terminal symbol is the more difficult structure, for which using deep copy is not effective (for example, knot of the syntactical tree), then better to use pointers on this structure in capacity of YYType. In this case, don't forget to put the deleting elements cycle in your code renewal from mistakes.
subsubsection%union statement
If you use %union statement in file Grammar.y, then corresponding definition of type is generated automatically as concatenation of lines MyGrammarTag and YYType.
Thus, for example, if you run yyac with option -n Calculator, and there is the definition of union in your Calculator.y file.
%union {
int i;
char ch;
};
then in work result the following lines will appear in y.tab.h and in y.h.cpp :
typedef union {
int i;
char ch;
} CalculatorYYTag;
In Calculator.h you may either duplicate this definition or include y.tab.h and write something like that:
struct Calculator
{
typedef CalculatorYYType YYType;
...
};
subsectionYYInfoType
This data type, which is used for information passing between syntactical analyzer and program environment from enters analyzer.
More detail: At the time of creation the reference is passed into the class Parser on the object as type YYInfoType. You may use it for passing additional information from/into syntactical analyzer.
subsectionmaxStackSize
It must be integer constant, which define maximal size of stack of syntactical analyzer. It may be considered as top limit for maximal possible quantity of no reducible symbols. The value on default in yacc - 10000.
By the way, it is question: for what is it necessary to limit from the top the size of stack - for when use the syntactical analyzer in network services it isn't any possibility for attack as type DOS.
subsectioninitStackSize
This must be the integer constant, which define the initial size of the analyzer stack. It may be considered the top limit for quantity of no reducible symbols in current program. For grammar calculator it will be near five. Constant value in yacc on preterition - 100.
subsectionThe example: describing of the grammar tag
struct MyGrammarTag
{
typedef int YYType;
typedef bool YYInfoType;
static const int maxTableSize;
static const int initTableSize;
}
A lexical analyzer is passed 1 to the object YYParser when its creation.
Template for lexical analyzer is described in interface file GradSoft/YaYacc.h and has a appearance:
template<class YYTag>
class YYLexer
{
public:
int readToken();
typename YYTag::YYType getLastValue();
YYLexer() {};
virtual ~YYLexer() {};
private:
YYLexer(const YYLexer&);
YYLexer& operator=(const YYLexer&);
};
You must assign a specialization this template and /or/ inherit your lexical analyzer from it.
Two following functions are important:
int readToken() - read next lexeme, keep correspond value in inside status variable. (if it exists).
getLastValue() - return the value of last read lexeme.
The example of lexical analyzer is situated in files CalculatorLexer.h
(corresponding CalculatorLexer.cpp)
in subfolder demo/calculator of distribute YaYacc
yyinfo.
It has type typename MyGrammarTag::YYInfoType.
You pass the reference on this variable in constructor of syntactical analyzer, in rules you can appropriate yyinfo meanings; after seance you can take meaning yyinfo with the help of method YYParser<MyGrammarTag>::getYYInfo();
yyerror. Its definition must be situated in file MyGrammar.y and look as following:
template<>
void YYParse<MayGrammarTag>::yyerror(const char* msg)
{
.. you cleanup here
}
In the case of complicated structures YYType you will necessary do cleaning stack:
In this case have in view that there are elements from 0 to (yyssp-yyss) in your examination.
template<>
void YYParse<MayGrammarTag>::yyerror(const char* msg)
{
for(inti i=0; i<yyn; ++i) {
delete yyvs[i];
}
}
YYParse<YYTag>::getErrorMessage. Note, that this method returns NULL,
if no errors was occur.
YYParser<MyGrammarTag>::setDebugLevel. For enabling debug printing you must call this method with parameter, which is bigger then 0.
It is situated in directory demo/calculator/ in yayacc distributive.
-n <MyGrammarTag> - this is added by us option, which defines the value of the YYTag symbol.
-b <file-prefix> - the traditional option, it changes value of prefix of generated files.
-d - the traditional option, it calls the file generation.
y.tab.h. In our variant this option is included on default.
-l - the traditional option, to disable the generation of #line preprocessor directives.
-o <file-name> - the traditional option, to generate the file file-name in place of y.tab.cpp.
-p <symbol-prefix> - the traditional option, to use symbol-prefix in place of yy. We don't guarantee the compatibility of yayacc with this option.
-r - the traditional option, to generate separately the file of tables y.tab.cpp and file of code y.code.cpp
-t - the traditional option - to include generation of debug printing in generated code.
-v - the traditional option - to generate the readable description of grammar parser in file y.output.
Simple transport the contents of subcatalogue interfaces in some subcatalogue of your project and set it as one more source of included files in options of your C++ compiler.
If your project installs included files, which use yayacc interfaces, then during installation create in
<prefix>/include 2 subdirectory GradSoft and install there the file YaYacc.h
<prefix>/include2