mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-15 11:20:03 +00:00
226 lines
2.7 KiB
Text
226 lines
2.7 KiB
Text
%{
|
|
#include "grep.h"
|
|
%}
|
|
|
|
%union
|
|
{
|
|
int val;
|
|
char* str;
|
|
Re2 re;
|
|
}
|
|
|
|
%type <re> expr prog
|
|
%type <re> expr0 expr1 expr2 expr3 expr4
|
|
%token <str> LCLASS
|
|
%token <val> LCHAR
|
|
%token LLPAREN LRPAREN LALT LSTAR LPLUS LQUES
|
|
%token LBEGIN LEND LDOT LBAD LNEWLINE
|
|
%%
|
|
|
|
prog:
|
|
expr newlines
|
|
{
|
|
$$.beg = ral(Tend);
|
|
$$.end = $$.beg;
|
|
$$ = re2cat(re2star(re2or(re2char(0x00, '\n'-1), re2char('\n'+1, 0xff))), $$);
|
|
$$ = re2cat($1, $$);
|
|
$$ = re2cat(re2star(re2char(0x00, 0xff)), $$);
|
|
topre = $$;
|
|
}
|
|
|
|
expr:
|
|
expr0
|
|
| expr newlines expr0
|
|
{
|
|
$$ = re2or($1, $3);
|
|
}
|
|
|
|
expr0:
|
|
expr1
|
|
| LSTAR { literal = 1; } expr1
|
|
{
|
|
$$ = $3;
|
|
}
|
|
|
|
expr1:
|
|
expr2
|
|
| expr1 LALT expr2
|
|
{
|
|
$$ = re2or($1, $3);
|
|
}
|
|
|
|
expr2:
|
|
expr3
|
|
| expr2 expr3
|
|
{
|
|
$$ = re2cat($1, $2);
|
|
}
|
|
|
|
expr3:
|
|
expr4
|
|
| expr3 LSTAR
|
|
{
|
|
$$ = re2star($1);
|
|
}
|
|
| expr3 LPLUS
|
|
{
|
|
$$.beg = ral(Talt);
|
|
patchnext($1.end, $$.beg);
|
|
$$.beg->u.alt = $1.beg;
|
|
$$.end = $$.beg;
|
|
$$.beg = $1.beg;
|
|
}
|
|
| expr3 LQUES
|
|
{
|
|
$$.beg = ral(Talt);
|
|
$$.beg->u.alt = $1.beg;
|
|
$$.end = $1.end;
|
|
appendnext($$.end, $$.beg);
|
|
}
|
|
|
|
expr4:
|
|
LCHAR
|
|
{
|
|
$$.beg = ral(Tclass);
|
|
$$.beg->u.x.lo = $1;
|
|
$$.beg->u.x.hi = $1;
|
|
$$.end = $$.beg;
|
|
}
|
|
| LBEGIN
|
|
{
|
|
$$.beg = ral(Tbegin);
|
|
$$.end = $$.beg;
|
|
}
|
|
| LEND
|
|
{
|
|
$$.beg = ral(Tend);
|
|
$$.end = $$.beg;
|
|
}
|
|
| LDOT
|
|
{
|
|
$$ = re2class("^\n");
|
|
}
|
|
| LCLASS
|
|
{
|
|
$$ = re2class($1);
|
|
}
|
|
| LLPAREN expr1 LRPAREN
|
|
{
|
|
$$ = $2;
|
|
}
|
|
|
|
newlines:
|
|
LNEWLINE
|
|
| newlines LNEWLINE
|
|
%%
|
|
|
|
void
|
|
yyerror(char *e, ...)
|
|
{
|
|
if(filename)
|
|
fprint(2, "grep: %s:%ld: %s\n", filename, lineno, e);
|
|
else
|
|
fprint(2, "grep: %s\n", e);
|
|
exits("syntax");
|
|
}
|
|
|
|
int
|
|
yylex(void)
|
|
{
|
|
char *q, *eq;
|
|
int c, s;
|
|
|
|
if(peekc) {
|
|
s = peekc;
|
|
peekc = 0;
|
|
return s;
|
|
}
|
|
c = getrec();
|
|
if(literal) {
|
|
if(c != 0 && c != '\n') {
|
|
yylval.val = c;
|
|
return LCHAR;
|
|
}
|
|
literal = 0;
|
|
}
|
|
switch(c) {
|
|
default:
|
|
yylval.val = c;
|
|
s = LCHAR;
|
|
break;
|
|
case '\\':
|
|
c = getrec();
|
|
yylval.val = c;
|
|
s = LCHAR;
|
|
if(c == '\n')
|
|
s = LNEWLINE;
|
|
break;
|
|
case '[':
|
|
goto getclass;
|
|
case '(':
|
|
s = LLPAREN;
|
|
break;
|
|
case ')':
|
|
s = LRPAREN;
|
|
break;
|
|
case '|':
|
|
s = LALT;
|
|
break;
|
|
case '*':
|
|
s = LSTAR;
|
|
break;
|
|
case '+':
|
|
s = LPLUS;
|
|
break;
|
|
case '?':
|
|
s = LQUES;
|
|
break;
|
|
case '^':
|
|
s = LBEGIN;
|
|
break;
|
|
case '$':
|
|
s = LEND;
|
|
break;
|
|
case '.':
|
|
s = LDOT;
|
|
break;
|
|
case 0:
|
|
peekc = -1;
|
|
case '\n':
|
|
s = LNEWLINE;
|
|
break;
|
|
}
|
|
return s;
|
|
|
|
getclass:
|
|
q = u.string;
|
|
eq = q + nelem(u.string) - 5;
|
|
c = getrec();
|
|
if(c == '^') {
|
|
q[0] = '^';
|
|
q[1] = '\n';
|
|
q[2] = '-';
|
|
q[3] = '\n';
|
|
q += 4;
|
|
c = getrec();
|
|
}
|
|
for(;;) {
|
|
if(q >= eq)
|
|
error("class too long");
|
|
if(c == ']' || c == 0)
|
|
break;
|
|
if(c == '\\') {
|
|
*q++ = c;
|
|
c = getrec();
|
|
if(c == 0)
|
|
break;
|
|
}
|
|
*q++ = c;
|
|
c = getrec();
|
|
}
|
|
*q = 0;
|
|
if(c == 0)
|
|
return LBAD;
|
|
yylval.str = u.string;
|
|
return LCLASS;
|
|
}
|