Skip to content

Commit

Permalink
Documentation: add documentation for parser_state.(c|h)
Browse files Browse the repository at this point in the history
  • Loading branch information
spalmer25 committed Feb 15, 2024
1 parent f31c0b2 commit 9ff9067
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 48 deletions.
9 changes: 9 additions & 0 deletions app/src/parser/parser_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,18 @@

#include "parser_state.h"

/**
* @brief Syntactic sugar to handle parser result case
*
*/
#define TZ_LABEL(_x) \
case TZ_##_x: \
return #_x

/**
* @brief Syntactic sugar to handle blocking parser result case
*
*/
#define BLO_LABEL(_x) \
case TZ_BLO_##_x: \
return #_x
Expand Down
203 changes: 155 additions & 48 deletions app/src/parser/parser_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,84 +24,182 @@

// Parser buffers and buffer handling registers

/**
* @brief This struct represents the parser register.
*
* It contains output and input buffers
*
*/
typedef struct {
// update `ibuf`, `iofs` and `ilen` at once with `parser_regs_refill`
// invariant between two refills:
// `iofs + ilen` = (constant) number of readable bytes in `ibuf`
uint8_t *ibuf; // input buffer
size_t iofs; // current offset
size_t ilen; // remaining bytes readable in input
// update `obuf`, `oofs` and `olen` at once with `parser_regs_flush`
// invariant between two refills:
// `oofs + olen` = (constant) number of readable bytes in `obuf`
char *obuf; // output buffer
size_t oofs; // current offset
size_t olen; // remaining bytes writable in output
/// update `ibuf`, `iofs` and `ilen` at once with `parser_regs_refill`
/// invariant between two refills:
/// `iofs + ilen` = (constant) number of readable bytes in `ibuf`
uint8_t *ibuf; /// input buffer
size_t iofs; /// current offset
size_t ilen; /// remaining bytes readable in input
/// update `obuf`, `oofs` and `olen` at once with `parser_regs_flush`
/// invariant between two refills:
/// `oofs + olen` = (constant) number of readable bytes in `obuf`
char *obuf; /// output buffer
size_t oofs; /// current offset
size_t olen; /// remaining bytes writable in output
} tz_parser_regs;

// Parser state

#define TZ_FIELD_NAME_SIZE 30
#define TZ_CAPTURE_BUFFER_SIZE 256
#define TZ_FIELD_NAME_SIZE 30 /// The size of the field name buffer
#define TZ_CAPTURE_BUFFER_SIZE 256 /// The size of the capture buffer

/**
* @brief Enumeration of all kinds of results meaningful to the parser
*
*/
typedef enum {
// success and non blocking, should loop again
TZ_CONTINUE = 0, // fall through rest of current step
TZ_BREAK, // signals caller to return, errno should be CONTINUE
// success but parsing blocked
TZ_BLO_DONE = 100, // parsing complete
TZ_BLO_FEED_ME, // blocked on read from input
TZ_BLO_IM_FULL, // blocked on output space
// everything below is an error
TZ_ERR_INVALID_TAG = 200,
TZ_ERR_INVALID_OP,
TZ_ERR_INVALID_DATA,
TZ_ERR_UNSUPPORTED,
TZ_ERR_TOO_LARGE,
TZ_ERR_TOO_DEEP,
TZ_ERR_INVALID_STATE,
/// success and non blocking, should loop again
TZ_CONTINUE = 0, /// fall through rest of current step
TZ_BREAK, /// signals caller to return, errno should be CONTINUE
/// success but parsing blocked
TZ_BLO_DONE = 100, /// parsing complete
TZ_BLO_FEED_ME, /// blocked on read from input
TZ_BLO_IM_FULL, /// blocked on output space
/// everything below is an error
TZ_ERR_INVALID_TAG = 200, /// an invalid tag has been found
TZ_ERR_INVALID_OP, /// an invalid michelson operation has been found
TZ_ERR_INVALID_DATA, /// a data has been considered as invalid
TZ_ERR_UNSUPPORTED, /// a non-supported action has been triggered
TZ_ERR_TOO_LARGE, /// too large data has been found
TZ_ERR_TOO_DEEP, /// too deep data has been found
TZ_ERR_INVALID_STATE, /// the parser is in an invalid state
} tz_parser_result;
#define TZ_IS_BLOCKED(code) (code >= 100)
#define TZ_IS_ERR(code) (code >= 200)

#define TZ_IS_BLOCKED(code) \
(code >= 100) /// If the result is a blocking result
#define TZ_IS_ERR(code) (code >= 200) /// If the result is an error

/**
* @brief Get the human readable name of a parser result
*
* @param code: the parser result
* @return const char*: the name of the parser result
*/
const char *tz_parser_result_name(tz_parser_result code);

/**
* @brief This struct represents the parser state.
*
*/
typedef struct {
tz_parser_regs regs;
tz_parser_regs regs; /// parser register

// common fields to communicate with caller
tz_parser_result errno;
tz_parser_result errno; /// current parser result
struct {
char field_name[TZ_FIELD_NAME_SIZE];
bool is_field_complex;
int field_index;
} field_info;
// common singleton buffers
int ofs;
char field_name[TZ_FIELD_NAME_SIZE]; /// the name of the last field
/// parsed
bool is_field_complex; /// if the last field parsed is considered
/// complex for a common user
int field_index; /// the index of the last field parsed
} field_info; /// information of the last field parsed
// common singleton buffers
int ofs; /// offset for the parser
struct {
tz_num_parser_buffer num;
uint8_t capture[TZ_CAPTURE_BUFFER_SIZE];
tz_num_parser_buffer num; /// number parser buffer
uint8_t capture[TZ_CAPTURE_BUFFER_SIZE]; /// capture buffer is used
/// to store string values
} buffers;
// input type specific state
tz_micheline_state micheline;
tz_operation_state operation;
tz_micheline_state micheline; /// micheline parser state
tz_operation_state operation; /// operation parser state
} tz_parser_state;

/**
* @brief Initialize a parser state
*
* @param state: the parser state
*/
void tz_parser_init(tz_parser_state *state);

/**
* @brief Flush what has been parsed
*
* @param state: the parser state
* @param obuf: the ouput buffer
* @param olen: the length of the output buffer
*/
void tz_parser_flush(tz_parser_state *state, char *obuf, size_t olen);

/**
* @brief Flush a part of what has been parsed
*
* @param state: the parser state
* @param obuf: the ouput buffer
* @param olen: the length of the output buffer
* @param up_to: the length of what we want to flush up to
*/
void tz_parser_flush_up_to(tz_parser_state *state, char *obuf, size_t olen,
size_t up_to);

/**
* @brief Refill what should be parsed
*
* @param state: the parser state
* @param ibuf: the input buffer
* @param ilen: the length of the input buffer
*/
void tz_parser_refill(tz_parser_state *state, uint8_t *ibuf, size_t ilen);

/**
* @brief Skip to next byte
*
* @param state: the parser state
*/
void tz_parser_skip(tz_parser_state *state);

/**
* @brief Put a character at the end of was has been parsed
*
* @param state: the parser state
* @param c: the character
* @return tz_parser_result: the parser result
*/
tz_parser_result tz_parser_put(tz_parser_state *state, char c);

/**
* @brief Read a bytes
*
* @param state: the parser state
* @param out: the output character pointer
* @return tz_parser_result: the parser result
*/
tz_parser_result tz_parser_read(tz_parser_state *state, uint8_t *out);

/**
* @brief Peek a bytes
*
* @param state: the parser state
* @param out: the output character pointer
* @return tz_parser_result: the parser result
*/
tz_parser_result tz_parser_peek(tz_parser_state *state, uint8_t *out);

// error handling utils

/**
* @brief Set and raise a parser result
*
* @param state: the parser state
* @param code: the parser result to set
* @return tz_parser_result: the parser result raised
*/
tz_parser_result tz_parser_set_errno(tz_parser_state *state,
tz_parser_result code);

/**
* @brief Set a parser result and raise
*
* Expect a `state` variable
*
*/
#ifdef TEZOS_DEBUG
#define tz_return(e) \
do { \
Expand All @@ -115,15 +213,24 @@ tz_parser_result tz_parser_set_errno(tz_parser_state *state,
#else
#define tz_return(e) return tz_parser_set_errno(state, e)
#endif
#define tz_raise(e) tz_return(TZ_ERR_##e)
#define tz_stop(e) tz_return(TZ_BLO_##e)
#define tz_reraise return state->errno

#define tz_raise(e) tz_return(TZ_ERR_##e) /// Raise an parser error
#define tz_stop(e) tz_return(TZ_BLO_##e) /// Stop the parser
#define tz_reraise return state->errno /// Re-raise the parser result

/**
* @brief Raise if the condition did not continue
*
* Usually used to ensure that the parser did not raised errors
*
*/
#define tz_must(cond) \
do { \
tz_parser_result _err = cond; \
if (_err) { \
tz_return(_err); \
} \
} while (0)
#define tz_continue tz_return(TZ_CONTINUE)
#define tz_break tz_return(TZ_BREAK)

#define tz_continue tz_return(TZ_CONTINUE) /// continue the parsing
#define tz_break tz_return(TZ_BREAK) /// break the parsing

0 comments on commit 9ff9067

Please sign in to comment.