Extra errors in compound parse rule, and in project parser

This commit is contained in:
Allen Webster 2018-06-01 21:06:13 -07:00
parent 7699b37767
commit 10b7d139c7
6 changed files with 122 additions and 62 deletions

View File

@ -1463,7 +1463,7 @@ CUSTOM_DOC("Opens the 4coder colors and fonts selector menu.")
////////////////////////////////
CUSTOM_COMMAND_SIG(open_in_other)
CUSTOM_DOC("Switches to the next active panel and begins an open file dialogue.")
CUSTOM_DOC("Interactively opens a file in the other panel.")
{
change_active_panel(app);
interactive_open_or_new(app);

View File

@ -70,10 +70,10 @@ get_error_location(char *base, char *pos){
static String
config_stringize_errors(Partition *arena, Config *parsed){
String result = {0};
if (parsed->first_error != 0){
if (parsed->errors.first != 0){
result.str = push_array(arena, char, 0);
result.memory_size = partition_remaining(arena);
for (Config_Error *error = parsed->first_error;
for (Config_Error *error = parsed->errors.first;
error != 0;
error = error->next){
Error_Location location = get_error_location(parsed->data.str, error->pos);
@ -204,37 +204,48 @@ text_data_and_token_array_to_parse_data(Partition *arena, String file_name, Stri
return(config);
}
static Config_Error*
config_parser__push_error(Config_Parser *ctx){
Config_Error *error = push_array(ctx->arena, Config_Error, 1);
zdll_push_back(ctx->first_error, ctx->last_error, error);
error->file_name = ctx->file_name;
error->pos = ctx->data.str + ctx->token->start;
ctx->count_error += 1;
return(error);
}
// TODO(allen): Move to string library
static String
config_parser__begin_string(Config_Parser *ctx){
config_begin_string(Partition *arena){
String str;
str.str = push_array(ctx->arena, char, 0);
str.str = push_array(arena, char, 0);
str.size = 0;
str.memory_size = ctx->arena->max - ctx->arena->pos;
str.memory_size = arena->max - arena->pos;
return(str);
}
static void
config_parser__end_string(Config_Parser *ctx, String *str){
config_end_string(Partition *arena, String *str){
str->memory_size = str->size;
push_array(ctx->arena, char, str->size);
push_array(arena, char, str->size);
}
static Config_Error*
config_error_push(Partition *arena, Config_Error_List *list, String file_name, char *pos, char *error_text){
Config_Error *error = push_array(arena, Config_Error, 1);
zdll_push_back(list->first, list->last, error);
list->count += 1;
error->file_name = file_name;
error->pos = pos;
error->text = config_begin_string(arena);
append(&error->text, error_text);
config_end_string(arena, &error->text);
return(error);
}
static char*
config_parser__get_pos(Config_Parser *ctx){
return(ctx->data.str + ctx->token->start);
}
static void
config_parser__log_error_pos(Config_Parser *ctx, char *pos, char *error_text){
config_error_push(ctx->arena, &ctx->errors, ctx->file_name, pos, error_text);
}
static void
config_parser__log_error(Config_Parser *ctx, char *error_text){
Config_Error *error = config_parser__push_error(ctx);
error->text = config_parser__begin_string(ctx);
append(&error->text, error_text);
config_parser__end_string(ctx, &error->text);
config_parser__log_error_pos(ctx, config_parser__get_pos(ctx), error_text);
}
static Config*
@ -258,9 +269,8 @@ config_parser__config(Config_Parser *ctx){
config->first = first;
config->last = last;
config->count = count;
config->first_error = ctx->first_error;
config->last_error = ctx->last_error;
config->count_error = ctx->count_error;
config->errors = ctx->errors;
config->file_name = ctx->file_name;
config->data = ctx->data;
return(config);
}
@ -316,6 +326,8 @@ config_parser__version(Config_Parser *ctx){
static Config_Assignment*
config_parser__assignment(Config_Parser *ctx){
char *pos = config_parser__get_pos(ctx);
Config_LValue *l = config_parser__lvalue(ctx);
if (l == 0){
config_parser__log_error(ctx, "expected an l-value; l-value formats: 'identifier', 'identifier[#]'");
@ -349,6 +361,7 @@ config_parser__assignment(Config_Parser *ctx){
Config_Assignment *assignment = push_array(ctx->arena, Config_Assignment, 1);
memset(assignment, 0, sizeof(*assignment));
assignment->pos = pos;
assignment->l = l;
assignment->r = r;
return(assignment);
@ -449,6 +462,22 @@ config_parser__rvalue(Config_Parser *ctx){
return(0);
}
static void
config_parser__compound__check(Config_Parser *ctx, Config_Compound *compound){
bool32 implicit_index_allowed = true;
for (Config_Compound_Element *node = compound->first;
node != 0;
node = node->next){
if (node->l.type != ConfigLayoutType_Unset){
implicit_index_allowed = false;
}
else if (!implicit_index_allowed){
config_parser__log_error_pos(ctx, node->l.pos,
"encountered unlabeled member after one or more labeled members");
}
}
}
static Config_Compound*
config_parser__compound(Config_Parser *ctx){
Config_Compound_Element *first = 0;
@ -477,12 +506,14 @@ config_parser__compound(Config_Parser *ctx){
compound->first = first;
compound->last = last;
compound->count = count;
config_parser__compound__check(ctx, compound);
return(compound);
}
static Config_Compound_Element*
config_parser__element(Config_Parser *ctx){
Config_Layout layout = {0};
layout.pos = config_parser__get_pos(ctx);
if (config_parser__match_token(ctx, CPP_TOKEN_DOT)){
if (config_parser__recognize_token(ctx, CPP_TOKEN_IDENTIFIER)){
layout.type = ConfigLayoutType_Identifier;
@ -511,6 +542,13 @@ config_parser__element(Config_Parser *ctx){
////////////////////////////////
static Config_Error*
config_add_error(Partition *arena, Config *config, char *pos, char *error_text){
return(config_error_push(arena, &config->errors, config->file_name, pos, error_text));
}
////////////////////////////////
static Config_Assignment*
config_lookup_assignment(Config *config, String var_name, int32_t subscript){
Config_Assignment *assignment;
@ -540,6 +578,7 @@ config_evaluate_rvalue(Config *config, Config_Assignment *assignment, Config_RVa
}
else{
result.success = true;
result.pos = assignment->pos;
result.type = r->type;
switch (r->type){
case ConfigRValueType_Boolean:
@ -617,6 +656,7 @@ config_compound_member(Config *config, Config_Compound *compound, String var_nam
}
if (element_matches_query){
Config_Assignment dummy_assignment = {0};
dummy_assignment.pos = element->l.pos;
result = config_evaluate_rvalue(config, &dummy_assignment, element->r);
break;
}

View File

@ -24,6 +24,12 @@ struct Config_Error{
String text;
};
struct Config_Error_List{
Config_Error *first;
Config_Error *last;
int32_t count;
};
struct Config_Parser{
Cpp_Token *start;
Cpp_Token *token;
@ -34,9 +40,7 @@ struct Config_Parser{
Partition *arena;
Config_Error *first_error;
Config_Error *last_error;
int32_t count_error;
Config_Error_List errors;
};
struct Config_LValue{
@ -95,6 +99,7 @@ enum{
};
struct Config_Layout{
Config_Layout_Type type;
char *pos;
union{
String identifier;
int32_t integer;
@ -113,6 +118,7 @@ struct Config_Assignment{
Config_Assignment *next;
Config_Assignment *prev;
char *pos;
Config_LValue *l;
Config_RValue *r;
@ -125,10 +131,9 @@ struct Config{
Config_Assignment *last;
int32_t count;
Config_Error *first_error;
Config_Error *last_error;
int32_t count_error;
Config_Error_List errors;
String file_name;
String data;
};
@ -144,6 +149,7 @@ enum{
struct Config_Get_Result{
bool32 success;
Config_RValue_Type type;
char *pos;
union{
bool32 boolean;
int32_t integer;

View File

@ -232,7 +232,7 @@ static Command_Metadata fcoder_metacmd_table[196] = {
{ PROC_LINKS(clean_all_lines, 0), "clean_all_lines", 15, "Removes trailing whitespace from all lines in the current buffer.", 65, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 368 },
{ PROC_LINKS(click_set_cursor, 0), "click_set_cursor", 16, "Sets the cursor position to the mouse position.", 47, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 174 },
{ PROC_LINKS(click_set_mark, 0), "click_set_mark", 14, "Sets the mark position to the mouse position.", 45, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 187 },
{ PROC_LINKS(close_all_code, 0), "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 986 },
{ PROC_LINKS(close_all_code, 0), "close_all_code", 14, "Closes any buffer with a filename ending with an extension configured to be recognized as a code file type.", 107, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1000 },
{ PROC_LINKS(close_build_panel, 0), "close_build_panel", 17, "If the special build panel is open, closes it.", 46, "C:\\work\\4ed\\code\\4coder_build_commands.cpp", 46, 205 },
{ PROC_LINKS(close_panel, 0), "close_panel", 11, "Closes the currently active panel if it is not the only panel open.", 67, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 441 },
{ PROC_LINKS(copy, 0), "copy", 4, "Copy the text in the range from the cursor to the mark onto the clipboard.", 74, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 26 },
@ -298,7 +298,7 @@ static Command_Metadata fcoder_metacmd_table[196] = {
{ PROC_LINKS(list_all_locations_of_type_definition_of_identifier, 0), "list_all_locations_of_type_definition_of_identifier", 51, "Reads a token or word under the cursor and lists all locations of strings that appear to define a type whose name matches it.", 125, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 800 },
{ PROC_LINKS(list_all_substring_locations, 0), "list_all_substring_locations", 28, "Queries the user for a string and lists all case-sensitive substring matches found in all open buffers.", 103, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 747 },
{ PROC_LINKS(list_all_substring_locations_case_insensitive, 0), "list_all_substring_locations_case_insensitive", 45, "Queries the user for a string and lists all case-insensitive substring matches found in all open buffers.", 105, "C:\\work\\4ed\\code\\4coder_search.cpp", 38, 759 },
{ PROC_LINKS(load_project, 0), "load_project", 12, "Looks for a project.4coder file in the current directory and tries to load it. Looks in parent directories until a project file is found or there are no more parents.", 167, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1009 },
{ PROC_LINKS(load_project, 0), "load_project", 12, "Looks for a project.4coder file in the current directory and tries to load it. Looks in parent directories until a project file is found or there are no more parents.", 167, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1023 },
{ PROC_LINKS(make_directory_query, 0), "make_directory_query", 20, "Queries the user for a name and creates a new directory with the given name.", 76, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1101 },
{ PROC_LINKS(miblo_decrement_basic, 0), "miblo_decrement_basic", 21, "Decrement an integer under the cursor by one.", 45, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 110 },
{ PROC_LINKS(miblo_decrement_time_stamp, 0), "miblo_decrement_time_stamp", 26, "Decrement a time stamp under the cursor by one second. (format [m]m:ss or h:mm:ss", 81, "C:\\work\\4ed\\code\\4coder_miblo_numbers.cpp", 45, 383 },
@ -320,11 +320,11 @@ static Command_Metadata fcoder_metacmd_table[196] = {
{ PROC_LINKS(newline_or_goto_position_same_panel_direct, 0), "newline_or_goto_position_same_panel_direct", 42, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "C:\\work\\4ed\\code\\4coder_jump_direct.cpp", 43, 116 },
{ PROC_LINKS(newline_or_goto_position_same_panel_sticky, 0), "newline_or_goto_position_same_panel_sticky", 42, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor_same_panel.", 117, "C:\\work\\4ed\\code\\4coder_jump_sticky.cpp", 43, 571 },
{ PROC_LINKS(newline_or_goto_position_sticky, 0), "newline_or_goto_position_sticky", 31, "If the buffer in the active view is writable, inserts a character, otherwise performs goto_jump_at_cursor.", 106, "C:\\work\\4ed\\code\\4coder_jump_sticky.cpp", 43, 556 },
{ PROC_LINKS(open_all_code, 0), "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 993 },
{ PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1000 },
{ PROC_LINKS(open_all_code, 0), "open_all_code", 13, "Open all code in the current directory. File types are determined by extensions. An extension is considered code based on the extensions specified in 4coder.config.", 164, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1007 },
{ PROC_LINKS(open_all_code_recursive, 0), "open_all_code_recursive", 23, "Works as open_all_code but also runs in all subdirectories.", 59, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1014 },
{ PROC_LINKS(open_color_tweaker, 0), "open_color_tweaker", 18, "Opens the 4coder colors and fonts selector menu.", 48, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1457 },
{ PROC_LINKS(open_file_in_quotes, 0), "open_file_in_quotes", 19, "Reads a filename from surrounding '\"' characters and attempts to open the corresponding file.", 94, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1320 },
{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Switches to the next active panel and begins an open file dialogue.", 67, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1465 },
{ PROC_LINKS(open_in_other, 0), "open_in_other", 13, "Interactively opens a file in the other panel.", 46, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 1465 },
{ PROC_LINKS(open_long_braces, 0), "open_long_braces", 16, "At the cursor, insert a '{' and '}' separated by a blank line.", 62, "C:\\work\\4ed\\code\\4coder_combined_write_commands.cpp", 55, 58 },
{ PROC_LINKS(open_long_braces_break, 0), "open_long_braces_break", 22, "At the cursor, insert a '{' and '}break;' separated by a blank line.", 68, "C:\\work\\4ed\\code\\4coder_combined_write_commands.cpp", 55, 74 },
{ PROC_LINKS(open_long_braces_semicolon, 0), "open_long_braces_semicolon", 26, "At the cursor, insert a '{' and '};' separated by a blank line.", 63, "C:\\work\\4ed\\code\\4coder_combined_write_commands.cpp", 55, 66 },
@ -338,8 +338,8 @@ static Command_Metadata fcoder_metacmd_table[196] = {
{ PROC_LINKS(paste_next, 0), "paste_next", 10, "If the previous command was paste or paste_next, replaces the paste range with the next text down on the clipboard, otherwise operates as the paste command.", 156, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 84 },
{ PROC_LINKS(paste_next_and_indent, 0), "paste_next_and_indent", 21, "Paste the next item on the clipboard and run auto-indent on the newly pasted text.", 82, "C:\\work\\4ed\\code\\4coder_clipboard.cpp", 41, 135 },
{ PROC_LINKS(place_in_scope, 0), "place_in_scope", 14, "Wraps the code contained in the range between cursor and mark with a new curly brace scope.", 91, "C:\\work\\4ed\\code\\4coder_scope_commands.cpp", 46, 481 },
{ PROC_LINKS(project_fkey_command, 0), "project_fkey_command", 20, "Run an 'fkey command' configured in a project.4coder file. Determines the index of the 'fkey command' by which function key or numeric key was pressed to trigger the command.", 175, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1016 },
{ PROC_LINKS(project_go_to_root_directory, 0), "project_go_to_root_directory", 28, "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1041 },
{ PROC_LINKS(project_fkey_command, 0), "project_fkey_command", 20, "Run an 'fkey command' configured in a project.4coder file. Determines the index of the 'fkey command' by which function key or numeric key was pressed to trigger the command.", 175, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1030 },
{ PROC_LINKS(project_go_to_root_directory, 0), "project_go_to_root_directory", 28, "Changes 4coder's hot directory to the root directory of the currently loaded project. With no loaded project nothing hapepns.", 125, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1055 },
{ PROC_LINKS(query_replace, 0), "query_replace", 13, "Queries the user for two strings, and incrementally replaces every occurence of the first string with the second string.", 120, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 893 },
{ PROC_LINKS(query_replace_identifier, 0), "query_replace_identifier", 24, "Queries the user for a string, and incrementally replace every occurence of the word or token found at the cursor with the specified string.", 140, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 913 },
{ PROC_LINKS(query_replace_selection, 0), "query_replace_selection", 23, "Queries the user for a string, and incrementally replace every occurence of the string found in the selected range with the specified string.", 141, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 931 },
@ -381,10 +381,10 @@ static Command_Metadata fcoder_metacmd_table[196] = {
{ PROC_LINKS(set_bindings_default, 0), "set_bindings_default", 20, "Remap keybindings using the 'default' mapping rule.", 51, "C:\\work\\4ed\\code\\4coder_remapping_commands.cpp", 50, 61 },
{ PROC_LINKS(set_bindings_mac_default, 0), "set_bindings_mac_default", 24, "Remap keybindings using the 'mac-default' mapping rule.", 55, "C:\\work\\4ed\\code\\4coder_remapping_commands.cpp", 50, 75 },
{ PROC_LINKS(set_mark, 0), "set_mark", 8, "Sets the mark to the current position of the cursor.", 52, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 86 },
{ PROC_LINKS(setup_build_bat, 0), "setup_build_bat", 15, "Queries the user for several configuration options and initializes a new build batch script.", 92, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1426 },
{ PROC_LINKS(setup_build_bat_and_sh, 0), "setup_build_bat_and_sh", 22, "Queries the user for several configuration options and initializes a new build batch script.", 92, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1438 },
{ PROC_LINKS(setup_build_sh, 0), "setup_build_sh", 14, "Queries the user for several configuration options and initializes a new build shell script.", 92, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1432 },
{ PROC_LINKS(setup_new_project, 0), "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1419 },
{ PROC_LINKS(setup_build_bat, 0), "setup_build_bat", 15, "Queries the user for several configuration options and initializes a new build batch script.", 92, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1440 },
{ PROC_LINKS(setup_build_bat_and_sh, 0), "setup_build_bat_and_sh", 22, "Queries the user for several configuration options and initializes a new build batch script.", 92, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1452 },
{ PROC_LINKS(setup_build_sh, 0), "setup_build_sh", 14, "Queries the user for several configuration options and initializes a new build shell script.", 92, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1446 },
{ PROC_LINKS(setup_new_project, 0), "setup_new_project", 17, "Queries the user for several configuration options and initializes a new 4coder project with build scripts for every OS.", 120, "C:\\work\\4ed\\code\\4coder_project_commands.cpp", 48, 1433 },
{ PROC_LINKS(show_filebar, 0), "show_filebar", 12, "Sets the current view to show it's filebar.", 43, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 464 },
{ PROC_LINKS(show_scrollbar, 0), "show_scrollbar", 14, "Sets the current view to show it's scrollbar.", 45, "C:\\work\\4ed\\code\\4coder_base_commands.cpp", 45, 450 },
{ PROC_LINKS(snipe_token_or_word, 0), "snipe_token_or_word", 19, "Delete a single, whole token on or to the left of the cursor and post it to the clipboard.", 90, "C:\\work\\4ed\\code\\4coder_seek.cpp", 36, 1259 },

View File

@ -411,13 +411,16 @@ parse_project__config_data__version_1(Partition *arena, String root_dir, Config
for (Config_Get_Result_Node *node = list.first;
node != 0;
node = node->next, ++dst){
char *pos = node->result.pos;
Config_Compound *src = node->result.compound;
memset(dst, 0, sizeof(*dst));
bool32 can_emit_command = true;
Config_Compound *cmd_set = 0;
String name = {0};
Config_Get_Result cmd_result = {0};
Config_Compound *cmd_set = 0;
char *cmd_pos = 0;
String cmd_str = {0};
String out = {0};
bool32 footer_panel = false;
@ -426,11 +429,19 @@ parse_project__config_data__version_1(Partition *arena, String root_dir, Config
if (!config_compound_string_member(parsed, src, "name", 0, &name)){
can_emit_command = false;
config_add_error(arena, parsed, pos, "a command must have a string type name member");
goto finish_command;
}
if (!config_compound_compound_member(parsed, src, "cmd", 1, &cmd_set)){
cmd_result = config_compound_member(parsed, src,
make_lit_string("cmd"), 1);
if (cmd_result.success){
cmd_set = cmd_result.compound;
cmd_pos = cmd_result.pos;
}
else{
can_emit_command = false;
config_add_error(arena, parsed, pos, "a command must have an array type cmd member");
goto finish_command;
}
@ -464,7 +475,11 @@ parse_project__config_data__version_1(Partition *arena, String root_dir, Config
}
}
if (can_emit_command){
if (!can_emit_command){
config_add_error(arena, parsed, cmd_pos, "no usable command strings found in cmd");
goto finish_command;
}
config_compound_string_member(parsed, src, "out", 2, &out);
config_compound_bool_member(parsed, src, "footer_panel", 3, &footer_panel);
config_compound_bool_member(parsed, src, "save_dirty_files", 4,
@ -478,7 +493,6 @@ parse_project__config_data__version_1(Partition *arena, String root_dir, Config
dst->footer_panel = footer_panel;
dst->save_dirty_files = save_dirty_files;
dst->cursor_at_end = cursor_at_end;
}
finish_command:;
}