Tasmota/lib/libesp32/re1.5/compile.c

180 lines
2.8 KiB
C
Raw Normal View History

2021-11-25 21:57:37 +00:00
// Copyright 2007-2009 Russ Cox. All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#ifdef DEBUG
#include "re1.5.h"
static Inst *pc;
static int count(Regexp*);
static void emit(Regexp*);
Prog*
compile(Regexp *r)
{
int n;
Prog *p;
n = count(r) + 1;
p = mal(sizeof *p + n*sizeof p->start[0]);
p->start = (Inst*)(p+1);
pc = p->start;
emit(r);
pc->opcode = Match;
pc++;
p->len = pc - p->start;
return p;
}
// how many instructions does r need?
static int
count(Regexp *r)
{
switch(r->type) {
default:
re1_5_fatal("bad count");
case Alt:
return 2 + count(r->left) + count(r->right);
case Cat:
return count(r->left) + count(r->right);
case Lit:
case Dot:
return 1;
case Paren:
return 2 + count(r->left);
case Quest:
return 1 + count(r->left);
case Star:
return 2 + count(r->left);
case Plus:
return 1 + count(r->left);
}
}
static void
emit(Regexp *r)
{
Inst *p1, *p2, *t;
switch(r->type) {
default:
re1_5_fatal("bad emit");
case Alt:
pc->opcode = Split;
p1 = pc++;
p1->x = pc;
emit(r->left);
pc->opcode = Jmp;
p2 = pc++;
p1->y = pc;
emit(r->right);
p2->x = pc;
break;
case Cat:
emit(r->left);
emit(r->right);
break;
case Lit:
pc->opcode = Char;
pc->c = r->ch;
pc++;
break;
case Dot:
pc++->opcode = Any;
break;
case Paren:
pc->opcode = Save;
pc->n = 2*r->n;
pc++;
emit(r->left);
pc->opcode = Save;
pc->n = 2*r->n + 1;
pc++;
break;
case Quest:
pc->opcode = Split;
p1 = pc++;
p1->x = pc;
emit(r->left);
p1->y = pc;
if(r->n) { // non-greedy
t = p1->x;
p1->x = p1->y;
p1->y = t;
}
break;
case Star:
pc->opcode = Split;
p1 = pc++;
p1->x = pc;
emit(r->left);
pc->opcode = Jmp;
pc->x = p1;
pc++;
p1->y = pc;
if(r->n) { // non-greedy
t = p1->x;
p1->x = p1->y;
p1->y = t;
}
break;
case Plus:
p1 = pc;
emit(r->left);
pc->opcode = Split;
pc->x = p1;
p2 = pc;
pc++;
p2->y = pc;
if(r->n) { // non-greedy
t = p2->x;
p2->x = p2->y;
p2->y = t;
}
break;
}
}
void
printprog(Prog *p)
{
Inst *pc, *e;
pc = p->start;
e = p->start + p->len;
for(; pc < e; pc++) {
switch(pc->opcode) {
default:
re1_5_fatal("printprog");
case Split:
printf("%2d. split %d, %d\n", (int)(pc-p->start), (int)(pc->x-p->start), (int)(pc->y-p->start));
break;
case Jmp:
printf("%2d. jmp %d\n", (int)(pc-p->start), (int)(pc->x-p->start));
break;
case Char:
printf("%2d. char %c\n", (int)(pc-p->start), pc->c);
break;
case Any:
printf("%2d. any\n", (int)(pc-p->start));
break;
case Match:
printf("%2d. match\n", (int)(pc-p->start));
break;
case Save:
printf("%2d. save %d\n", (int)(pc-p->start), pc->n);
}
}
}
#endif //DEBUG