cparse  1.1.0
A small hand-written recursive-descent parser core for C++
fedem::parser::Parser Class Referenceabstract

Abstract driver for a hand-written recursive-descent grammar. More...

#include <Parser.hh>

Public Types

enum class  TermRequirementDeclaration { DISALLOWED , OPTIONAL , MANDATORY }
 Whether a grammar rule requires, permits, or forbids a terminator. Passed to grammar-specific term-matching helpers. More...
 

Public Member Functions

 Parser ()
 Default-construct. No file is open until parse() is called. More...
 
virtual ~Parser ()
 Destructor. More...
 
bool parse (std::string filename)
 Parse filename: open it, run start(), and classify the ending. More...
 
bool openStream (std::string filename)
 Open filename and set up the cursor, but do not run start() — for a grammar driven from outside one unit at a time instead of "parse everything, then read the result" (the canonical example: a CSV-style reader whose public interface is nextRow(), called until it returns nothing). More...
 
virtual std::string getGrammarName () const noexcept=0
 The grammar's name, for diagnostics. Implemented by the subclass. More...
 
std::vector< ParseError > const & errors () const noexcept
 The collected diagnostics, in the order they were recorded. Valid after parse() returns; check when it returns false. More...
 
bool hasErrors () const noexcept
 Whether any diagnostic has been collected. More...
 
void clearErrors () noexcept
 Discard all collected diagnostics. Called by parse() on entry. More...
 

Protected Member Functions

virtual bool start ()=0
 The grammar's entry rule. Implemented by the subclass; called by parse(). More...
 
virtual bool skipWhiteSpaces ()
 Consume a run of whitespace at the cursor. More...
 
virtual bool skipComments ()
 Consume a comment at the cursor. The base returns false (no comment syntax); a grammar overrides it. More...
 
bool skipCommentsBlock ()
 Repeatedly skipWhiteSpaces() and skipComments() until neither consumes anything. More...
 
bool extractToken (std::string const &token)
 Match token literally at the cursor. On a partial match the cursor is restored to where it started. More...
 
bool extractCharacter (std::string::value_type const token)
 Match a single character at the cursor. More...
 
void writeTraceMessage ()
 Write a short trace (location plus the next few lines of input) to std::clog. A debugging aid. More...
 
CursorgetCursor ()
 The active cursor. More...
 
Cursor const & getCursor () const
 The active cursor (const overload). More...
 
void pushCursor (std::string const &sourceName, std::shared_ptr< Cursor::stream_type > stream)
 Push a new input onto the cursor stack (an include). The current cursor is saved and restored when the nested input ends. More...
 
Cursor const & storeCursor ()
 Save the cursor position and return a copy to hold as a backtrack point. More...
 
void restoreCursor (Cursor const &crs)
 Restore the cursor from a copy taken by storeCursor(). More...
 
void exit (int status)
 Abort the parse. Throws an internal exception caught by parse(), which then returns false. More...
 
void recordError (ParseError::Kind kind, std::string const &message, unsigned long int line=0, unsigned long int col=0)
 Append a diagnostic to the collector. More...
 
void enterScope () noexcept
 Note that the grammar has consumed a scope opener (brace, bracket, begin, …). More...
 
void leaveScope () noexcept
 Note that the grammar has consumed the matching scope closer. Called only on the path that actually consumed a closer. More...
 
unsigned int openScopeDepth () const noexcept
 The number of scope openers not yet balanced by a closer. More...
 

Detailed Description

Abstract driver for a hand-written recursive-descent grammar.

Subclass Parser, implement start() (the grammar's entry rule) and getGrammarName(), and call parse() with a filename. The base handles the parts every grammar shares:

Copy and move are deleted.

See also
https://cparse.fedem.eu/reference/parser — reference manual page.
https://cparse.fedem.eu/docs/getting-started — build a first grammar.
Cursor

Member Enumeration Documentation

◆ TermRequirementDeclaration

Whether a grammar rule requires, permits, or forbids a terminator. Passed to grammar-specific term-matching helpers.

See also
https://cparse.fedem.eu/reference/parser-term-requirement-declaration
Enumerator
DISALLOWED 

A terminator must not appear.

OPTIONAL 

A terminator may appear.

MANDATORY 

A terminator must appear.

Constructor & Destructor Documentation

◆ Parser()

fedem::parser::Parser::Parser ( )
default

Default-construct. No file is open until parse() is called.

See also
https://cparse.fedem.eu/reference/parser-ctor

◆ ~Parser()

fedem::parser::Parser::~Parser ( )
virtualdefault

Member Function Documentation

◆ parse()

bool fedem::parser::Parser::parse ( std::string  filename)

Parse filename: open it, run start(), and classify the ending.

Parameters
filenamePath to parse. Resolved with std::filesystem::canonical; a missing file is reported on std::clog and yields false.
Returns
true on a clean parse (grammar succeeded and any scopes it opened were closed); false if start() failed, exit() was called, the input ended with scopes still open, or an I/O / internal error occurred. A nested parse() (an include) restores the parent cursor and returns true.
Note
On failure, inspect errors() for the reason(s). Only the outermost parse() resets the open-scope depth.
See also
https://cparse.fedem.eu/reference/parser-parse

◆ openStream()

bool fedem::parser::Parser::openStream ( std::string  filename)

Open filename and set up the cursor, but do not run start() — for a grammar driven from outside one unit at a time instead of "parse everything, then read the result" (the canonical example: a CSV-style reader whose public interface is nextRow(), called until it returns nothing).

parse() does not fit that shape: it calls start() itself and, the instant start() returns, tears the cursor down — right for a grammar where start() is the whole parse, fatal for a driver that still needs getCursor() valid afterwards (the external caller has not finished reading yet). openStream() does only the setup half parse() does — same std::filesystem::canonical resolution, same missing-file diagnostic on std::clog — and stops there. Drive the grammar afterwards through whatever public methods it exposes for that (e.g. repeated calls into helpers built on getCursor()); the cursor stays valid until the next parse()/openStream() call or destruction.

Parameters
filenamePath to open. Resolved with std::filesystem::canonical; a missing file is reported on std::clog and yields false.
Returns
true if the file was opened and the cursor is ready.
See also
https://cparse.fedem.eu/reference/parser-open-stream
https://cparse.fedem.eu/walkthrough/csv-lite

◆ getGrammarName()

virtual std::string fedem::parser::Parser::getGrammarName ( ) const
pure virtualnoexcept

The grammar's name, for diagnostics. Implemented by the subclass.

Returns
The grammar name.
See also
https://cparse.fedem.eu/reference/parser-get-grammar-name

◆ errors()

std::vector< ParseError > const & fedem::parser::Parser::errors ( ) const
inlinenoexcept

The collected diagnostics, in the order they were recorded. Valid after parse() returns; check when it returns false.

Returns
The diagnostics collector, oldest first.
See also
https://cparse.fedem.eu/reference/parser-errors

◆ hasErrors()

bool fedem::parser::Parser::hasErrors ( ) const
inlinenoexcept

Whether any diagnostic has been collected.

Returns
true if the collector is non-empty.
See also
https://cparse.fedem.eu/reference/parser-has-errors

◆ clearErrors()

void fedem::parser::Parser::clearErrors ( )
inlinenoexcept

Discard all collected diagnostics. Called by parse() on entry.

See also
https://cparse.fedem.eu/reference/parser-clear-errors

◆ start()

virtual bool fedem::parser::Parser::start ( )
protectedpure virtual

The grammar's entry rule. Implemented by the subclass; called by parse().

Returns
true if the grammar accepted the input.
See also
https://cparse.fedem.eu/reference/parser-start

◆ skipWhiteSpaces()

bool fedem::parser::Parser::skipWhiteSpaces ( )
protectedvirtual

Consume a run of whitespace at the cursor.

Returns
true if at least one whitespace character was consumed.
See also
https://cparse.fedem.eu/reference/parser-skip-white-spaces

◆ skipComments()

bool fedem::parser::Parser::skipComments ( )
protectedvirtual

Consume a comment at the cursor. The base returns false (no comment syntax); a grammar overrides it.

Returns
true if a comment was consumed.
See also
https://cparse.fedem.eu/reference/parser-skip-comments

◆ skipCommentsBlock()

bool fedem::parser::Parser::skipCommentsBlock ( )
protected

Repeatedly skipWhiteSpaces() and skipComments() until neither consumes anything.

Returns
true if anything at all was skipped.
See also
https://cparse.fedem.eu/reference/parser-skip-comments-block

◆ extractToken()

bool fedem::parser::Parser::extractToken ( std::string const &  token)
protected

Match token literally at the cursor. On a partial match the cursor is restored to where it started.

Parameters
tokenThe literal to match.
Returns
true if the whole token matched and was consumed.
See also
https://cparse.fedem.eu/reference/parser-extract-token

◆ extractCharacter()

bool fedem::parser::Parser::extractCharacter ( std::string::value_type const  token)
protected

Match a single character at the cursor.

Parameters
tokenThe character to match.
Returns
true if it matched and was consumed.
See also
https://cparse.fedem.eu/reference/parser-extract-character

◆ writeTraceMessage()

void fedem::parser::Parser::writeTraceMessage ( )
protected

Write a short trace (location plus the next few lines of input) to std::clog. A debugging aid.

See also
https://cparse.fedem.eu/reference/parser-write-trace-message

◆ getCursor() [1/2]

Cursor & fedem::parser::Parser::getCursor ( )
inlineprotected

The active cursor.

Returns
A reference to the cursor parse() is currently reading.
See also
https://cparse.fedem.eu/reference/parser-get-cursor

◆ getCursor() [2/2]

Cursor const & fedem::parser::Parser::getCursor ( ) const
inlineprotected

The active cursor (const overload).

Returns
A const reference to the cursor parse() is currently reading.
See also
https://cparse.fedem.eu/reference/parser-get-cursor

◆ pushCursor()

void fedem::parser::Parser::pushCursor ( std::string const &  sourceName,
std::shared_ptr< Cursor::stream_type stream 
)
protected

Push a new input onto the cursor stack (an include). The current cursor is saved and restored when the nested input ends.

Parameters
sourceNameName for diagnostics.
streamThe nested input stream.
See also
https://cparse.fedem.eu/reference/parser-push-cursor

◆ storeCursor()

Cursor const & fedem::parser::Parser::storeCursor ( )
protected

Save the cursor position and return a copy to hold as a backtrack point.

Returns
A reference to the active cursor, now with its position saved.
See also
https://cparse.fedem.eu/reference/parser-store-cursor

References fedem::parser::Cursor::store().

+ Here is the call graph for this function:

◆ restoreCursor()

void fedem::parser::Parser::restoreCursor ( Cursor const &  crs)
protected

Restore the cursor from a copy taken by storeCursor().

Parameters
crsA cursor copy previously returned by storeCursor().
See also
https://cparse.fedem.eu/reference/parser-restore-cursor

References fedem::parser::Cursor::restore().

+ Here is the call graph for this function:

◆ exit()

void fedem::parser::Parser::exit ( int  status)
protected

Abort the parse. Throws an internal exception caught by parse(), which then returns false.

Parameters
statusExit code carried on the exception.
Note
Record the reason with recordError() before calling this.
See also
https://cparse.fedem.eu/reference/parser-exit

◆ recordError()

void fedem::parser::Parser::recordError ( ParseError::Kind  kind,
std::string const &  message,
unsigned long int  line = 0,
unsigned long int  col = 0 
)
protected

Append a diagnostic to the collector.

Parameters
kindSeverity / category.
messageDescription.
line1-based line, or 0 to take the cursor's current line.
col1-based column, or 0 to take the cursor's current column.
Note
Does not call exit(); call exit() separately when fatal.
See also
https://cparse.fedem.eu/reference/parser-record-error

References fedem::parser::ParseError::col, fedem::parser::ParseError::filename, fedem::parser::ParseError::kind, fedem::parser::ParseError::line, and fedem::parser::ParseError::message.

◆ enterScope()

void fedem::parser::Parser::enterScope ( )
protectednoexcept

Note that the grammar has consumed a scope opener (brace, bracket, begin, …).

A grammar with nesting calls this on an opener and leaveScope() on the matching closer. parse() reads openScopeDepth() after end-of-input: a non-zero depth means the input was truncated mid-construct and parse() records a syntax error instead of treating the EOF as clean.

This is deliberately not an RAII guard: the depth must stay non-zero while the end-of-input exception unwinds, because that is the condition being detected. Grammars that never call these keep a depth of zero and behave exactly as before.

See also
https://cparse.fedem.eu/reference/parser-enter-scope

◆ leaveScope()

void fedem::parser::Parser::leaveScope ( )
protectednoexcept

Note that the grammar has consumed the matching scope closer. Called only on the path that actually consumed a closer.

See also
https://cparse.fedem.eu/reference/parser-leave-scope

◆ openScopeDepth()

unsigned int fedem::parser::Parser::openScopeDepth ( ) const
protectednoexcept

The number of scope openers not yet balanced by a closer.

Returns
The current open-scope depth (0 for a grammar that does not call enterScope()).
See also
https://cparse.fedem.eu/reference/parser-open-scope-depth

The documentation for this class was generated from the following files: