The LAP library: ParserText

Derived from: Parser

Declared in: ParserText.h


Overview

The ParserText object is meant to parse... text files. This object really doesn't do much. It mainly consists in a public interface to a LexerBin object. Still, it is pretty handy.


Constructor and D estructor


ParserText()

 
      ParserText(bool Verbose) 

Creates a ParserText object with the verbose mode set to Verbose Note that the lexer object is not allocated. Indeed, ParserText is an abstract class, because its ParserText::Parse() method is declared as pure virtual. Hence, you have to derive a MyParserText class and declare and define a MyParserText::Parse() method to have a usable binary parser.


~ParserText()

 
      ~ParserText(void) 

Nothing much happens in here.


Member Functions


SearchSymbol()

 
      Symbol* SearchSymbol(char* Name)

Calls and returns the result of Lexer::SearchSymbol()

This method is not declared in the Parser class, because no Lexer object is defined.


PrintSymbol()

 
      void PrintSymbol(Symbol* S)

Calls Lexer::PrintSymbol()

This method is not declared in the Parser class, because no Lexer object is defined.


SearchLexeme()

 
      Lexeme* SearchLexeme(char* Name)

Calls and returns the result of Lexer::SearchLexeme()

This method doesn't exist in ParserBin object because there are no lexemes in a binary file. Well, that's an assumption which often holds, given that they are replaced by "chunk identifiers" or similar integer-based codes.


DetachLexeme()

 
      char* DetachLexeme(char* Lexeme)

Calls and returns the output of Lexer::DetachLexeme()

This method is not declared in the Parser class, because no Lexer object is defined.


DeleteLexeme()

This method is not declared in the Parser class, because no Lexer object is defined.

 
      void DeleteLexeme(char* Lexeme)

Calls Lexer::DeleteLexeme()

This method is not declared in the Parser class, because no Lexer object is defined.


LexInt()

 
      bool LexInt(int32&  Out)

Parse an integer. The method fails (returns false) if the current token is not an integer. Otherwise, true is returned, and the value is written in the integer referenced in parameter.

In case of failure, the output value is in an undetermined state, and should not be used.


LexFloat()

 
      bool LexFloat(float&  Out)

Parse a float. The method fails (returns false) if the current token is not a float. Otherwise, true is returned, and the value is written in the float referenced in parameter.

In case of failure, the output value is in an undetermined state, and should not be used.

see also ParseFloat()


ParseFloat()

 
      bool ParseFloat(float&  Out)

Parse a float value. If an integer is found instead, it is converted into a float. The method fails (returns false) if the current token is neither a float, nor an integer. Otherwise, true is returned, and the value is written in the float referenced in parameter.

In case of failure, the output value is in an undetermined state, and should not be used.


ParseString()

 
      bool ParseString(char*&  Out)

Parse a string. The output value needn't be allocated, it is allocated by the lexer if necessary.

In case of failure, the output value is in an undetermined state, and should not be used.


SkipLine()

 
      bool SkipLine(void)

Skips characters to the next line.


ParseWord()

 
      bool ParseWord(char*&  Out)

Parse a word (a string which is terminated by a space, regardless of the in-between characters). The output value needn't be allocated, it is allocated by the lexer if necessary.

Also see Lexer::LexWord().


Terminate()

 
      virtual void Terminate()

Calls Lexer::Terminate()

This method is not declared in the Parser class, because no Lexer object is defined.


SetInput()

 
      virtual bool SetInput(entry_ref& Ref)

This method sets the input of the lexer. It defines the file to be used, but contrary to ParserBin::SetInput(), there is no need for file endianness or so.

Then, the Parser::CheckType() is called to check that the type of the file is the one the lexer can handle. The verbose mode of the parser is ignored, every message output with the _PRINT or PRINT functions won't be displayed.

The verbose mode is then set back to its original settings, and the lexer reset to point back to the beginning of the file. Then the indentation stuff is initialized so that a simple call to Parse() is needed.

This method is not declared in the Parser class, because no Lexer object is defined.


EndOfFile()

 
      bool EndOfFile()

Calls and returns the output of Lexer::Eof()

This method is not declared in the Parser class, because no Lexer object is defined.


NextToken()

 
      bool NextToken()
This method is called from any of the parsing routines defined in the ParserText class. It provides the next token found in the input stream, and is stored in the attribute ParserText::ParserToken

The fact that there is no "tokens stack" (that is, the attribute ParserText::ParserToken is overwritten anytime NextToken() is called, explains why this is a "one lookahead" symbol parsing library.

Implementing a multi-lookahead symbol library means implementing a stack and a push and pop mechanism, which can be avoided by rewriting the grammar. In other words, it's not a good solution.

This method is rarely called directly by the programmer, but rather by calling the methods Match and Peek.


Match()

 
      bool Match(uint32 Token)
This method is called to assert the fact that the current token is the one given in parameter. It fails and returns false if it is not, true otherwise. The calling method should fail if this method does. This basic mechanism is implemented through the use of the macro MATCH. and its use is recommended.


Peek()

 
      bool Peek(uint32 Token)
This method is called to check whether the current token is the one given in parameter. It returns false if it is not, true otherwise. Contrary to the Match() method, the calling method shouldn't fail if this one does.

This method is used to test several possibilities. For instance:

  if (Peek(LX_TYPE_STRING))
  {
    MATCH(LX_TYPE_STRING);

    if (Peek(LX_TOKEN_EQUAL_SIGN))
    {
      MATCH(LX_TOKEN_EQUAL_SIGN);
      if (Peek(LX_TYPE_INTEGER))
      {
        MATCH(LX_TYPE_INTEGER);
		MATCH(LX_TOKEN_SEMI_COLON);  // [string] '=' [integer] ';'
      }
      else if (Peek(LX_TYPE_FLOAT))
      {
        MATCH(LX_TYPE_FLOAT);
		MATCH(LX_TOKEN_SEMI_COLON);  // [string] '=' [float] ';'
      }
      elseif (Peek(LX_TYPE_STRING))
      {
        MATCH(LX_TYPE_STRING);
		MATCH(LX_TOKEN_SEMI_COLON);  // [string] '=' [string] ';'
      }
    }
  }
  else if (Peek(LX_TOKEN_WHATEVER))
  {
    ...
  }
This example is somewhat dirty (I should haave broken the code into several methods), and dumb (show me a language where only this kind of assignement are allowed (Yes assembly language! Shut up!)), but the idea is here.


Macro Definitions

This method is not declared in the Parser class, because no Lexer object is defined.


PRINT(...)

 
      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)

These are macros to output information on screen using the underlying printf function. The PRINTi macro prints out i arguments, only if the ParserText was constructed in a verbose mode. These messages ARE indented, contrary to the macros Parser::_PRINT, and also have the current line number associated with it.


MATCH(...)

 
      MATCH(Token)

This very handy macro tests if the current Token is the one given in parameter. If it is not, the calling method is returned with false. Otherwise, the execution proceeds normally.
It is actually a shortcut for

    ASSERT(Match(Token))


The LAP library, V0.7, November 3rd 1997, First public release