diff --git a/tests/grammar.c b/tests/grammar.c index c878d87..b561cf4 100644 --- a/tests/grammar.c +++ b/tests/grammar.c @@ -144,9 +144,10 @@ static void PrintRule(MD_Node *rule) typedef enum OperationFlags OperationFlags; enum OperationFlags { - OperationFlag_Fill = 1<<0, - OperationFlag_Markup = 1<<1, - OperationFlag_Tag = 1<<2, + OperationFlag_Fill = 1<<0, + OperationFlag_Markup = 1<<1, + OperationFlag_Tag = 1<<2, + OperationFlag_PreComment = 1<<3, }; static void Extend(MD_String8 *s, char c) @@ -160,6 +161,7 @@ static void ExpandProduction(MD_Node *production, MD_String8List *out, MD_Node * static void ExpandRule(MD_Node *rule, MD_String8List *out_strings, MD_Node *cur_node, OperationFlags op_flags, MD_u32 max_depth, MD_u32 depth) { + MD_String8 pre_comment = {0}; for(MD_EachNode(rule_element, rule->first_child)) { MD_b32 expand = 1; @@ -179,6 +181,8 @@ static void ExpandRule(MD_Node *rule, MD_String8List *out_strings, MD_Node *cur_ if(expand) { MD_Node *node_to_tag = 0; + MD_Node *node_to_precomment = 0; + MD_String8 precomment = {0}; OperationFlags old_op_flags = op_flags; for(MD_EachNode(tag_node, rule_element->first_tag)){ if(MD_StringMatch(tag_node->string, MD_S8Lit("child"), 0)) @@ -205,6 +209,12 @@ static void ExpandRule(MD_Node *rule, MD_String8List *out_strings, MD_Node *cur_ { op_flags |= OperationFlag_Markup; } + else if(MD_StringMatch(tag_node->string, MD_S8Lit("pre_comment"), 0)) + { + op_flags |= OperationFlag_PreComment; + node_to_precomment = cur_node; + cur_node = NewChild(0); // NOTE(mal): Only used to store the comment, won't be linked as a node + } else if(MD_StringMatch(tag_node->string, MD_S8Lit(OPTIONAL_TAG), 0)) { } @@ -264,6 +274,12 @@ static void ExpandRule(MD_Node *rule, MD_String8List *out_strings, MD_Node *cur_ cur_node = node_to_tag; } + if(node_to_precomment) + { + node_to_precomment->comment_before = cur_node->string; + cur_node = node_to_precomment; + } + op_flags = old_op_flags; } } @@ -363,6 +379,7 @@ static MD_b32 EqualTrees(MD_Node *a, MD_Node *b) MD_StringMatch(a->whole_string, b->whole_string, 0)); result &= EqualList(a->first_tag, b->first_tag); result &= EqualList(a->first_child, b->first_child); + result &= MD_StringMatch(a->comment_before, b->comment_before, 0); return result; } diff --git a/tests/grammar.md b/tests/grammar.md index 39ede76..eb74beb 100644 --- a/tests/grammar.md +++ b/tests/grammar.md @@ -88,13 +88,53 @@ // digit : '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' //// General labels +//file : general_set +//general_set : { [@child set] | [@child uns_set] } +//set : {[tag_list] untagged_set} +//uns_set : {[tag_list] untagged_uns_set} +//tag_list : '@' @tag tag ' ' [tag_list] +//tag : @fill id['(' general_set ')'] +//untagged_set : @fill label | untagged_set [sep1 @sibling set] | scoped_set | untagged_uns_set sep2 @sibling set +//untagged_uns_set: @fill label [uns_set_tail] +//uns_set_tail : ':' @child uns_set | ' ' @sibling uns_set | ':' scoped_set | ' ' @sibling scoped_set +//scoped_set : '{' general_set '}' | alt_scope_beg general_set alt_scope_end +//alt_scope_beg : '(' | '[' +//alt_scope_end : ')' | ']' +//sep1 : ' ' | '\n' | ',' | ';' +//sep2 : '\n'| ',' | ';' +//id : alpha [alphanumeric] | '_' [alphanumeric] +//alphanumeric : alpha [alphanumeric] | digit [alphanumeric] | '_' [alphanumeric] +//alpha : lowercase | uppercase +//lowercase : 'a'|'b'|'c'|'d'|'e'|'f'|'g'|'h'|'i'|'j'|'k'|'l'|'m'|'n'|'o'|'p'|'q'|'r'|'s'|'t'|'u'|'v'|'w'|'z'|'y'|'z' +//uppercase : 'A'|'B'|'C'|'D'|'E'|'F'|'G'|'H'|'I'|'J'|'K'|'L'|'M'|'N'|'O'|'P'|'Q'|'R'|'S'|'T'|'U'|'V'|'W'|'Z'|'Y'|'Z' +//digit : '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' +//label : id | integer_literal | char_literal | string_literal | symbol_label +//integer_literal : { ['-'] natural_literal } +//natural_literal : digit [natural_literal] +//char_literal : @markup '\'' [char_literal_items] @markup '\'' +//char_literal_items : char_literal_item [char_literal_items] +//char_literal_item : ascii_no_backslash_no_quotes | '"' | '\\' ascii +//ascii : ascii_no_backslash_no_quotes | '\'' | '"' | '`' | '\\' +//ascii_no_backslash_no_quotes : digit | alpha | symbol_no_backslash_no_quotes | ' ' +//symbol_no_backslash_no_quotes : symbol_no_backslash_no_quotes_1 | symbol_no_backslash_no_quotes_2 +//symbol_no_backslash_no_quotes_1 : '!'|'#'|'$'|'%'|'&'|'('|')'|'*'|'+'|','|'-'|'.'|'/'|':' +//symbol_no_backslash_no_quotes_2 : ';'|'<'|'='|'>'|'?'|'@'|'['|']'|'^'|'_'|'{'|'|'|'}'|'~' +//string_literal : @markup '"' [string_literal_items] @markup '"' | @markup '`' [string_literal_items] @markup '`' +//string_literal_items : string_literal_item [string_literal_items] +//string_literal_item : ascii_no_backslash_no_quotes | '\'' | '\\' ascii +//symbol_label : '~'|'!'|'%'|'^'|'&'|'*'|'+'|'-'|'/'|'|'|'<'|'>'|'$'|'='|'.'|'?'|'$' + +//// Comments before file : general_set general_set : { [@child set] | [@child uns_set] } -set : {[tag_list] untagged_set} +set : {[tag_list] ['\n' @pre_comment pre_comment] untagged_set} +pre_comment : '/' '/' [' '] [@fill c_code_content] '\n' | '/' '*' [@fill c_code_content] '*' '/' +c_code_content : 'c''o''m''m''e''n''t' // TODO: Arbitrary strings, including C-style comments, as long as /* */ pairs are balanced +cpp_code_content: 'c''o''m''m''e''n''t' // TODO: Arbitrary strings that don't start with space uns_set : {[tag_list] untagged_uns_set} tag_list : '@' @tag tag ' ' [tag_list] tag : @fill id['(' general_set ')'] -untagged_set : @fill label | set [sep1 @sibling set] | scoped_set | uns_set sep2 @sibling set +untagged_set : @fill label | untagged_set [sep1 @sibling set] | scoped_set | untagged_uns_set sep2 @sibling set untagged_uns_set: @fill label [uns_set_tail] uns_set_tail : ':' @child uns_set | ' ' @sibling uns_set | ':' scoped_set | ' ' @sibling scoped_set scoped_set : '{' general_set '}' | alt_scope_beg general_set alt_scope_end