mirror of https://github.com/arendst/Tasmota.git
180 lines
2.8 KiB
C
180 lines
2.8 KiB
C
|
// 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
|