Skip to content

Commit

Permalink
Add an initial naked grammar dump to use at https://www.bottlecaps.de…
Browse files Browse the repository at this point in the history
…/convert/ and https://www.bottlecaps.de/rr/ui to have a railroad diagram with a command like:

../cli parse -n -G ../tests/peppa.peg -e grammar abnf.peg
  • Loading branch information
mingodad committed Dec 14, 2021
1 parent 631174b commit d8e43ed
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 4 deletions.
114 changes: 114 additions & 0 deletions peppa.c
Original file line number Diff line number Diff line change
Expand Up @@ -2728,6 +2728,120 @@ P4_TxtSourceAst(FILE* stream, P4_Node* node, int depth) {
}
}

P4_PUBLIC void
P4_NakedSourceAst(FILE* stream, P4_Node* node, int depth, const char *sep) {
P4_size_t child_count, sep_count = 0;
P4_ConstString rule_name;
P4_Node *tmp_node = node;
while (tmp_node) {
P4_String node_string = P4_CopyNodeString(tmp_node);
rule_name = tmp_node->rule_name;
if(strcmp(rule_name, "choice") == 0) {
fprintf(stream, "%s", (sep_count++ ? sep : ""));
child_count = P4_GetNodeChildrenCount(tmp_node);
if(depth && child_count > 1) fprintf(stream, " ( ");
P4_NakedSourceAst(stream, tmp_node->head, depth+1, " / ");
if(depth && child_count > 1) fprintf(stream, " )");
}
else if(strcmp(rule_name, "cut") == 0) {
fprintf(stream, " /*%s*/", node_string);
}
else if(strcmp(rule_name, "decorator") == 0) {
fprintf(stream, "/*%s*/ ", node_string);
}
else if(strcmp(rule_name, "decorators") == 0) {
P4_NakedSourceAst(stream, tmp_node->head, 0, " ");
}
else if(strcmp(rule_name, "dot") == 0) {
fprintf(stream, ".");
}
else if(strcmp(rule_name, "grammar") == 0) {
P4_NakedSourceAst(stream, tmp_node->head, 0, " ");
}
else if(strcmp(rule_name, "back_reference") == 0
|| strcmp(rule_name, "insensitive") == 0
|| strcmp(rule_name, "char") == 0
|| strcmp(rule_name, "reference") == 0
|| strcmp(rule_name, "number") == 0
|| strcmp(rule_name, "literal") == 0) {
fprintf(stream, "%s%s", (sep_count++ ? sep : ""), node_string);
}
else if(strcmp(rule_name, "left_recursion") == 0) {
P4_FREE(node_string);
node_string = P4_CopyNodeString(tmp_node->head);
fprintf(stream, "%s%s /*|*/ / ", (sep_count++ ? sep : ""), node_string);
P4_NakedSourceAst(stream, tmp_node->head->next, depth+1, " ");
}
else if(strcmp(rule_name, "name") == 0) {
fprintf(stream, "%s =\n\t", node_string);
sep_count = 0;
}
else if(strcmp(rule_name, "negative") == 0) {
fprintf(stream, "%s!", (sep_count++ ? sep : ""));
P4_NakedSourceAst(stream, tmp_node->head, depth+1, sep);
}
else if(strcmp(rule_name, "positive") == 0) {
fprintf(stream, "%s&", (sep_count++ ? sep : ""));
P4_NakedSourceAst(stream, tmp_node->head, depth+1, sep);
}
else if(strcmp(rule_name, "range") == 0) {
fprintf(stream, "%s[", (sep_count++ ? sep : ""));
P4_NakedSourceAst(stream, tmp_node->head, depth+1, "-");
fprintf(stream, "]");
}
else if(strcmp(rule_name, "range_category") == 0) {
fprintf(stream, "\\p{%s}", node_string);
}
else if(strcmp(rule_name, "repeat") == 0) {
fprintf(stream, "%s", (sep_count++ ? sep : ""));
P4_NakedSourceAst(stream, tmp_node->head, depth+1, " ");
}
else if(strcmp(rule_name, "rule") == 0) {
fprintf(stream, "\n");
P4_NakedSourceAst(stream, tmp_node->head, depth+1, " ");
fprintf(stream, " ;");
}
else if(strcmp(rule_name, "sequence") == 0) {
fprintf(stream, "%s", (sep_count++ ? sep : ""));
child_count = P4_GetNodeChildrenCount(tmp_node);
if(depth && child_count > 1) fprintf(stream, " ( ");
P4_NakedSourceAst(stream, tmp_node->head, depth+1, " ");
if(depth && child_count > 1) fprintf(stream, " )");
}
else if(strcmp(rule_name, "onceormore") == 0) { fprintf(stream, "+ "); }
else if(strcmp(rule_name, "zeroormore") == 0) { fprintf(stream, "* "); }
else if(strcmp(rule_name, "zerooronce") == 0) { fprintf(stream, "? "); }
else if(strcmp(rule_name, "repeatexact") == 0) {
fprintf(stream, "{");
P4_NakedSourceAst(stream, tmp_node->head, depth+1, " ");
fprintf(stream, "} ");
}
else if(strcmp(rule_name, "repeatmin") == 0) {
fprintf(stream, "{");
P4_NakedSourceAst(stream, tmp_node->head, depth+1, " ");
fprintf(stream, ",} ");
}
else if(strcmp(rule_name, "repeatmax") == 0) {
fprintf(stream, "{,");
P4_NakedSourceAst(stream, tmp_node->head, depth+1, " ");
fprintf(stream, "} ");
}
else if(strcmp(rule_name, "repeatminmax") == 0) {
fprintf(stream, "{");
P4_NakedSourceAst(stream, tmp_node->head, depth+1, ",");
fprintf(stream, "} ");
}
else {
P4_FREE(node_string);
fprintf(stream, "\n\n***Unknown rule name: %s\n", rule_name);
return;
}
tmp_node = tmp_node->next;
P4_FREE(node_string);
}
if(depth == 0)
fprintf(stream, "\n");
}

P4_PUBLIC P4_Error
P4_InspectSourceAst(P4_Node* node, void* userdata, P4_Error (*inspector)(P4_Node*, void*)) {
Expand Down
7 changes: 4 additions & 3 deletions peppa.h
Original file line number Diff line number Diff line change
Expand Up @@ -1578,9 +1578,10 @@ P4_size_t P4_GetSourcePosition(P4_Source* source);
* P4_Node* root = P4_GetSourceAst(source);
* P4_JsonifySourceAst(stdout, root);
*/
void P4_JsonifySourceAst(FILE* stream, P4_Node* node, P4_Formatter formatter);
void P4_Jsonify2SourceAst(FILE* stream, P4_Node* node, P4_Formatter formatter);
void P4_TxtSourceAst(FILE* stream, P4_Node* node, int depth);
void P4_JsonifySourceAst(FILE* stream, P4_Node* node, P4_Formatter formatter);
void P4_Jsonify2SourceAst(FILE* stream, P4_Node* node, P4_Formatter formatter);
void P4_TxtSourceAst(FILE* stream, P4_Node* node, int depth);
void P4_NakedSourceAst(FILE* stream, P4_Node* node, int depth, const char *sep);

/**
* @brief Inspect the node tree.
Expand Down
10 changes: 9 additions & 1 deletion shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct p4_args_t {
bool json;
bool json2;
bool text;
bool naked;
bool debug;
};

Expand All @@ -78,6 +79,7 @@ static int subcommand_usage(const char* name) {
#endif
" --json/-j\t\tjson ast output\n"
" --json2/-J\t\tjson ast output with only arrays\n"
" --naked/-n\t\tdump naked grammar\n"
" --text/-t\t\ttext ast output [default]\n"
" --quiet/-q\t\tno ast output\n"
"\n"
Expand Down Expand Up @@ -130,6 +132,8 @@ static int print_ast(
P4_Jsonify2SourceAst(stdout, root, 0);
else if(args->json)
P4_JsonifySourceAst(stdout, root, 0);
else if(args->naked)
P4_NakedSourceAst(stdout, root, 0, " ");
else
P4_TxtSourceAst(stdout, root, 0);
fprintf(stdout, "\n");
Expand All @@ -152,6 +156,7 @@ int init_args(p4_args_t* args, int argc, char* argv[]) {
{"quiet", no_argument, 0, 'q'},
{"json", no_argument, 0, 'j'},
{"json2", no_argument, 0, 'J'},
{"naked", no_argument, 0, 'n'},
{"text", no_argument, 0, 't'},
{"debug", no_argument, 0, 'd'},
{"grammar-entry", required_argument, 0, 'e'},
Expand All @@ -160,7 +165,7 @@ int init_args(p4_args_t* args, int argc, char* argv[]) {
{0, 0, 0, 0}
};
int option_index = 0;
c = getopt_long (argc, argv, "VhqjJtde:g:G:", long_options, &option_index);
c = getopt_long (argc, argv, "VhqjJntde:g:G:", long_options, &option_index);
if (c == -1) break;
switch (c) {
case 0:
Expand All @@ -183,6 +188,9 @@ int init_args(p4_args_t* args, int argc, char* argv[]) {
case 'J':
args->json2 = true;
break;
case 'n':
args->naked = true;
break;
case 't':
args->text = true;
break;
Expand Down

0 comments on commit d8e43ed

Please sign in to comment.