Derived from: none
Declared in: Parser.h
The Parser class is meant to provide facilities in order to perform the syntaxic analysis. Some debugging features have been added, in particular, the possibility to output messages on the screen, and to auto-indent them.
This library only supports one-lookahead symbol top-down parsing methods, which are actually the most broadly used. So, this is no severe limitation.
A Parser object is, in theory, dedicated to the parsing of one file type, and no other one.
Hence, it has first to check whether the type of the file is the one it can handle. This is performed
by CheckType().
Once the type of the file has been checked, the parsing itself of the file is next.
The method associated with it is Parse().
Given that these 2 methods are particular to a type of file, they are defined as pure virtual methods, making of Parser an abstract class. In other words, this class can't be instanciated, the user will need to derive a MyParser class from it and define both methods CheckType() and Parse().
The LAP library actually provides 2 derived classes, namely:
Parser(bool Verbose)
Creates a Parser object with the verbose mode set to Verbose
~Parser(void)
Nothing much happens in here.
virtual bool CheckType() = 0
This method is called one the input file is set. It allows the parser to check for the type validity of the file. If the file type is recognized, true is returned. Otherwise, false is returned.
This method has to be written by the programmer. At the beginning of the routine, the input is ready to be used with whatever method is available through inheritance, or methods declared in the current class. true or false is to be returned, but the input doesn't have to be reset by the programmer, it will be automatically done when CheckType is exited.
This method is not meant to be called by the programmer. It will be used by the ParserText::SetInput() or ParserBin::SetInput().
By the way, this method is called in silent mode, even if the Parser object was built with the verbose mode on.
virtual bool Parse() = 0
This method performs the parsing of the file. It is declared as pure virtual, because it has to be defined by more specific classes. It has to be called after the input was set by a call to either ParserText::SetInput() or ParserBin::SetInput(). At the beginning of the routine, the lexer is positionned at the beginning of the file, and is ready to respond to read requests.
void InitIndent()
Sets up some indentation related-stuff. The user don't have to call this method, it is done automatically.
BIT00, BIT01, BIT02, ..., BIT31
These constants allow you to easily set or test bits in an integer. This is often used in
files, when you get a set of flags coded in an integer.
Well, that's not a big deal...
ASSERT(Expression)
This is a handy macro used to make sure the expression Expression is true. It it is not, false is returned, otherwise, the execution proceeds to the next instruction. Indeed, when parsing a file, you never know what can happen, and you never should make the assumption that any of your parsing methods can not fail. It is safer to... trust no one. Excepted the library and the compiler *8o)
I have to say my mind:
Computer science is all about paranoid and lazy people. At least, that's the way I'm used to code...
As an illustration:
ASSERT(The_actual_file_length = The_theoretical_file_length); // Here, I'm sure that "The_actual_file_length = The_theoretical_file_length" ... ASSERT(Parse_this_lovely_piece_of_data(dont_turn_left, dont_throw_up, ...); // Here, I'm sure that I've correctly parsed "this_lovely_piece_of_data" ...By the way, it is recommended to use this facility, because this is the way indentation is transparently performed.
A last word about the indentation. The depth of indentation is at most of MAX_PARSE_DEPTH/2, which is worse something like 32 (up to 32 recure calls are supported). Beyond this limit, you'll have some strange characters output instead of spaces, but no danger to crash. In a word, it just becomes ugly.
ASSERT2(Expression)
This is a macro which has the same role as ASSERT() but requires a second argument (an immediate string), to display some more information to trace in and out the functions that are called. For instance:
ASSERT2(ParseThisPlease(Here, AndHere), "ThisPlease");will generate (if in verbose mode):
ThisPlease in // Any subsequent message triggered by ParseThisPlease()... ThisPlease outor
ThisPlease in // Any subsequent message triggered by ParseThisPlease()... ThisPlease failedPretty simple, isn't it?
_PRINT0(s) _PRINT1(s, a) _PRINT2(s, a, b) _PRINT3(s, a, b, c) _PRINT4(s, a, b, c, d) _PRINT5(s, a, b, c, d, e) _PRINT6(s, a, b, c, d, e, f) _PRINT7(s, a, b, c, d, e, f, g) _PRINT8(s, a, b, c, d, e, f, g, h) _PRINT9(s, a, b, c, d, e, f, g, h, i) _PRINTA(s, a, b, c, d, e, f, g, h, i, j)
These are macros to output information on screen using the underlying printf function. The _PRINTi macro prints out i arguments, only if the parser was constructed in a verbose mode. As an illustration:
_PRINT0("Diantre, que c'la est pratique!\n"); _PRINT3("Hop %s, Gruik %f, Zorglub %d\n", TheString, TheInt, TheFloat);Note that these messages are not indented, see ParserText::PRINT and ParserBin::PRINT for indented messages.