Class AParser

DescriptionHierarchyFieldsMethodsProperties

Unit

Declaration

type AParser = class(ANode)

Description

This class represents a generic parser. You will likely not construct an instance of this class directly since it only provides the support mechanisms needed for a parser and lacks the code to do the actual parsing.

When constructing a parser, you are expected to provide:

  • a log for message output

  • an input stream, unless the parser creates its own

The parser will create and dispose of its own scanner while parsing.

Parsers descend from ANode because they are designed to be chained together: the top-level (program) parser will construct a block-level parser, which will itself construct a block-level or statement-level parser, which will construct an expression parser – and so on down the line. The advantages of this approach include readability – no long chain of case statements – and flexibility: new additions to the language usually require only the addition of a new type of statement- or expression-level parser.

Each time a higher-level parser constructs a lower-level parser, the new parser is linked to the Child property. The most recent lower-level parser created by a given parser can be obtained by calling AParser.CurrentElement.

Note that, although instances of AParser descend from ANode, they do not implement any of the streaming behavior for obvious reasons.

Hierarchy

  • AParser

Overview

Fields

Protected MyScanner: AScanner;
Protected MyLog: ALog;
Protected MySource: AStream;
Protected MyTokens: ATokenList;

Methods

Public constructor forSource(const ThisSource: AStream; const ThisLog: ALog); virtual; overload;
Public constructor forSource(const ThisParent: AParser); virtual; overload;
Public function init: boolean; override;
Public destructor destroy; override;
Public function readyToParse: boolean; virtual;
Public function parse: int64; virtual; abstract;
Public function parseUntilToken(const thisOpcode: TOpcode): int64; virtual;
Public function parseUntil(const ThisRule: ASyntaxRule): int64; overload; virtual;
Public function CurrentToken: AToken; virtual;
Public function PreviousToken: AToken; virtual;
Public function PeekToken: AToken; virtual;
Public function NextToken(const silenceCurrentToken: boolean = false): AToken; virtual;
Public function NextTokenIf(const condition: boolean; const silenceCurrentToken: boolean = false): AToken; virtual;
Public procedure rewind; virtual;
Public procedure resyncToToken(const opcode: TOpcode); virtual;
Public procedure resyncTo(const ThisRule: ASyntaxRule); virtual;
Public procedure skipToToken(const opcode: TOpcode; const silenceInterveningTokens: boolean = true); virtual;
Public procedure skipTo(const ThisRule: ASyntaxRule; const silenceInterveningTokens: boolean = true); virtual;
Public procedure skipOverToken(const opcode: TOpcode; const silenceInterveningTokens: boolean = true); virtual;
Public procedure skipOver(const ThisRule: ASyntaxRule; const silenceInterveningTokens: boolean = true); virtual;
Public procedure note(const fmt: string; const params: array of const); virtual;
Public procedure hint(const fmt: string; const params: array of const); virtual;
Public procedure warn(const fmt: string; const params: array of const); virtual;
Public procedure syntaxError(const fmt: string; const params: array of const); virtual;
Public function fatalError(const fmt: string; const params: array of const): AParserFatalError; virtual;
Public function Scanner: AScanner; virtual;
Public function Log: ALog; virtual;
Public function Source: AStream; virtual;
Public function Tokens: ATokenList; virtual;
Public function CurrentElement: AParser; virtual;
Public function PreviousElement: AParser; virtual;

Description

Fields

Protected MyScanner: AScanner;

Refers to the scanner used to tokenize the source

Protected MyLog: ALog;

Refers to the log used for parser output

Protected MySource: AStream;

Refers to the source stream being parsed

Protected MyTokens: ATokenList;

Refers to the list of tokens parsed from the source

Methods

Public constructor forSource(const ThisSource: AStream; const ThisLog: ALog); virtual; overload;

Construct a new parser that will parse the specified source and output status and error messages to the specified log.

Both ThisSource and ThisLog must be valid instances of their respective classes in order for AParser.parse to succeed.

Public constructor forSource(const ThisParent: AParser); virtual; overload;

Construct a new parser that will inherit the properties of its parent parser.

The new parser will inherit the values of ThisParent's Scanner, Source and Log.

Public function init: boolean; override;

Initializer

Public destructor destroy; override;

Destroy the parser instance.

If Self.Parent is Nil, then that indicates this is a top-level parser, and so this method will free the token list and scanner associated with the parser, if any, before calling the inherited routine.

Otherwise, this method first pops its current token and pushes it back into the parent's list, so that the parent has the token which ended the program element. Then it nils the related properties so they are not freed (since the parent will still be using them) before calling the inherited routine.

Public function readyToParse: boolean; virtual;

Initialize the parser prior to parsing the source.

The purpose of this method is to allow descendant classes to override the various properties of the parser at parsing time, providing greater flexibility to the parser. For instance, sometimes it is desirable to inherit a token list from a parent parser, rather than constructing your own. This method should be called before AParser.parse, AParser.parseUntilToken, or AParser.parseUntil are called for the first time, and those methods should be called only if this method returns True.

The base implementation of this method checks to ensure Self.Source, Self.Log, and Self.Tokens are all valid references (not Nil). If Self.Tokens is Nil, indicating that a descendant has not already assigned the list of tokens, then the routine will construct an instance of ATokenList for the parser. Descendant classes should call this routine before performing their own checks and parsing the specified source.

Returns

True if the parser is ready to parse; False if not.

Public function parse: int64; virtual; abstract;

Parse the source.

Descendant classes should override this method to parse the element represented by the parser (source, file, block, statement, expression, etc.).

Before this method is called, the caller should check the return value of AParser.readyToParse; if the value is False, then the parser is not ready to parse and this method should not be called.

Returns

A negative value if an error has occurred before any parsing was done. This will most likely occur if Self.readyToParse returns False. A value greater than or equal to zero (0) indicates the number of non-fatal errors (such as syntax errors) that occurred while parsing. A value of zero (0) indicates all is well.

Public function parseUntilToken(const thisOpcode: TOpcode): int64; virtual;

Parse statements until the specified opcode is reached.

This method may be called on to parse tokens or statements from the source until a specific keyword or delimiter is reached. It will most commonly be used to process function bodies, which are usually terminated by a keyword or delimiter of some kind.

Before this method is called, the caller should check the return value of AParser.readyToParse; if the value is False, then the parser is not ready to parse and this method should not be called.

Internally, this method simply loops by calling Self.parse and then checking the current token when that method returns. If the end of the stream is reached (and it is not the opcode desired), then this method will flag a fatal error.

When this method exits, Self.CurrentToken should refer to thisOpcode or to the end of the stream.

Returns

The total number of syntax errors that have occurred while parsing. This is the accumulated total from successive calls to Self.parse.

Exceptions raised
AParserFatalError
if the end of the source stream is encountered before thisOpcode is found – unless thisOpcode is TOKCAT_EOS.
Public function parseUntil(const ThisRule: ASyntaxRule): int64; overload; virtual;

Parse until a token from the specified rule is encountered.

This method may be called to parse statements or tokens from the source until one of a number of opcodes is reached. It will most commonly be used to process loops, which are normally terminated by a keyword, delimiter, or expression.

Before this method is called, the caller should check the return value of AParser.readyToParse; if the value is False, then the parser is not ready to parse and this method should not be called.

Internally, this method simply loops by calling Self.parse and then checking the current token when that method returns. If the end of the stream is reached (and it is not part of the specified rule), then this method will flag a fatal error.

When this method exits, Self.CurrentToken should refer to a token from ThisRule or the end of the stream.

Returns

The total number of syntax errors that have occurred while parsing. This is the accumulated total from successive calls to Self.parse.

Exceptions raised
AParserFatalError
if the end of the source stream is encountered before a token from ThisRule is found – unless TOKCAT_EOS is part of ThisRule.
Public function CurrentToken: AToken; virtual;

Retrieve a reference to the most recent token parsed from the source.

This method returns a reference to the last token in the token list maintained by the parser. This reference should NOT be freed by the caller; that will be done by the token list to which the token belongs.

If the caller wishes to pop a token from the token list, it should do so by calling ATokenList.Pop on AParser.Tokens. It is then responsible for freeing the token itself.

If Self.Tokens is Nil, this routine will construct a new instance of ATokenList to hold the tokens parsed by the parser. Additionally, after creating the new list, the routine checks to see if Self.Parent is not Nil; if not, it means that that this parser was been created to parse a sub-element (such as a statement block or statement), and this method will push a copy of the previous token from its parent's list onto the new list, as well as the ACTUAL current token from the parent.

Public function PreviousToken: AToken; virtual;

Retrieve a reference to the second-most-recent token parsed from the source.

This method returns a reference to the second-to-last token in the token list maintained by the parser. This reference should NOT be freed by the caller; that will be done by the token list to which the token belongs.

Public function PeekToken: AToken; virtual;

Peek at the next token without advancing the current position in the source.

This method calls AScanner.Peek on the instance of AScanner maintained by the parser and returns the token reference to the caller. The caller is responsible for freeing that reference when it is no longer required.

Public function NextToken(const silenceCurrentToken: boolean = false): AToken; virtual;

Retrieve the next token from the source.

This method calls AScanner.next on the instance of AScanner maintained by the paser and pushes the resulting token reference onto its list of tokens. That reference is then returned to the caller. The caller should NOT free it directly. Instead, they should pop the token from AParser.Tokens and then free the reference.

If silenceCurrentToken is True, then this method calls AToken.setSilenced on the current token before retrieving the next token from the source. Although AParser does not make use of this behavior, descendant classes may prevent silenced tokens from being output to their intermediate code streams.

Public function NextTokenIf(const condition: boolean; const silenceCurrentToken: boolean = false): AToken; virtual;

Retrieve the next token from the source, but only if the specified condition is met.

This method is defined for convenience; it allows the programmer to specify a boolean expression, the outcome of which will determine whether another token is read from the source or not. If condition evaluates to True, then this method calls AParser.NextToken on Self; otherwise it does nothing and returns Nil.

If silenceCurrentToken is True, then this method calls AToken.setSilenced on the current token before retrieving the next token from the source. Although AParser does not make use of this behavior, descendant classes may prevent silenced tokens from being output to their intermediate code streams.

Public procedure rewind; virtual;

Return the current token to the source.

This method pops the last token from its token list and returns it to the source stream, so that it will be read again. If AParser.CurrentToken is Nil, then this routine does nothing.

Public procedure resyncToToken(const opcode: TOpcode); virtual;

Resynchronize the parser to the specified opcode.

This method is designed to allow the parser to recover after a syntax error. If CurrentToken.opcode does not match opcode, it logs a syntax error to indicate that the current token is not expected, then calls AParser.skipToToken to skip tokens in the source.

Public procedure resyncTo(const ThisRule: ASyntaxRule); virtual;

Resynchronize the parser to one of the tokens from the specified Rule.

This method is designed to allow the parser to recover after a syntax error. If CurrentToken.opcode is not found in ThisRule, it logs a syntax error to indicate that the current token is not expected, then calls AParser.skipTo to skip tokens in the source.

If ThisRule is Nil, then this routine does nothing.

Public procedure skipToToken(const opcode: TOpcode; const silenceInterveningTokens: boolean = true); virtual;

Skip tokens in the source until one with the specified opcode is encountered.

If silenceInterveningTokens is True, then all tokens encountered before opcode will have their silenced property set by a call to AToken.setSilenced. Although AParser does not make use of this behavior, descendant classes may prevent silenced tokens from being written to their intermediate code streams.

Exceptions raised
AParserFatalError
if opcode is not TOKCAT_EOS and the end of the source was reached before opcode was found.
Public procedure skipTo(const ThisRule: ASyntaxRule; const silenceInterveningTokens: boolean = true); virtual;

Skip tokens until one of the tokens in ThisRule is encountered.

If ThisRule is Nil, then this method does nothing.

If silenceInterveningTokens is True, then all tokens encountered before opcode will have their silenced property set by a call to AToken.setSilenced. Although AParser does not make use of this behavior, descendant classes may prevent silenced tokens from being written to their intermediate code streams.

Exceptions raised
AParserFatalError
if ThisRule does not contain TOKCAT_EOS and the end of the source is encountered before an opcode that is part of ThisRule.
Public procedure skipOverToken(const opcode: TOpcode; const silenceInterveningTokens: boolean = true); virtual;

Skip over tokens in the source until one is encountered that does not match the specified opcode, or until the end of the stream is reached.

If silenceInterveningTokens is True, then all tokens encountered until one that is not opcode will have their silenced property set by a call to AToken.setSilenced. Although AParser does not make use of this behavior, descendant classes may prevent silenced tokens from being written to their intermediate code streams.

Public procedure skipOver(const ThisRule: ASyntaxRule; const silenceInterveningTokens: boolean = true); virtual;

Skip over tokens in the source until one is encountered that is not part of ThisRule, or until the end of the stream is reached.

If ThisRule is Nil, then this method does nothing.

If silenceInterveningTokens is True, then all tokens encountered until one that is not opcode will have their silenced property set by a call to AToken.setSilenced. Although AParser does not make use of this behavior, descendant classes may prevent silenced tokens from being written to their intermediate code streams.

Public procedure note(const fmt: string; const params: array of const); virtual;

Output a note to the log.

This method is defined for convenience; it automates the construction of an instance of AParserNote, then writes that instance to AParser.Log before freeing it.

fmt specifies the format of the message that will be written to the log. params specifies any values that should be incorporated into that message when it is logged.

Public procedure hint(const fmt: string; const params: array of const); virtual;

Output a hint to the log.

This method is defined for convenience; it automates the construction of an instance of AParserHint, then writes that instance to AParser.Log before freeing it.

fmt specifies the format of the message that will be written to the log. params specifies any values that should be incorporated into that message when it is logged.

Public procedure warn(const fmt: string; const params: array of const); virtual;

Output a warning to the log.

This method is defined for convenience; it automates the construction of an instance of AParserWarning, then writes that instance to AParser.Log before freeing it.

fmt specifies the format of the message that will be written to the log. params specifies any values that should be incorporated into that message when it is logged.

Public procedure syntaxError(const fmt: string; const params: array of const); virtual;

Output a syntax error to the log.

This method is defined for convenience; it automates the construction of an instance of AParserSyntaxError, then writes that instance to AParser.Log before freeing it.

fmt specifies the format of the message that will be written to the log. params specifies any values that should be incorporated into that message when it is logged.

Public function fatalError(const fmt: string; const params: array of const): AParserFatalError; virtual;

Output a fatal error to the log.

This method is defined for convenience; it automates the construction of an instance of AParserFatalError, then writes that instance to AParser.Log. The instance is returned to the caller, which allows the caller to both raise the fatal error and log it in one statement:

        // We should not be at the end of the source here
        if MySource.hasEnded then
          // Log and raise an exception that will halt parsing
          raise Self.fatalError('unexpected end of source', []);
      

If the caller does not intend to raise an exception with the returned instance, then it is responsible for freeing the instance when it is no longer required.

fmt specifies the format of the message that will be written to the log. params specifies any values that should be incorporated into that message when it is logged.

Public function Scanner: AScanner; virtual;

Retrieve a reference to the scanner being used by the parser.

This value may be Nil until AParser.parse is called on the parser. In any event, the reference is managed by the parser and should NOT be freed by the caller.

Public function Log: ALog; virtual;

Retrieve a reference to the log used by the parser for status and error output.

This reference should NOT be freed by the caller.

Public function Source: AStream; virtual;

Retrieve a reference to the source stream being parsed by the parser.

This reference should NOT be freed by the caller.

Public function Tokens: ATokenList; virtual;

Retrieve a reference to the list of tokens being managed by the parser.

This reference should NOT be freed by the caller; that will be done by the parser when it is, itself, freed.

Public function CurrentElement: AParser; virtual;

Retrieve a reference to the most recent program element (a statement, statement block, expression) created by this parser for use in parsing the source. Calling this routine is functionally equivalent to casting the return value from AParser.Child to an instance of AParser.

This function may return Nil if the parser implementation does not make use of sub-parsers to process statements, statement blocks, or expressions.

Public function PreviousElement: AParser; virtual;

Retrieve a reference to the second most recent program element (a statement, statement block, expression) created by this parser for use in parsing the source. Calling this routine is functionally equivalent to casting the return value from AParser.Previous, when called on AParser.CurrentElement, to an instance of AParser.

This function may return Nil if the parser implementation does not make use of sub-parsers to process statement, statement blocks, or expressions – or if the parser does not cache such program elements, but instead disposes of them as soon as they have done their work.


Generated by PasDoc 0.13.0 on 2015-06-25 11:12:03