pianod2
multisource multiuser scriptable networked music player
Classes | Typedefs | Functions | Variables
Parsnip Namespace Reference

Serialization and parsing library. More...

Classes

class  Exception
 Class representing issues related to serialization & parsing. More...
 
class  DataRangeError
 DataRangeError indicates a value received in a stream can't be represented. More...
 
class  Data
 Generic data type. More...
 
class  DataFormatError
 DataFormatError represents a syntax error in a datastream. More...
 
class  NoSuchKey
 An element requested from a constant dictionary does not exist. More...
 
class  IncorrectDataType
 The data's type is inconsistent with the use requested of it. More...
 
class  IncorrectListSize
 The list size does not meet schema requirements. More...
 
class  InvalidKey
 They key is not specified in the schema. More...
 
class  SchemaConflict
 Parsing/command patterns produce schema inconsistency. More...
 
struct  SchemaBaseDeleter
 Helper functor for schema smart pointers. More...
 
class  SchemaBaseRef
 Smart pointer for schemas, with unusual ability to be copied. More...
 
class  Schema
 Schema for one JSON object. More...
 
class  ArgumentVector
 This class lexically analyzes a string, splitting it up into tokens, which are accessed as a vector. More...
 
class  ArgvCursor
 An iterator for argument vectors. More...
 
class  NumberOutOfRange
 NumberOutOfRange: The number was outside the range defined in the command pattern. More...
 
class  NotNumeric
 Not numeric: A command pattern specified a number, but the token was not valid number. More...
 
class  InvalidValue
 A token encountered was not one of the expected keywords. More...
 
class  IncompleteCommand
 More tokens were expected. More...
 
class  RunOnCommand
 There were extra tokens at the end of the command pattern. More...
 
class  DuplicateOption
 An option was supplied twice to an iterating option parser. More...
 
class  NoSchemaDefined
 A schema is not defined for a certain command ID. More...
 
struct  EvaluatorDeleter
 This does what std::default_delete would do, but is required since we haven't defined Evaluator yet. More...
 
class  OptionParser
 A class for parsing command line options (name-value pairs, for instance). More...
 
class  Parser
 A class for parsing command lines. More...
 
class  Interpreter
 
class  Dispatcher
 
class  SchemaSet
 A schema built to validate JSON messages based on command line patterns. More...
 
class  Evaluator
 Evaluator base class. More...
 
class  TerminatorEvaluator
 An evaluator representing abrupt end of the command pattern. More...
 
class  EndOfOptionEvaluator
 An evaluator representing abrupt end of the command pattern. More...
 
class  ValueEvaluator
 Evaluate a value/fill-in field. More...
 
class  StringEvaluator
 Evaluate a string value field. More...
 
class  RegExEvaluator
 Evaluate a string value field. More...
 
class  RawRemainderEvaluator
 Gather the rest of the command line as an untokenized string. More...
 
class  IntegerEvaluator
 Evaluate and validate an integral value field. More...
 
class  RealEvaluator
 Evaluate and validate a numeric value field. More...
 
class  KeywordEvaluator
 Evaluate a keyword in a command line. More...
 
class  RemainderEvaluator
 An evaluator that represents the rest of the command line. More...
 
class  RemainingValuesEvaluator
 Gather the rest of the command line tokens in a list. More...
 
class  OptionEvaluator
 Evaluate remainder with a different parser. More...
 
class  SchemaBase
 
class  UncheckedSchema
 Schema component requiring data be a particular type. More...
 
class  TypeSchema
 Schema component requiring data be a particular type. More...
 
class  StringSchema
 Schema component requiring data be a string of characters (no control characters). More...
 
class  RegExSchema
 Schema component requiring data be a string of characters matching a regular expression. More...
 
class  KeywordSchema
 Schema component accepting strings with certain values. More...
 
class  RangeSchema
 Schema component for numeric data, either Integer or Real. More...
 
class  IntegerSchema
 
class  OptionSchema
 Schema adapter component that allows use of schemas from option parsers. More...
 
class  ListSchema
 Schema component for lists. More...
 
class  DictionarySchema
 Schema component for validating dictionaries. More...
 
class  ConjunctionSchema
 A meta-schema that determines if any, all, or exactly one or none of its subschemas are valid. More...
 
class  InvalidSchema
 Parsing/command patterns produce schema inconsistency. More...
 

Typedefs

using InputStream = std::istream
 
using SchemaRef = std::shared_ptr< class Schema >
 
using EvaluatorRef = std::unique_ptr< class Evaluator, EvaluatorDeleter >
 
using OptionParserRef = std::shared_ptr< OptionParser >
 
using ParserRef = std::shared_ptr< Parser >
 
using SchemaSetRef = std::shared_ptr< SchemaSet >
 
using SchemaIntegratorCallback = std::function< void(const int, const class DictionarySchema &)>
 
using NumberSchema = RangeSchema< double >
 

Functions

Data parse_json (std::istream &from, bool check_termination)
 Parse a stream as JSON data. More...
 
Data parse_json (const std::string &from)
 Parse a string as a JSON stream. More...
 
std::ostream & operator<< (std::ostream &out, const Parsnip::Data &data)
 
static void options_evaluator_convert (EvaluatorRef &evaluator)
 Convert a terminator evaluator to an end-of-options evaluator. More...
 
void parser_assert (bool requirement, const char *explanation)
 
void parser_assert (bool requirement, const char *explanation, const std::string &detail)
 
template<class DesiredEvaluator >
static DesiredEvaluator * uptype_construct (EvaluatorRef &parser, bool *existed=nullptr)
 If an evaluator isn't constructed, create it. More...
 
static char hexdigit (int digit)
 Helper function: Retrieve a hexadecimal digit. More...
 
static void do_indent (std::ostream &target, int amount)
 Generate some indentation. More...
 
static void do_newline (std::ostream &target, int amount)
 Write a newline to a stream. More...
 
static void json_encode_string (std::ostream &target, const std::string &value)
 Write a string to a stream, literal-encoding special characters. More...
 
std::istream::int_type next_non_whitespace (InputStream &from)
 Read from a stream until a non-whitespace character is found. More...
 
static void require_character (InputStream &from, std::istream::int_type expect)
 Verify the next non-whitespace character in a stream is what's expected. More...
 
static int parse_hex_digits (InputStream &from, int count)
 Parse hexadecimal digits from a stream. More...
 
static const std::string parse_json_string (InputStream &from, const char quote)
 Parse a string out of a JSON stream. More...
 
static Data parse_json_inline_text (InputStream &from)
 Parse a keyword out of a JSON string. More...
 
static Data parse_json_inline_value (InputStream &from)
 Parse a numeric value in a JSON stream. More...
 
static Data parse_json_element (InputStream &from)
 Extract data from a JSON stream. More...
 
static Data parse_json_dictionary (InputStream &from)
 Parse a JSON dictionary from a stream. More...
 
static Data parse_json_list (InputStream &from)
 Parse a list from a JSON stream. More...
 
static SchemaBaseconstruct_schema (const Parsnip::Data &schema_spec)
 Assemble a schema from a specification. More...
 
static DictionarySchemaasDictionary (const SchemaBaseRef &schema)
 Verify the schema is the dictionary we expect, and return it typecast as such. More...
 

Variables

const std::string EmptyString
 
const char hex_digits [] = "0123456789abcdef"
 Digits used for encoding/decoding hexadecimal. More...
 
static const std::unordered_map< std::string, std::string > RegExForFormat
 Regular expressions for JSON strings that specify a format. More...
 

Detailed Description

Serialization and parsing library.

Classes providing evaluation for command lines.

The Parser class accepts arrays of strings/command ID combinations (Parser::Definition). From these, it builds a parse tree against which it can subsequently evaluate commands, identifying commands by ID and providing a dictionary the commands parameters. Multiple definition sets can be added to a single parser.

Lexically, commands are split at spaces, unless quoted. Single or double quotes may be used, but must match. Open quotes are only identified at the start of a word, close quotes only at the end of a word. Quotes may be doubled within a quoted span to insert a literal quote.

Statement patterns can be composed of:

Literal:

Names:

Alternation and optional patterns may contain an arbitrary number of possible keywords, Storage behavior:

Ranges:

Examples:

{ CREATE_USER, "create <rank:admin|guest|user> {username} {password}" }
-- Recognizes the 3 types of users and requires username & password parameter, nothing more.
{ CREATE_USER_EXTENDED, "create <rank:admin|guest|user> {username} {password} [{additional}] ..." }
-- Recognizes the 3 types of users and requires username, password, & at least 1 additional parameter.
{ CREATE_USER_OPTIONAL_EXTENDED, "create <rank:admin|guest|user> {user} {password} ... }
-- Recognizes the 3 types of users, requires username and password, allows additional parameters.
This definition is incompatible with CREATE_USER above--the parser would error when adding this
definition. (There is no way to delineate that command and this command with 0 parameters.)

A completely different approach to the above would be:

{ CREATE_ADMIN_USER, "create admin {username} {password} ..." },
{ CREATE_STANDARD_USER, "create standard {username} {password} ..." },
{ CREATE_GUEST_USER, "create guest {username} {password} ..." }
-- Returns different values for the different user types, so you can determine that
from the command's enumeration instead of having to further parse. As written, these
would each allow additional optional parameters beyond username and password.

Since the parse tree is assumed to be hard-coded in your application, this module simply throws a runtime_error it finds problems in the parse definitions.

Options parsing

An option parser may be used inline or as a remainder handler:

The option parser must be predefined and registered with the containing Parser prior to adding statements that reference it. Values from within the option parser sequences are stored in a dictionary named name.

Typedef Documentation

◆ EvaluatorRef

using Parsnip::EvaluatorRef = typedef std::unique_ptr<class Evaluator, EvaluatorDeleter>

◆ InputStream

using Parsnip::InputStream = typedef std::istream

◆ NumberSchema

using Parsnip::NumberSchema = typedef RangeSchema <double>

◆ OptionParserRef

using Parsnip::OptionParserRef = typedef std::shared_ptr<OptionParser>

◆ ParserRef

using Parsnip::ParserRef = typedef std::shared_ptr<Parser>

◆ SchemaIntegratorCallback

using Parsnip::SchemaIntegratorCallback = typedef std::function <void (const int, const class DictionarySchema &)>

◆ SchemaRef

using Parsnip::SchemaRef = typedef std::shared_ptr <class Schema>

◆ SchemaSetRef

using Parsnip::SchemaSetRef = typedef std::shared_ptr <SchemaSet>

Function Documentation

◆ asDictionary()

static DictionarySchema* Parsnip::asDictionary ( const SchemaBaseRef schema)
inlinestatic

Verify the schema is the dictionary we expect, and return it typecast as such.

Throw if it's not what we expected.

Here is the caller graph for this function:

◆ construct_schema()

static SchemaBase * Parsnip::construct_schema ( const Parsnip::Data schema_spec)
static

Assemble a schema from a specification.

Parameters
schema_specThe specification.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ do_indent()

static void Parsnip::do_indent ( std::ostream &  target,
int  amount 
)
inlinestatic

Generate some indentation.

Parameters
targetThe stream to write indentation to.
amountThe amount of indentation, in spaces. Negative numbers = none.
Here is the caller graph for this function:

◆ do_newline()

static void Parsnip::do_newline ( std::ostream &  target,
int  amount 
)
inlinestatic

Write a newline to a stream.

Parameters
targetThe stream to write the newline to.
amountAmount of indent. If negative, we're not indenting, so don't worry about newlines either.
Here is the caller graph for this function:

◆ hexdigit()

static char Parsnip::hexdigit ( int  digit)
inlinestatic

Helper function: Retrieve a hexadecimal digit.

Here is the caller graph for this function:

◆ json_encode_string()

static void Parsnip::json_encode_string ( std::ostream &  target,
const std::string &  value 
)
static

Write a string to a stream, literal-encoding special characters.

Parameters
targetThe stream to write to.
valueThe string to write.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ next_non_whitespace()

std::istream::int_type Parsnip::next_non_whitespace ( InputStream from)

Read from a stream until a non-whitespace character is found.

Exceptions
DataFormatErrorif EOF is encountered.
Here is the caller graph for this function:

◆ operator<<()

std::ostream& Parsnip::operator<< ( std::ostream &  out,
const Parsnip::Data data 
)
inline

◆ options_evaluator_convert()

static void Parsnip::options_evaluator_convert ( EvaluatorRef evaluator)
inlinestatic

Convert a terminator evaluator to an end-of-options evaluator.

Parameters
evaluatorA pointer container for the existing evaluator.
Here is the caller graph for this function:

◆ parse_hex_digits()

static int Parsnip::parse_hex_digits ( InputStream from,
int  count 
)
static

Parse hexadecimal digits from a stream.

Parameters
fromThe stream to take digits from.
countThe number of digits expected.
Here is the caller graph for this function:

◆ parse_json() [1/2]

Data Parsnip::parse_json ( const std::string &  from)

Parse a string as a JSON stream.

Parameters
fromThe string to parse.
Returns
Data structure accoring to parsed string.
Exceptions
DataFormatErrorif JSON is mangled.
DataRangeErrorIf the stream contains unrepresentable numbers.
Here is the call graph for this function:

◆ parse_json() [2/2]

Data Parsnip::parse_json ( std::istream &  from,
bool  check_termination 
)

Parse a stream as JSON data.

Parameters
fromThe stream to parse.
check_terminationIf true (default), validates stream terminates (EOF) after end of JSON data. If false, stops reading after a complete JSON object has been read.
Returns
Data structure accoring to parsed string.
Exceptions
DataFormatErrorif JSON is mangled.
DataRangeErrorIf the stream contains unrepresentable numbers.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_json_dictionary()

static Data Parsnip::parse_json_dictionary ( InputStream from)
static

Parse a JSON dictionary from a stream.

Parameters
fromThe stream to read.
Returns
A Data object containing the dictionary.
Exceptions
DataFormatErrorif the dictionary is invalid.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_json_element()

static Data Parsnip::parse_json_element ( InputStream from)
static

Extract data from a JSON stream.

This function looks at the next non-whitespace character in the stream to determine the data type, then calls the appropriate handler to do the work.

Parameters
fromThe stream to parse.
Returns
A Data object with the data extracted.
Exceptions
DataFormatErrorIf the stream is invalid.
DataRangeErrorIf the stream contains unrepresentable numbers.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_json_inline_text()

static Data Parsnip::parse_json_inline_text ( InputStream from)
static

Parse a keyword out of a JSON string.

Parameters
fromThe stream to read.
Returns
A Data object corresponding to the keyword.
Exceptions
DataFormatErrorif the keyword is invalid.
Here is the caller graph for this function:

◆ parse_json_inline_value()

static Data Parsnip::parse_json_inline_value ( InputStream from)
static

Parse a numeric value in a JSON stream.

Parameters
fromThe stream
Returns
The number, wrapped in a Data object.
Exceptions
DataFormatErrorif there isn't a number.
Here is the caller graph for this function:

◆ parse_json_list()

static Data Parsnip::parse_json_list ( InputStream from)
static

Parse a list from a JSON stream.

Parameters
fromThe stream to read from.
Returns
A Data object containing the list.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parse_json_string()

static const std::string Parsnip::parse_json_string ( InputStream from,
const char  quote 
)
static

Parse a string out of a JSON stream.

Parameters
fromThe stream to parse.
quoteThe quote characters being used around the string.
Returns
A string with literals converted to their real values.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parser_assert() [1/2]

void Parsnip::parser_assert ( bool  requirement,
const char *  explanation 
)
inline
Here is the caller graph for this function:

◆ parser_assert() [2/2]

void Parsnip::parser_assert ( bool  requirement,
const char *  explanation,
const std::string &  detail 
)
inline

◆ require_character()

static void Parsnip::require_character ( InputStream from,
std::istream::int_type  expect 
)
inlinestatic

Verify the next non-whitespace character in a stream is what's expected.

Exceptions
DataFormatErrorif the character isn't the one expected or EOF.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ uptype_construct()

template<class DesiredEvaluator >
static DesiredEvaluator* Parsnip::uptype_construct ( EvaluatorRef parser,
bool *  existed = nullptr 
)
inlinestatic

If an evaluator isn't constructed, create it.

If it exists and is the right type, leave it alone. If it is a TerminatorEvaluator, upgrade it to the type we want.

Template Parameters
DesiredEvaluatorThe type of evaluator we want.
Parameters
parserA pointer container for the existing evaluator.
existedIf not null, set to indicate whether parser was already the specified type.
Returns
A pointer to the parser.

Variable Documentation

◆ EmptyString

const std::string Parsnip::EmptyString

◆ hex_digits

const char Parsnip::hex_digits = "0123456789abcdef"
extern

Digits used for encoding/decoding hexadecimal.

◆ RegExForFormat

const std::unordered_map<std::string, std::string> Parsnip::RegExForFormat
static

Regular expressions for JSON strings that specify a format.