diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2022-04-30 15:23:02 -0400 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2022-04-30 15:23:02 -0400 |
| commit | 206e1fa68fb921d0fd8c9d31ec59a9b7d0fc2a5d (patch) | |
| tree | 916e508c47a30ed69c6e904479e642d12ec4d080 | |
| parent | 24ed834317f3fda8f0f55489f54a2df1aca5de17 (diff) | |
Added tagged definitions: `foo:: blah`
| -rw-r--r-- | Lua/lbp.c | 6 | ||||
| -rw-r--r-- | json.c | 3 | ||||
| -rw-r--r-- | match.c | 4 | ||||
| -rw-r--r-- | pattern.c | 10 | ||||
| -rw-r--r-- | pattern.h | 3 |
5 files changed, 21 insertions, 5 deletions
@@ -72,7 +72,11 @@ static void push_matchstring(lua_State *L, match_t *m) static void set_capture_fields(lua_State *L, match_t *m, int *n, const char *start) { - if (m->pat->type == BP_CAPTURE) { + if (m->pat->type == BP_TAGGED) { + lua_pushlstring(L, m->pat->args.capture.name, m->pat->args.capture.namelen); + lua_setfield(L, -2, "__tag"); + set_capture_fields(L, m->children[0], n, start); + } else if (m->pat->type == BP_CAPTURE) { if (m->pat->args.capture.namelen > 0) { lua_pushlstring(L, m->pat->args.capture.name, m->pat->args.capture.namelen); push_match(L, m->children[0], start); @@ -30,6 +30,9 @@ static int _json_match(const char *text, match_t *m, int comma, bool verbose) } printf("\",\"range\":[%ld,%ld]", m->start - text, m->end - text); + if (m->pat->type == BP_TAGGED) + printf(",\"tag\":\"%.*s\"", (int)m->pat->args.capture.namelen, m->pat->args.capture.name); + if (m->children && (verbose || m->pat->type != BP_REF)) { printf(",\"children\":["); for (int i = 0; m->children && m->children[i]; i++) @@ -256,7 +256,7 @@ static pat_t *get_prerequisite(match_ctx_t *ctx, pat_t *pat) if (p->args.repetitions.min == 0) return p; p = p->args.repetitions.repeat_pat; break; - case BP_CAPTURE: + case BP_CAPTURE: case BP_TAGGED: p = p->args.capture.capture_pat; break; case BP_CHAIN: { pat_t *f = p->args.multiple.first; @@ -538,7 +538,7 @@ static match_t *match(match_ctx_t *ctx, const char *str, pat_t *pat) match_t *after = match(ctx, str, pat->args.pat); return after ? new_match(pat, str, str, MATCHES(after)) : NULL; } - case BP_CAPTURE: { + case BP_CAPTURE: case BP_TAGGED: { match_t *p = match(ctx, str, pat->args.pat); return p ? new_match(pat, str, p->end, MATCHES(p)) : NULL; } @@ -210,6 +210,7 @@ static pat_t *_bp_definition(const char *start, const char *end) const char *str = after_name(start, end); size_t namelen = (size_t)(str - start); if (!matchchar(&str, ':', false, end)) return NULL; + bool is_tagged = matchchar(&str, ':', false, end); pat_t *def = bp_pattern_nl(str, end, false); if (!def) parse_err(str, end, "Could not parse this definition."); str = def->end; @@ -217,6 +218,13 @@ static pat_t *_bp_definition(const char *start, const char *end) pat_t *ret = new_pat(BP_DEFINITIONS, start, str, 0, -1); ret->args.def.name = start; ret->args.def.namelen = namelen; + if (is_tagged) { // `id:: foo` means define a rule named `id` that gives captures an `id` tag + pat_t *capture = new_pat(BP_TAGGED, def->start, def->end, def->min_matchlen, def->max_matchlen); + capture->args.capture.capture_pat = def; + capture->args.capture.name = start; + capture->args.capture.namelen = namelen; + def = capture; + } ret->args.def.meaning = def; ret->args.def.next_def = _bp_definition(after_spaces(str, true, end), end); if (ret->args.def.next_def) @@ -679,7 +687,7 @@ void delete_pat(pat_t **at_pat, bool recursive) case BP_REPLACE: delete_pat(&pat->args.replace.pat, true); break; - case BP_CAPTURE: + case BP_CAPTURE: case BP_TAGGED: delete_pat(&pat->args.capture.capture_pat, true); break; case BP_NOT: case BP_AFTER: case BP_BEFORE: @@ -35,7 +35,8 @@ enum pattype_e { BP_END_OF_LINE = 23, BP_WORD_BOUNDARY = 24, BP_DEFINITIONS = 25, - BP_LEFTRECURSION = 26, + BP_TAGGED = 26, + BP_LEFTRECURSION = 27, }; // |
