drgn/libdrgn/lexer.h
Omar Sandoval 7d251fee6e Translate C lexer tests to C unit tests
This allows us to get rid of a bunch of exports and ctypes wrappers.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2024-04-26 14:53:53 -07:00

131 lines
3.0 KiB
C

// Copyright (c) Meta Platforms, Inc. and affiliates.
// SPDX-License-Identifier: LGPL-2.1-or-later
/**
* @file
*
* Lexer interface.
*
* See @ref Lexer.
*/
#ifndef DRGN_LEXER_H
#define DRGN_LEXER_H
#include <stddef.h>
#include "vector.h"
/**
* @ingroup Internals
*
* @defgroup Lexer Lexer
*
* Lexical analysis.
*
* This is a convenient interface for lexical analysis. @ref drgn_lexer provides
* the abstraction of a stack of tokens (@ref drgn_token) on top of a raw @ref
* drgn_lexer_func.
*
* @{
*/
struct drgn_lexer;
struct drgn_token;
/**
* Lexer function.
*
* A lexer function does the work of lexing the next token in a string. It
* should initialize the passed in token and advance @ref drgn_lexer::p.
*/
typedef struct drgn_error *(*drgn_lexer_func)(struct drgn_lexer *,
struct drgn_token *);
/** Lexical token. */
struct drgn_token {
/** Kind of token as defined by the lexer function. */
int kind;
/**
* String value of the token (i.e., the lexeme).
*
* This points to the contents of the original string, so it isn't
* null-terminated.
*/
const char *value;
/** Length of the token value. */
size_t len;
};
DEFINE_VECTOR_TYPE(drgn_token_vector, struct drgn_token);
/**
* Lexer instance.
*
* A lexer comprises a lexer function, a position, and a stack of tokens. Tokens
* can be pushed and popped onto the stack. When the stack is empty, a pop calls
* the lexer function instead.
*/
struct drgn_lexer {
/** Lexer function. */
drgn_lexer_func func;
/** Current position in the string. */
const char *p;
/** Stack of tokens. */
struct drgn_token_vector stack;
};
/**
* Initialize a @ref drgn_lexer from a lexer function and a string.
*
* @param[in] lexer Lexer to initialize.
* @param[in] func Lexer function.
* @param[in] str String to lex.
*/
void drgn_lexer_init(struct drgn_lexer *lexer, drgn_lexer_func func,
const char *str);
/**
* Free memory allocated by a @ref drgn_lexer.
*
* @param[in] lexer Lexer to deinitialize.
*/
void drgn_lexer_deinit(struct drgn_lexer *lexer);
/**
* Return the next token from a @ref drgn_lexer.
*
* If there are tokens on the stack, this pops and returns the top token.
* Otherwise, this calls the lexer function to get the next token.
*
* @return @c NULL on success, non-@c NULL on error.
*/
struct drgn_error *drgn_lexer_pop(struct drgn_lexer *lexer,
struct drgn_token *token);
/**
* Push a token onto the stack of a @ref drgn_lexer.
*
* This token must have been returned by @ref drgn_lexer_pop().
*
* @return @c NULL on success, non-@c NULL on error.
*/
struct drgn_error *drgn_lexer_push(struct drgn_lexer *lexer,
const struct drgn_token *token);
/**
* Return the next token from a @ref drgn_lexer and leave it on top of the
* stack.
*
* This is equivalent to a call to @ref drgn_lexer_pop() immediately followed by
* a call to @ref drgn_lexer_push().
*
* @return @c NULL on success, non-@c NULL on error.
*/
struct drgn_error *drgn_lexer_peek(struct drgn_lexer *lexer,
struct drgn_token *token);
/** @} */
#endif /* DRGN_LEXER_H */