Repository navigation
Open
Description
I'm trying to port a use of golang's https://golang.org/pkg/regexp/#Regexp.ReplaceAllString to tinygo, where
regexp doesn't work just yet. libfsm works nicely, i.e. I can use
re -l go -k str "ab"
to generate a nice matcher. But it isn't especially helpful for implementing ReplaceAllString, as it returns
neither the starting nor the ending index.
Returning starting and ending indices seems easy, e.g.
--- a/src/libfsm/print/go.c
+++ b/src/libfsm/print/go.c
@@ -92,14 +92,14 @@ print_end(FILE *f, const struct dfavm_op_ir *op, const struct fsm_options *opt,
enum dfavm_op_end end_bits, const struct ir *ir)
{
if (end_bits == VM_END_FAIL) {
- fprintf(f, "{\n\t\treturn -1\n\t}\n");
+ fprintf(f, "{\n\t\treturn -1, -1\n\t}\n");
return;
}
if (opt->endleaf != NULL) {
opt->endleaf(f, op->ir_state->end_ids, opt->endleaf_opaque);
} else {
- fprintf(f, "{\n\t\treturn %lu\n\t}\n", (unsigned long) (op->ir_state - ir->states));
+ fprintf(f, "{\n\t\treturn int(start_idx), int(idx+1)\n\t}");
}
}
@@ -175,6 +175,9 @@ fsm_print_gofrag(FILE *f, const struct ir *ir, const struct fsm_options *opt,
if (op->num_incoming > 0) {
print_label(f, op, opt);
fprintf(f, "\n");
+ if (op->index == 0) {
+ fprintf(f, "\tvar start_idx = idx + 1\n");
+ }
}
fprintf(f, "\t");
@@ -257,7 +260,7 @@ fsm_print_go(FILE *f, const struct fsm *fsm)
switch (fsm->opt->io) {
case FSM_IO_PAIR:
- fprintf(f, "(data []byte) int {\n");
+ fprintf(f, "(data []byte) (start, end int) {\n");
if (ir->n > 0) {
/* start idx at -1 unsigned so after first increment we're correct at index 0 */
fprintf(f, "\tvar idx = ^uint(0)\n");
@@ -266,7 +269,7 @@ fsm_print_go(FILE *f, const struct fsm *fsm)
break;
case FSM_IO_STR:
- fprintf(f, "(data string) int {\n");
+ fprintf(f, "(data string) (start, end int) {\n");
if (ir->n > 0) {
/* start idx at -1 unsigned so after first increment we're correct at index 0 */
fprintf(f, "\tvar idx = ^uint(0)\n");
and would let me implement a ReplaceAllString.
Is there an easier way? I feel like I haven't yet found the appropriate doc...
Metadata
Metadata
Assignees
Labels
No labels
Activity
dkegel-fastly commentedon Jun 2, 2021
Here's a demo of what I'm trying to do. Not quite happy yet...
Save that as main.go, then create match.go with something like
and run with
Currently, it outputs
Examining the generated code, fsm expands the quantifier a{2,3} to return immediately after the 2nd a, without even trying to consume a 3rd one.
(I filed #358 for that earlier, but may not have provided enough context.)
This is a fine optimization for detecting a match, so evidently my hack to return the end offset of the match is breaking an assumption libfsm made, and/or I'm misusing libfsm in some other way.
dhobsd commentedon Jun 2, 2021
dkegel-fastly commentedon Jun 2, 2021
Thanks. I updated the problem description to address your last suggestion about induced matches.
I'm not worried about the inefficiency of using string for the moment.
I am very interested in suggestions for coaxing libfsm into actually finishing the match of a{2,3} instead
of calling it a day after aa.