edfb3e24a3
bshell: the front-end binary bshell.runtime: contains the parser, compiler, and classes needed to run bshell scripts bshell.core: contains the builtin commandlets and aliases
205 lines
7.5 KiB
C
205 lines
7.5 KiB
C
#ifndef PARSE_LEX_INTERNAL_H_
|
|
#define PARSE_LEX_INTERNAL_H_
|
|
|
|
#include <bshell/parse/lex.h>
|
|
#include <bshell/parse/token.h>
|
|
#include <bshell/status.h>
|
|
|
|
struct bshell_lex_ctx;
|
|
|
|
enum state_flags {
|
|
/* statement: don't convert matching words to keywords */
|
|
STATEMENT_F_DISABLE_KEYWORDS = 0x01u,
|
|
/* arithmetic: don't switch back to statement mode even when
|
|
* encountering a token that would otherwise require it. */
|
|
ARITHMETIC_F_DISABLE_STATEMENTS = 0x01u,
|
|
};
|
|
|
|
enum read_flags {
|
|
READ_APPEND_HYPHEN = 0x01u,
|
|
READ_NO_SET_TOKEN_START = 0x02u,
|
|
READ_NO_NUMBER_RECOGNITION = 0x04u,
|
|
};
|
|
|
|
enum link_flags {
|
|
LINK_ALLOW_RECURSION = 0x01u,
|
|
};
|
|
|
|
#define LINK_PUSH(tok, target, flags) \
|
|
((struct bshell_lex_state_link) { \
|
|
.l_token = (tok), \
|
|
.l_type = BSHELL_LEX_STATE_LINK_PUSH, \
|
|
.l_target = (target), \
|
|
.l_target_flags = (flags), \
|
|
})
|
|
#define LINK_PUSH_WITH_TERM(tok, target, flags, ...) \
|
|
((struct bshell_lex_state_link) { \
|
|
.l_token = (tok), \
|
|
.l_type = BSHELL_LEX_STATE_LINK_PUSH, \
|
|
.l_target = (target), \
|
|
.l_target_flags = (flags), \
|
|
.l_terminators = {__VA_ARGS__, BSHELL_TOK_NONE}, \
|
|
})
|
|
#define LINK_CHANGE(tok, target) \
|
|
((struct bshell_lex_state_link) { \
|
|
.l_token = (tok), \
|
|
.l_type = BSHELL_LEX_STATE_LINK_CHANGE, \
|
|
.l_target = (target), \
|
|
})
|
|
#define LINK_POP(tok) \
|
|
((struct bshell_lex_state_link) { \
|
|
.l_token = (tok), \
|
|
.l_type = BSHELL_LEX_STATE_LINK_POP, \
|
|
})
|
|
#define LINK_POP2(tok, flags) \
|
|
((struct bshell_lex_state_link) { \
|
|
.l_token = (tok), \
|
|
.l_type = BSHELL_LEX_STATE_LINK_POP, \
|
|
.l_flags = (flags), \
|
|
})
|
|
#define LINK_NONE(tok) \
|
|
((struct bshell_lex_state_link) { \
|
|
.l_token = (tok), \
|
|
.l_type = BSHELL_LEX_STATE_LINK_NONE, \
|
|
})
|
|
#define LINK_END ((struct bshell_lex_state_link) {})
|
|
|
|
struct bshell_lex_state_link {
|
|
unsigned int l_token;
|
|
enum {
|
|
BSHELL_LEX_STATE_LINK_NONE,
|
|
BSHELL_LEX_STATE_LINK_PUSH,
|
|
BSHELL_LEX_STATE_LINK_CHANGE,
|
|
BSHELL_LEX_STATE_LINK_POP,
|
|
} l_type;
|
|
enum link_flags l_flags;
|
|
enum bshell_lex_state_id l_target;
|
|
enum state_flags l_target_flags;
|
|
unsigned int l_terminators[BSHELL_LEX_STATE_MAX_TERMINATORS];
|
|
};
|
|
|
|
typedef enum bshell_status (*lex_state_pump_token)(struct bshell_lex_ctx *);
|
|
typedef enum bshell_status (*lex_state_begin)(struct bshell_lex_ctx *);
|
|
typedef enum bshell_status (*lex_state_end)(struct bshell_lex_ctx *);
|
|
|
|
struct bshell_lex_state_type {
|
|
enum bshell_lex_state_id s_id;
|
|
lex_state_pump_token s_pump_token;
|
|
lex_state_begin s_begin;
|
|
lex_state_end s_end;
|
|
|
|
const unsigned int *s_keywords;
|
|
const unsigned int *s_operators;
|
|
const unsigned int *s_symbols;
|
|
const struct bshell_lex_state_link *s_links;
|
|
};
|
|
|
|
extern enum bshell_status pump_token_statement(struct bshell_lex_ctx *ctx);
|
|
extern enum bshell_status pump_token_expression(struct bshell_lex_ctx *ctx);
|
|
extern enum bshell_status pump_token_command(struct bshell_lex_ctx *ctx);
|
|
extern enum bshell_status pump_token_arithmetic(struct bshell_lex_ctx *ctx);
|
|
extern enum bshell_status pump_token_string(struct bshell_lex_ctx *ctx);
|
|
|
|
extern void set_token_start(struct bshell_lex_ctx *ctx);
|
|
extern void set_token_end(struct bshell_lex_ctx *ctx);
|
|
|
|
extern struct bshell_lex_state *lex_state_push(
|
|
struct bshell_lex_ctx *ctx,
|
|
enum bshell_lex_state_id state_type,
|
|
enum state_flags flags);
|
|
extern void lex_state_pop(struct bshell_lex_ctx *ctx);
|
|
extern struct bshell_lex_state *lex_state_get(struct bshell_lex_ctx *ctx);
|
|
extern void lex_state_change(
|
|
struct bshell_lex_ctx *ctx,
|
|
enum bshell_lex_state_id type);
|
|
extern fx_string *lex_state_get_tempstr(struct bshell_lex_ctx *ctx);
|
|
extern void lex_state_add_terminator(
|
|
struct bshell_lex_state *state,
|
|
unsigned int tok);
|
|
extern bool lex_state_terminates_at_token(
|
|
struct bshell_lex_ctx *ctx,
|
|
unsigned int tok);
|
|
|
|
extern fx_wchar peek_char(struct bshell_lex_ctx *ctx);
|
|
extern fx_wchar peek_char_noread(struct bshell_lex_ctx *ctx);
|
|
extern fx_wchar peek2_char(struct bshell_lex_ctx *ctx);
|
|
extern fx_wchar peek2_char_noread(struct bshell_lex_ctx *ctx);
|
|
extern void advance_char(struct bshell_lex_ctx *ctx);
|
|
extern void advance_char_noread(struct bshell_lex_ctx *ctx);
|
|
|
|
extern bool string_is_valid_number(
|
|
const char *s,
|
|
fx_value *out,
|
|
enum bshell_lex_token_type *out_type);
|
|
extern bool convert_word_to_number(struct bshell_lex_token *tok);
|
|
extern bool convert_word_to_keyword(struct bshell_lex_token *tok);
|
|
extern bool convert_word_to_operator(
|
|
struct bshell_lex_ctx *ctx,
|
|
struct bshell_lex_token *tok);
|
|
|
|
extern void enqueue_token(
|
|
struct bshell_lex_ctx *ctx,
|
|
struct bshell_lex_token *tok);
|
|
extern void enqueue_token_with_coordinates(
|
|
struct bshell_lex_ctx *ctx,
|
|
struct bshell_lex_token *tok,
|
|
const struct bshell_char_cell *start,
|
|
const struct bshell_char_cell *end);
|
|
|
|
extern enum bshell_status read_word(
|
|
struct bshell_lex_ctx *ctx,
|
|
enum read_flags flags,
|
|
struct bshell_lex_token **out);
|
|
extern enum bshell_status read_symbol(
|
|
struct bshell_lex_ctx *ctx,
|
|
const struct bshell_lex_token_definition **out);
|
|
extern enum bshell_status read_literal_string(
|
|
struct bshell_lex_ctx *ctx,
|
|
struct bshell_lex_token **out);
|
|
extern enum bshell_status read_line_comment(struct bshell_lex_ctx *lex);
|
|
extern enum bshell_status read_var(
|
|
struct bshell_lex_ctx *ctx,
|
|
enum bshell_lex_token_type type,
|
|
struct bshell_lex_token **out);
|
|
extern enum bshell_status read_braced_var(
|
|
struct bshell_lex_ctx *ctx,
|
|
enum bshell_lex_token_type type,
|
|
struct bshell_lex_token **out);
|
|
|
|
extern enum bshell_status push_symbol(
|
|
struct bshell_lex_ctx *ctx,
|
|
enum bshell_lex_symbol sym);
|
|
|
|
extern bool char_can_begin_symbol(struct bshell_lex_ctx *ctx, char c);
|
|
extern bool char_can_begin_symbol_in_state(
|
|
struct bshell_lex_ctx *ctx,
|
|
char c,
|
|
enum bshell_lex_state_id state_type);
|
|
extern bool char_has_flags(
|
|
struct bshell_lex_ctx *ctx,
|
|
char c,
|
|
enum bshell_lex_token_flags flags);
|
|
extern bool keyword_has_flags(
|
|
struct bshell_lex_ctx *ctx,
|
|
enum bshell_lex_keyword kw,
|
|
enum bshell_lex_token_flags flags);
|
|
extern enum bshell_lex_token_flags keyword_get_flags(
|
|
struct bshell_lex_ctx *ctx,
|
|
enum bshell_lex_keyword kw);
|
|
extern bool symbol_has_flags(
|
|
struct bshell_lex_ctx *ctx,
|
|
enum bshell_lex_symbol sym,
|
|
enum bshell_lex_token_flags flags);
|
|
extern enum bshell_lex_token_flags symbol_get_flags(
|
|
struct bshell_lex_ctx *ctx,
|
|
enum bshell_lex_symbol sym);
|
|
extern enum bshell_lex_operator get_bshell_operator_with_string(
|
|
struct bshell_lex_ctx *ctx,
|
|
const char *s);
|
|
|
|
extern void handle_lex_state_transition(
|
|
struct bshell_lex_ctx *ctx,
|
|
unsigned int token);
|
|
|
|
#endif
|