#ifndef PARSE_LEX_INTERNAL_H_ #define PARSE_LEX_INTERNAL_H_ #include #include #include 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, bool no_preserve_root); 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