Skip to content

Commit

Permalink
implemented and documented "between" operator to match integer values…
Browse files Browse the repository at this point in the history
… for ranges.
  • Loading branch information
akrennmair committed Jan 31, 2009
1 parent 970a242 commit 9e33f9e
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 76 deletions.
2 changes: 2 additions & 0 deletions doc/newsbeuter.txt
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ Examples for simple filter expressions are:

unread_count > 0
rssurl =~ "^https:"
age between 0:10

Logically connecting and grouping such expressions looks like in the
following examples:
Expand Down Expand Up @@ -337,6 +338,7 @@ Operator:Meaning
>:greater than
<=:less than or equal
>=:greater than or equal
between:within a range of integer values, where the two integer values are separated by a colon (see above for an example)
#:contains; this operator matches if a word is contained in a list of space-separated words (useful for matching tags, see below)
!#:contains not; the negation of the # operator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion filter/FilterParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include <regex.h>


enum { LOGOP_INVALID = 0, LOGOP_AND = 1, LOGOP_OR, MATCHOP_EQ, MATCHOP_NE, MATCHOP_RXEQ, MATCHOP_RXNE, MATCHOP_LT, MATCHOP_GT, MATCHOP_LE, MATCHOP_GE, MATCHOP_CONTAINS, MATCHOP_CONTAINSNOT };
enum { LOGOP_INVALID = 0, LOGOP_AND = 1, LOGOP_OR, MATCHOP_EQ, MATCHOP_NE, MATCHOP_RXEQ, MATCHOP_RXNE, MATCHOP_LT, MATCHOP_GT, MATCHOP_LE, MATCHOP_GE, MATCHOP_CONTAINS, MATCHOP_CONTAINSNOT, MATCHOP_BETWEEN };

struct expression {
expression(const std::string& n, const std::string& lit, int o);
Expand Down
92 changes: 51 additions & 41 deletions filter/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ void Parser::stringlit(char* &lit) {
Get();
} else if (la->kind == 5) {
Get();
} else SynErr(20);
} else if (la->kind == 6) {
Get();
} else SynErr(22);
lit = coco_string_create_char(t->val);
}

Expand All @@ -78,73 +80,78 @@ void Parser::matchattrib(char* &name) {

void Parser::matchop(int &op) {
switch (la->kind) {
case 6: {
case 7: {
Get();
op = MATCHOP_EQ;
break;
}
case 7: {
case 8: {
Get();
op = MATCHOP_EQ;
break;
}
case 8: {
case 9: {
Get();
op = MATCHOP_NE;
break;
}
case 9: {
case 10: {
Get();
op = MATCHOP_RXEQ;
break;
}
case 10: {
case 11: {
Get();
op = MATCHOP_RXNE;
break;
}
case 11: {
case 12: {
Get();
op = MATCHOP_LT;
break;
}
case 12: {
case 13: {
Get();
op = MATCHOP_GT;
break;
}
case 13: {
case 14: {
Get();
op = MATCHOP_LE;
break;
}
case 14: {
case 15: {
Get();
op = MATCHOP_GE;
break;
}
case 15: {
case 16: {
Get();
op = MATCHOP_CONTAINS;
break;
}
case 16: {
case 17: {
Get();
op = MATCHOP_CONTAINSNOT;
break;
}
default: SynErr(21); break;
case 18: {
Get();
op = MATCHOP_BETWEEN;
break;
}
default: SynErr(23); break;
}
}

void Parser::logop(int &lop) {
if (la->kind == 17) {
if (la->kind == 19) {
Get();
lop = LOGOP_AND;
} else if (la->kind == 18) {
} else if (la->kind == 20) {
Get();
lop = LOGOP_OR;
} else SynErr(22);
} else SynErr(24);
}

void Parser::matchexpr() {
Expand All @@ -169,15 +176,15 @@ void Parser::expr() {
matchexpr();
} else if (la->kind == 1) {
blockexpr();
} else SynErr(23);
while (la->kind == 17 || la->kind == 18) {
} else SynErr(25);
while (la->kind == 19 || la->kind == 20) {
logop(lop);
gen->add_logop(lop);
if (la->kind == 3) {
matchexpr();
} else if (la->kind == 1) {
blockexpr();
} else SynErr(24);
} else SynErr(26);
}
}

Expand All @@ -204,7 +211,8 @@ Parser::Parser(Scanner *scanner) {
_ident = 3;
_stringliteral = 4;
_numliteral = 5;
maxT = 19;
_rangeliteral = 6;
maxT = 21;

minErrDist = 2;
errDist = minErrDist;
Expand All @@ -216,8 +224,8 @@ bool Parser::StartOf(int s) {
const bool T = true;
const bool x = false;

static bool set[1][21] = {
{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x}
static bool set[1][23] = {
{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}
};


Expand All @@ -243,25 +251,27 @@ void Errors::SynErr(int n) {
case 3: s = coco_string_create(L"ident expected"); break;
case 4: s = coco_string_create(L"stringliteral expected"); break;
case 5: s = coco_string_create(L"numliteral expected"); break;
case 6: s = coco_string_create(L"\"==\" expected"); break;
case 7: s = coco_string_create(L"\"=\" expected"); break;
case 8: s = coco_string_create(L"\"!=\" expected"); break;
case 9: s = coco_string_create(L"\"=~\" expected"); break;
case 10: s = coco_string_create(L"\"!~\" expected"); break;
case 11: s = coco_string_create(L"\"<\" expected"); break;
case 12: s = coco_string_create(L"\">\" expected"); break;
case 13: s = coco_string_create(L"\"<=\" expected"); break;
case 14: s = coco_string_create(L"\">=\" expected"); break;
case 15: s = coco_string_create(L"\"#\" expected"); break;
case 16: s = coco_string_create(L"\"!#\" expected"); break;
case 17: s = coco_string_create(L"\"and\" expected"); break;
case 18: s = coco_string_create(L"\"or\" expected"); break;
case 19: s = coco_string_create(L"??? expected"); break;
case 20: s = coco_string_create(L"invalid stringlit"); break;
case 21: s = coco_string_create(L"invalid matchop"); break;
case 22: s = coco_string_create(L"invalid logop"); break;
case 23: s = coco_string_create(L"invalid expr"); break;
case 24: s = coco_string_create(L"invalid expr"); break;
case 6: s = coco_string_create(L"rangeliteral expected"); break;
case 7: s = coco_string_create(L"\"==\" expected"); break;
case 8: s = coco_string_create(L"\"=\" expected"); break;
case 9: s = coco_string_create(L"\"!=\" expected"); break;
case 10: s = coco_string_create(L"\"=~\" expected"); break;
case 11: s = coco_string_create(L"\"!~\" expected"); break;
case 12: s = coco_string_create(L"\"<\" expected"); break;
case 13: s = coco_string_create(L"\">\" expected"); break;
case 14: s = coco_string_create(L"\"<=\" expected"); break;
case 15: s = coco_string_create(L"\">=\" expected"); break;
case 16: s = coco_string_create(L"\"#\" expected"); break;
case 17: s = coco_string_create(L"\"!#\" expected"); break;
case 18: s = coco_string_create(L"\"between\" expected"); break;
case 19: s = coco_string_create(L"\"and\" expected"); break;
case 20: s = coco_string_create(L"\"or\" expected"); break;
case 21: s = coco_string_create(L"??? expected"); break;
case 22: s = coco_string_create(L"invalid stringlit"); break;
case 23: s = coco_string_create(L"invalid matchop"); break;
case 24: s = coco_string_create(L"invalid logop"); break;
case 25: s = coco_string_create(L"invalid expr"); break;
case 26: s = coco_string_create(L"invalid expr"); break;

default:
{
Expand Down
1 change: 1 addition & 0 deletions filter/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Parser {
int _ident;
int _stringliteral;
int _numliteral;
int _rangeliteral;
int maxT;

Token *dummyToken;
Expand Down
80 changes: 47 additions & 33 deletions filter/Scanner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,25 +341,26 @@ Scanner::~Scanner() {
void Scanner::Init() {
EOL = '\n';
eofSym = 0;
maxT = 19;
noSym = 19;
maxT = 21;
noSym = 21;
for (int i = 46; i <= 46; ++i) start.set(i, 3);
for (int i = 65; i <= 90; ++i) start.set(i, 3);
for (int i = 95; i <= 95; ++i) start.set(i, 3);
for (int i = 97; i <= 122; ++i) start.set(i, 3);
for (int i = 48; i <= 57; ++i) start.set(i, 6);
for (int i = 48; i <= 57; ++i) start.set(i, 9);
start.set(40, 1);
start.set(41, 2);
start.set(34, 4);
start.set(45, 7);
start.set(61, 16);
start.set(33, 17);
start.set(60, 18);
start.set(62, 19);
start.set(35, 14);
start.set(45, 10);
start.set(61, 19);
start.set(33, 20);
start.set(60, 21);
start.set(62, 22);
start.set(35, 17);
start.set(Buffer::EoF, -1);
keywords.set(L"and", 17);
keywords.set(L"or", 18);
keywords.set(L"between", 18);
keywords.set(L"and", 19);
keywords.set(L"or", 20);


tvalLength = 128;
Expand Down Expand Up @@ -504,47 +505,60 @@ Token* Scanner::NextToken() {
if (ch >= L'0' && ch <= L'9') {AddCh(); goto case_6;}
else {t->kind = 5; break;}
case 7:
if (ch >= L'-' && ch <= L'.' || ch >= L'A' && ch <= L'Z' || ch == L'_' || ch >= L'a' && ch <= L'z') {AddCh(); goto case_3;}
else if (ch >= L'0' && ch <= L'9') {AddCh(); goto case_6;}
else {t->kind = 3; wchar_t *literal = coco_string_create(tval, 0, tlen); t->kind = keywords.get(literal, t->kind); coco_string_delete(literal); break;}
case_7:
if (ch >= L'0' && ch <= L'9') {AddCh(); goto case_8;}
else {t->kind = noSym; break;}
case 8:
case_8:
{t->kind = 6; break;}
if (ch >= L'0' && ch <= L'9') {AddCh(); goto case_8;}
else {t->kind = 6; break;}
case 9:
case_9:
{t->kind = 8; break;}
if (ch >= L'0' && ch <= L'9') {AddCh(); goto case_9;}
else if (ch == L':') {AddCh(); goto case_7;}
else {t->kind = 5; break;}
case 10:
case_10:
{t->kind = 9; break;}
if (ch >= L'-' && ch <= L'.' || ch >= L'A' && ch <= L'Z' || ch == L'_' || ch >= L'a' && ch <= L'z') {AddCh(); goto case_3;}
else if (ch >= L'0' && ch <= L'9') {AddCh(); goto case_6;}
else {t->kind = 3; wchar_t *literal = coco_string_create(tval, 0, tlen); t->kind = keywords.get(literal, t->kind); coco_string_delete(literal); break;}
case 11:
case_11:
{t->kind = 10; break;}
{t->kind = 7; break;}
case 12:
case_12:
{t->kind = 13; break;}
{t->kind = 9; break;}
case 13:
case_13:
{t->kind = 14; break;}
{t->kind = 10; break;}
case 14:
{t->kind = 15; break;}
case_14:
{t->kind = 11; break;}
case 15:
case_15:
{t->kind = 16; break;}
{t->kind = 14; break;}
case 16:
if (ch == L'=') {AddCh(); goto case_8;}
else if (ch == L'~') {AddCh(); goto case_10;}
else {t->kind = 7; break;}
case_16:
{t->kind = 15; break;}
case 17:
if (ch == L'=') {AddCh(); goto case_9;}
else if (ch == L'~') {AddCh(); goto case_11;}
else if (ch == L'#') {AddCh(); goto case_15;}
else {t->kind = noSym; break;}
{t->kind = 16; break;}
case 18:
if (ch == L'=') {AddCh(); goto case_12;}
else {t->kind = 11; break;}
case_18:
{t->kind = 17; break;}
case 19:
if (ch == L'=') {AddCh(); goto case_13;}
if (ch == L'=') {AddCh(); goto case_11;}
else if (ch == L'~') {AddCh(); goto case_13;}
else {t->kind = 8; break;}
case 20:
if (ch == L'=') {AddCh(); goto case_12;}
else if (ch == L'~') {AddCh(); goto case_14;}
else if (ch == L'#') {AddCh(); goto case_18;}
else {t->kind = noSym; break;}
case 21:
if (ch == L'=') {AddCh(); goto case_15;}
else {t->kind = 12; break;}
case 22:
if (ch == L'=') {AddCh(); goto case_16;}
else {t->kind = 13; break;}

}
AppendVal(t);
Expand Down
4 changes: 3 additions & 1 deletion filter/filter.atg
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ TOKENS
ident = identchar { identchar }.
stringliteral = '"' { nonquote } '"'.
numliteral = ['-'] digit { digit }.
rangeliteral = digit { digit } ':' digit { digit }.

PRODUCTIONS

stringlit<char* &lit>
= ( stringliteral | numliteral ) (. lit = coco_string_create_char(t->val); .)
= ( stringliteral | numliteral | rangeliteral ) (. lit = coco_string_create_char(t->val); .)
.

matchattrib<char* &name>
Expand All @@ -42,6 +43,7 @@ PRODUCTIONS
| ">=" (. op = MATCHOP_GE; .)
| "#" (. op = MATCHOP_CONTAINS; .)
| "!#" (. op = MATCHOP_CONTAINSNOT; .)
| "between" (. op = MATCHOP_BETWEEN; .)
.

logop<int &lop>
Expand Down
1 change: 1 addition & 0 deletions include/matcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace newsbeuter {
bool matchop_rxeq(expression * e, matchable * item);
bool matchop_cont(expression * e, matchable * item);
bool matchop_eq(expression * e, matchable * item);
bool matchop_between(expression * e, matchable * item);

FilterParser p;
bool success;
Expand Down
Loading

0 comments on commit 9e33f9e

Please sign in to comment.