2013-12-09 13:54:06 +08:00
/**\file parse_constants.h
Constants used in the programmatic representation of fish code .
*/
# ifndef fish_parse_constants_h
# define fish_parse_constants_h
2014-03-26 11:13:33 +08:00
# include "config.h"
2013-12-09 13:54:06 +08:00
# define PARSE_ASSERT(a) assert(a)
# define PARSER_DIE() do { fprintf(stderr, "Parser dying!\n"); exit_without_destructors(-1); } while (0)
enum parse_token_type_t
{
token_type_invalid ,
// Non-terminal tokens
symbol_job_list ,
symbol_job ,
symbol_job_continuation ,
symbol_statement ,
symbol_block_statement ,
symbol_block_header ,
symbol_for_header ,
symbol_while_header ,
symbol_begin_header ,
symbol_function_header ,
symbol_if_statement ,
symbol_if_clause ,
symbol_else_clause ,
symbol_else_continuation ,
symbol_switch_statement ,
symbol_case_item_list ,
symbol_case_item ,
symbol_boolean_statement ,
symbol_decorated_statement ,
symbol_plain_statement ,
symbol_arguments_or_redirections_list ,
symbol_argument_or_redirection ,
symbol_argument_list ,
symbol_argument ,
symbol_redirection ,
symbol_optional_background ,
2014-01-15 17:40:40 +08:00
2013-12-12 10:34:28 +08:00
symbol_end_command ,
2013-12-09 13:54:06 +08:00
// Terminal types
parse_token_type_string ,
parse_token_type_pipe ,
parse_token_type_redirection ,
parse_token_type_background ,
parse_token_type_end ,
2014-01-15 17:40:40 +08:00
2013-12-27 06:52:15 +08:00
// Special terminal type that means no more tokens forthcoming
2013-12-09 13:54:06 +08:00
parse_token_type_terminate ,
// Very special terminal types that don't appear in the production list
parse_special_type_parse_error ,
parse_special_type_tokenizer_error ,
parse_special_type_comment ,
FIRST_TERMINAL_TYPE = parse_token_type_string ,
LAST_TERMINAL_TYPE = parse_token_type_terminate ,
LAST_TOKEN_OR_SYMBOL = parse_token_type_terminate ,
FIRST_PARSE_TOKEN_TYPE = parse_token_type_string
2014-03-26 11:06:34 +08:00
} __packed ;
2013-12-09 13:54:06 +08:00
enum parse_keyword_t
{
parse_keyword_none ,
parse_keyword_if ,
parse_keyword_else ,
parse_keyword_for ,
parse_keyword_in ,
parse_keyword_while ,
parse_keyword_begin ,
parse_keyword_function ,
parse_keyword_switch ,
parse_keyword_case ,
parse_keyword_end ,
parse_keyword_and ,
parse_keyword_or ,
parse_keyword_not ,
parse_keyword_command ,
parse_keyword_builtin ,
2014-02-14 02:08:04 +08:00
parse_keyword_exec ,
2014-01-15 17:40:40 +08:00
2014-03-18 23:50:27 +08:00
LAST_KEYWORD = parse_keyword_exec
2014-03-26 11:06:34 +08:00
} __packed ;
2013-12-09 13:54:06 +08:00
/* Statement decorations. This matches the order of productions in decorated_statement */
enum parse_statement_decoration_t
{
parse_statement_decoration_none ,
parse_statement_decoration_command ,
2014-02-14 02:08:04 +08:00
parse_statement_decoration_builtin ,
parse_statement_decoration_exec
2013-12-09 13:54:06 +08:00
} ;
/* Parse error code list */
enum parse_error_code_t
{
parse_error_none ,
2014-01-15 17:40:40 +08:00
2014-01-01 06:37:37 +08:00
/* Matching values from enum parser_error */
2013-12-13 10:18:07 +08:00
parse_error_syntax ,
parse_error_eval ,
parse_error_cmdsubst ,
2014-01-15 17:40:40 +08:00
2013-12-13 10:18:07 +08:00
parse_error_generic , // unclassified error types
2014-01-15 17:40:40 +08:00
2014-01-14 16:01:26 +08:00
//tokenizer errors
parse_error_tokenizer_unterminated_quote ,
parse_error_tokenizer_unterminated_subshell ,
parse_error_tokenizer_unterminated_escape ,
parse_error_tokenizer_other ,
2014-01-15 17:40:40 +08:00
2013-12-09 13:54:06 +08:00
parse_error_unbalancing_end , //end outside of block
parse_error_unbalancing_else , //else outside of if
parse_error_unbalancing_case , //case outside of switch
2014-01-15 17:40:40 +08:00
2014-01-13 18:24:11 +08:00
parse_error_double_pipe , // foo || bar, has special error message
parse_error_double_background // foo && bar, has special error message
2013-12-09 13:54:06 +08:00
} ;
2014-01-15 17:40:40 +08:00
enum
{
PARSER_TEST_ERROR = 1 ,
PARSER_TEST_INCOMPLETE = 2
2013-12-16 08:05:37 +08:00
} ;
typedef unsigned int parser_test_error_bits_t ;
2014-03-22 08:13:33 +08:00
struct parse_error_t
{
/** Text of the error */
wcstring text ;
/** Code for the error */
enum parse_error_code_t code ;
/** Offset and length of the token in the source code that triggered this error */
size_t source_start ;
size_t source_length ;
/** Return a string describing the error, suitable for presentation to the user. If skip_caret is false, the offending line with a caret is printed as well */
wcstring describe ( const wcstring & src ) const ;
/** Return a string describing the error, suitable for presentation to the user, with the given prefix. If skip_caret is false, the offending line with a caret is printed as well */
wcstring describe_with_prefix ( const wcstring & src , const wcstring & prefix , bool is_interactive , bool skip_caret ) const ;
} ;
typedef std : : vector < parse_error_t > parse_error_list_t ;
/* Special source_start value that means unknown */
# define SOURCE_LOCATION_UNKNOWN (static_cast<size_t>(-1))
/* Helper function to offset error positions by the given amount. This is used when determining errors in a substring of a larger source buffer. */
void parse_error_offset_source_start ( parse_error_list_t * errors , size_t amt ) ;
2013-12-16 08:05:37 +08:00
2014-01-02 07:29:56 +08:00
/** Maximum number of function calls. */
# define FISH_MAX_STACK_DEPTH 128
2013-12-09 13:54:06 +08:00
2014-01-02 07:29:56 +08:00
/** Error message on a function that calls itself immediately */
# define INFINITE_FUNC_RECURSION_ERR_MSG _( L"The function '%ls' calls itself immediately, which would result in an infinite loop.")
/** Error message on reaching maximum call stack depth */
# define CALL_STACK_LIMIT_EXCEEDED_ERR_MSG _( L"The function call stack limit has been exceeded. Do you have an accidental infinite loop?")
2013-12-09 13:54:06 +08:00
2014-01-13 19:57:59 +08:00
/** Error message when a non-string token is found when expecting a command name */
2014-01-13 18:24:11 +08:00
# define CMD_OR_ERR_MSG _( L"Expected a command, but instead found a pipe. Did you mean 'COMMAND; or COMMAND'? See the help section for the 'or' builtin command by typing 'help or'.")
2013-12-09 13:54:06 +08:00
2014-01-13 19:57:59 +08:00
/** Error message when a non-string token is found when expecting a command name */
2014-01-13 18:24:11 +08:00
# define CMD_AND_ERR_MSG _( L"Expected a command, but instead found a '&'. Did you mean 'COMMAND; and COMMAND'? See the help section for the 'and' builtin command by typing 'help and'.")
2013-12-09 13:54:06 +08:00
2014-01-13 19:57:59 +08:00
/** Error message when encountering an illegal command name */
2013-12-09 13:54:06 +08:00
# define ILLEGAL_CMD_ERR_MSG _( L"Illegal command name '%ls'")
2014-02-22 10:20:51 +08:00
/** Error message when encountering a failed expansion, e.g. for the variable name in for loops */
# define FAILED_EXPANSION_VARIABLE_NAME_ERR_MSG _( L"Unable to expand variable name '%ls'")
2014-01-13 19:57:59 +08:00
/** Error message when encountering an illegal file descriptor */
# define ILLEGAL_FD_ERR_MSG _( L"Illegal file descriptor in redirection '%ls'")
2013-12-09 13:54:06 +08:00
2014-01-13 19:57:59 +08:00
/** Error message for wildcards with no matches */
2013-12-09 13:54:06 +08:00
# define WILDCARD_ERR_MSG _( L"No matches for wildcard '%ls'.")
2013-12-17 08:52:23 +08:00
/** Error when using break outside of loop */
# define INVALID_BREAK_ERR_MSG _( L"break command while not inside of loop" )
2013-12-09 13:54:06 +08:00
2013-12-17 08:52:23 +08:00
/** Error when using continue outside of loop */
# define INVALID_CONTINUE_ERR_MSG _( L"continue command while not inside of loop" )
/** Error when using return builtin outside of function definition */
2013-12-09 13:54:06 +08:00
# define INVALID_RETURN_ERR_MSG _( L"'return' builtin command outside of function definition" )
2014-01-13 19:57:59 +08:00
/** Error message for Posix-style assignment: foo=bar */
2013-12-09 13:54:06 +08:00
# define COMMAND_ASSIGN_ERR_MSG _( L"Unknown command '%ls'. Did you mean 'set %ls %ls'? See the help section on the set command by typing 'help set'.")
2014-03-04 18:53:34 +08:00
/**
Error issued on invalid variable name
*/
# define COMPLETE_VAR_DESC _( L"The '$' character begins a variable name. The character '%lc', which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on $ ?
*/
# define COMPLETE_YOU_WANT_STATUS _( L"$? is not a valid variable in fish. If you want the exit status of the last command, try $status.")
/**
Error issued on invalid variable name
*/
# define COMPLETE_VAR_NULL_DESC _( L"The '$' begins a variable name. It was given at the end of an argument. Variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
# define COMPLETE_VAR_BRACKET_DESC _( L"Did you mean %ls{$%ls}%ls? The '$' character begins a variable name. A bracket, which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'." )
/**
Error issued on invalid variable name
*/
# define COMPLETE_VAR_PARAN_DESC _( L"Did you mean (COMMAND)? In fish, the '$' character is only used for accessing variables. To learn more about command substitution in fish, type 'help expand-command-substitution'.")
2013-12-09 13:54:06 +08:00
/**
While block description
*/
# define WHILE_BLOCK N_( L"'while' block" )
/**
For block description
*/
# define FOR_BLOCK N_( L"'for' block" )
/**
Breakpoint block
*/
# define BREAKPOINT_BLOCK N_( L"Block created by breakpoint" )
/**
If block description
*/
# define IF_BLOCK N_( L"'if' conditional block" )
/**
Function definition block description
*/
# define FUNCTION_DEF_BLOCK N_( L"function definition block" )
/**
Function invocation block description
*/
# define FUNCTION_CALL_BLOCK N_( L"function invocation block" )
/**
Function invocation block description
*/
# define FUNCTION_CALL_NO_SHADOW_BLOCK N_( L"function invocation block with no variable shadowing" )
/**
Switch block description
*/
# define SWITCH_BLOCK N_( L"'switch' block" )
/**
Fake block description
*/
# define FAKE_BLOCK N_( L"unexecutable block" )
/**
Top block description
*/
# define TOP_BLOCK N_( L"global root block" )
/**
Command substitution block description
*/
# define SUBST_BLOCK N_( L"command substitution block" )
/**
Begin block description
*/
# define BEGIN_BLOCK N_( L"'begin' unconditional block" )
/**
Source block description
*/
# define SOURCE_BLOCK N_( L"Block created by the . builtin" )
/**
Source block description
*/
# define EVENT_BLOCK N_( L"event handler block" )
/**
Unknown block description
*/
# define UNKNOWN_BLOCK N_( L"unknown / invalid block" )
# endif