Better JSON printing and fixed issue with numbered captures

This commit is contained in:
Bruce Hill 2022-10-23 00:15:49 -04:00
parent 23c64e386c
commit 5db008dbd2
3 changed files with 54 additions and 20 deletions

51
json.c
View File

@ -16,24 +16,47 @@ static int _json_match(const char *text, match_t *m, int comma, bool verbose);
//
static int _json_match(const char *text, match_t *m, int comma, bool verbose)
{
if (!verbose && m->pat->type != BP_TAGGED) {
if (m->children) {
for (int i = 0; m->children && m->children[i]; i++)
comma |= _json_match(text, m->children[i], comma, verbose);
}
return comma;
}
if (comma) printf(",\n");
comma = 0;
printf("{\"rule\":\"");
for (const char *c = m->pat->start; c < m->pat->end; c++) {
switch (*c) {
case '"': printf("\\\""); break;
case '\\': printf("\\\\"); break;
case '\t': printf("\\t"); break;
case '\n': printf(""); break;
default: printf("%c", *c); break;
}
}
printf("\",\"range\":[%ld,%ld]", m->start - text, m->end - text);
printf("{");
if (m->pat->type == BP_TAGGED)
printf(",\"tag\":\"%.*s\"", (int)m->pat->args.capture.namelen, m->pat->args.capture.name);
printf("\"tag\":\"%.*s\"", (int)m->pat->args.capture.namelen, m->pat->args.capture.name);
if (verbose) {
printf(",\"rule\":\"");
for (const char *c = m->pat->start; c < m->pat->end; c++) {
switch (*c) {
case '"': printf("\\\""); break;
case '\\': printf("\\\\"); break;
case '\t': printf("\\t"); break;
case '\n': printf(""); break;
default: printf("%c", *c); break;
}
}
printf("\",");
printf("\"range\":[%ld,%ld]", m->start - text, m->end - text);
} else {
printf(",\"text\":\"");
for (const char *c = m->start; c < m->end; c++) {
switch (*c) {
case '"': printf("\\\""); break;
case '\\': printf("\\\\"); break;
case '\t': printf("\\t"); break;
case '\n': printf(""); break;
default: printf("%c", *c); break;
}
}
printf("\"");
}
if (m->children && (verbose || m->pat->type != BP_REF)) {
if (m->children) {
printf(",\"children\":[");
for (int i = 0; m->children && m->children[i]; i++)
comma |= _json_match(text, m->children[i], comma, verbose);

21
match.c
View File

@ -886,10 +886,13 @@ bool next_match_safe(match_t **m, const char *start, const char *end, pat_t *pat
__attribute__((nonnull))
static match_t *_get_numbered_capture(match_t *m, int *n)
{
if (*n == 0) return m;
if (m->pat->type == BP_CAPTURE && m->pat->args.capture.namelen == 0) {
if (m->pat->type == BP_CAPTURE && m->pat->args.capture.namelen > 0)
return NULL;
if ((m->pat->type == BP_CAPTURE && m->pat->args.capture.namelen == 0) || m->pat->type == BP_TAGGED) {
if (*n == 1) return m;
--(*n);
else return NULL;
// --(*n);
}
if (m->children) {
for (int i = 0; m->children[i]; i++) {
@ -905,14 +908,22 @@ static match_t *_get_numbered_capture(match_t *m, int *n)
//
match_t *get_numbered_capture(match_t *m, int n)
{
return _get_numbered_capture(m, &n);
if (n <= 0) return m;
if (m->children) {
for (int i = 0; m->children[i]; i++) {
match_t *cap = _get_numbered_capture(m->children[i], &n);
if (cap) return cap;
}
}
return NULL;
}
//
// Get a capture with a specific name.
//
match_t *get_named_capture(match_t *m, const char *name, size_t namelen)
match_t *get_named_capture(match_t *m, const char *name, ssize_t _namelen)
{
size_t namelen = _namelen < 0 ? strlen(name) : (size_t)_namelen;
if (m->pat->type == BP_CAPTURE && m->pat->args.capture.name
&& m->pat->args.capture.namelen == namelen
&& strncmp(m->pat->args.capture.name, name, m->pat->args.capture.namelen) == 0)

View File

@ -37,7 +37,7 @@ bool next_match_safe(match_t **m, const char *start, const char *end, pat_t *pat
__attribute__((nonnull))
match_t *get_numbered_capture(match_t *m, int n);
__attribute__((nonnull, pure))
match_t *get_named_capture(match_t *m, const char *name, size_t namelen);
match_t *get_named_capture(match_t *m, const char *name, ssize_t namelen);
#endif
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1,\:0