Initial import of filter parser
Current runs as its own program, partially implemented. Commiting for the sake of sharing access / backup. Still needs a lot of work.
This commit is contained in:
parent
21fa755c13
commit
9693b66024
2
filter_sandbox/.gitignore
vendored
Normal file
2
filter_sandbox/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.output
|
||||
test
|
8
filter_sandbox/Makefile
Normal file
8
filter_sandbox/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
all:
|
||||
gcc -c tree.c -o tree.o
|
||||
lex zmap.l
|
||||
yacc -d --debug --verbose zmap.y
|
||||
gcc tree.o lex.yy.c y.tab.c -o test
|
||||
|
||||
clean:
|
||||
rm *.o a.out test
|
7
filter_sandbox/README
Normal file
7
filter_sandbox/README
Normal file
@ -0,0 +1,7 @@
|
||||
make
|
||||
|
||||
./text
|
||||
|
||||
Example Input:
|
||||
|
||||
(ipaddr = 8 && herp = 6) || (field = value && yolo = swag)
|
1807
filter_sandbox/lex.yy.c
Normal file
1807
filter_sandbox/lex.yy.c
Normal file
File diff suppressed because it is too large
Load Diff
347
filter_sandbox/parser.y
Normal file
347
filter_sandbox/parser.y
Normal file
@ -0,0 +1,347 @@
|
||||
/* File: parser.y
|
||||
* --------------
|
||||
* Yacc input file to generate the parser for the compiler.
|
||||
*
|
||||
* pp2: your job is to write a parser that will construct the parse tree
|
||||
* and if no parse errors were found, print it. The parser should
|
||||
* accept the language as described in specification, and as augmented
|
||||
* in the pp2 handout.
|
||||
*/
|
||||
|
||||
%{
|
||||
|
||||
/* Just like lex, the text within this first region delimited by %{ and %}
|
||||
* is assumed to be C/C++ code and will be copied verbatim to the y.tab.c
|
||||
* file ahead of the definitions of the yyparse() function. Add other header
|
||||
* file inclusions or C++ variable declarations/prototypes that are needed
|
||||
* by your code here.
|
||||
*/
|
||||
#include "scanner.h" // for yylex
|
||||
#include "parser.h"
|
||||
#include "errors.h"
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
void yyerror(const char *msg); // standard error-handling routine
|
||||
|
||||
%}
|
||||
|
||||
/* The section before the first %% is the Definitions section of the yacc
|
||||
* input file. Here is where you declare tokens and types, add precedence
|
||||
* and associativity options, and so on.
|
||||
*/
|
||||
|
||||
/* yylval
|
||||
* ------
|
||||
* Here we define the type of the yylval global variable that is used by
|
||||
* the scanner to store attibute information about the token just scanned
|
||||
* and thus communicate that information to the parser.
|
||||
*
|
||||
* pp2: You will need to add new fields to this union as you add different
|
||||
* attributes to your non-terminal symbols.
|
||||
*/
|
||||
%union {
|
||||
int integerConstant;
|
||||
bool boolConstant;
|
||||
char *stringConstant;
|
||||
double doubleConstant;
|
||||
char identifier[MaxIdentLen+1]; // +1 for terminating null
|
||||
Decl *decl;
|
||||
VarDecl *varDecl;
|
||||
Case *caseNode;
|
||||
Default *defaultNode;
|
||||
List<Decl*> *declList;
|
||||
Stmt *stmt;
|
||||
List<Stmt*> *stmtList;
|
||||
List<VarDecl*> *varDeclList;
|
||||
List<Case*> *caseList;
|
||||
Expr *expr;
|
||||
Type *type;
|
||||
List<Expr*> *exprList;
|
||||
List<NamedType*> *typeList;
|
||||
}
|
||||
|
||||
/* Tokens
|
||||
* ------
|
||||
* Here we tell yacc about all the token types that we are using.
|
||||
* Yacc will assign unique numbers to these and export the #define
|
||||
* in the generated y.tab.h header file.
|
||||
*/
|
||||
%token T_Void T_Bool T_Int T_Double T_String T_Class
|
||||
%token T_LessEqual T_GreaterEqual T_Equal T_NotEqual T_Dims
|
||||
%token T_And T_Or T_Null T_Extends T_This T_Interface T_Implements
|
||||
%token T_While T_For T_If T_Else T_Return T_Break
|
||||
%token T_New T_NewArray T_Print T_ReadInteger T_ReadLine
|
||||
|
||||
%token <identifier> T_Identifier
|
||||
%token <stringConstant> T_StringConstant
|
||||
%token <integerConstant> T_IntConstant
|
||||
%token <doubleConstant> T_DoubleConstant
|
||||
%token <boolConstant> T_BoolConstant
|
||||
|
||||
%token T_Increm T_Decrem T_Switch T_Case T_Default
|
||||
|
||||
%nonassoc NON_ELSE
|
||||
%nonassoc T_Else
|
||||
%nonassoc '='
|
||||
%left T_Or
|
||||
%left T_And
|
||||
%left T_Equal T_NotEqual
|
||||
%nonassoc '<' T_LessEqual T_GreaterEqual '>'
|
||||
%left '+' '-'
|
||||
%left '*' '/' '%'
|
||||
%left NEG '!' INCRDECR
|
||||
%left '[' '.'
|
||||
|
||||
/* Non-terminal types
|
||||
* ------------------
|
||||
* In order for yacc to assign/access the correct field of $$, $1, we
|
||||
* must to declare which field is appropriate for the non-terminal.
|
||||
* As an example, this first type declaration establishes that the DeclList
|
||||
* non-terminal uses the field named "declList" in the yylval union. This
|
||||
* means that when we are setting $$ for a reduction for DeclList ore reading
|
||||
* $n which corresponds to a DeclList nonterminal we are accessing the field
|
||||
* of the union named "declList" which is of type List<Decl*>.
|
||||
* pp2: You'll need to add many of these of your own.
|
||||
*/
|
||||
%type <declList> DeclList
|
||||
%type <varDeclList> VarDeclList
|
||||
%type <varDeclList> Formals
|
||||
%type <decl> Decl
|
||||
%type <decl> FnDecl
|
||||
%type <varDecl> VarDecl
|
||||
%type <varDecl> Variable
|
||||
%type <stmt> Stmt
|
||||
%type <stmt> WhileStmt
|
||||
%type <stmt> IfStmt
|
||||
%type <stmt> ForStmt
|
||||
%type <stmt> BreakStmt
|
||||
%type <stmt> ReturnStmt
|
||||
%type <stmt> PrintStmt
|
||||
%type <stmt> StmtBlock
|
||||
%type <stmtList> StmtList
|
||||
%type <expr> Expr
|
||||
%type <expr> EmptyExpr
|
||||
%type <type> Type
|
||||
%type <decl> Field
|
||||
%type <declList> FieldList
|
||||
%type <decl> ClassDecl
|
||||
%type <decl> InterfaceDecl
|
||||
%type <typeList> InterfaceList
|
||||
%type <decl> Prototype
|
||||
%type <declList> PrototypeList
|
||||
%type <exprList> ExprList
|
||||
%type <exprList> Actuals
|
||||
%type <expr> LValue
|
||||
%type <expr> Constant
|
||||
%type <expr> Call
|
||||
%type <stmt> SwitchStmt
|
||||
%type <caseList> CaseList
|
||||
%type <caseNode> Case
|
||||
%type <defaultNode> Default
|
||||
|
||||
%%
|
||||
/* Rules
|
||||
* -----
|
||||
* All productions and actions should be placed between the start and stop
|
||||
* %% markers which delimit the Rules section.
|
||||
|
||||
*/
|
||||
Program : DeclList {
|
||||
Program *program = new Program($1);
|
||||
// if no errors, advance to next phase
|
||||
if (ReportError::NumErrors() == 0)
|
||||
program->Print(0);
|
||||
}
|
||||
;
|
||||
|
||||
DeclList : DeclList Decl { ($$=$1)->Append($2); }
|
||||
| Decl { ($$ = new List<Decl*>)->Append($1); }
|
||||
;
|
||||
|
||||
Decl : VarDecl { $$ = $1; }
|
||||
| FnDecl {$$ = $1;}
|
||||
| ClassDecl {$$ = $1;}
|
||||
| InterfaceDecl {$$ = $1;}
|
||||
;
|
||||
|
||||
VarDeclList : VarDeclList VarDecl { ($$=$1)->Append($2); }
|
||||
| VarDecl { ($$ = new List<VarDecl*>)->Append($1); }
|
||||
;
|
||||
|
||||
VarDecl : Variable ';' {$$ = $1;};
|
||||
|
||||
Variable : Type T_Identifier {$$ = new VarDecl(new Identifier(@2, $2), $1); };
|
||||
|
||||
ClassDecl : T_Class T_Identifier '{' FieldList '}' {$$ = new ClassDecl(new Identifier(@2, $2), 0, new List<NamedType*>, $4);}
|
||||
| T_Class T_Identifier T_Extends T_Identifier '{' FieldList '}' {$$ = new ClassDecl(new Identifier(@2, $2), new NamedType(new Identifier(@4, $4)), new List<NamedType*>, $6);}
|
||||
| T_Class T_Identifier T_Extends T_Identifier T_Implements InterfaceList '{' FieldList '}' {$$ = new ClassDecl(new Identifier(@2, $2), new NamedType(new Identifier(@4, $4)), $6, $8);}
|
||||
| T_Class T_Identifier T_Implements InterfaceList '{' FieldList '}' {$$ = new ClassDecl(new Identifier(@2, $2), 0, $4, $6);}
|
||||
;
|
||||
|
||||
InterfaceList: T_Identifier ',' InterfaceList {($$=$3)->Append(new NamedType(new Identifier(@1, $1)));}
|
||||
| T_Identifier {($$=new List<NamedType*>)->Append(new NamedType(new Identifier(@1, $1)));}
|
||||
|
||||
FieldList : FieldList Field {($$ = $1)->Append($2);}
|
||||
| /* empty */ {$$ = new List<Decl*>;}
|
||||
;
|
||||
|
||||
Type: T_Int {$$ = Type::intType; }
|
||||
| T_Double {$$ = Type::doubleType; }
|
||||
|T_Bool {$$ = Type::boolType; }
|
||||
|T_String {$$ = Type::stringType; }
|
||||
|T_Identifier {$$ = new NamedType(new Identifier(@1, $1)); }
|
||||
|Type T_Dims {$$ = new ArrayType(@1, $1); }
|
||||
;
|
||||
|
||||
FnDecl : Type T_Identifier '(' Formals ')' StmtBlock {$$ = new FnDecl(new Identifier(@2, $2), $1, $4); ((FnDecl *)$$)->SetFunctionBody($6); }
|
||||
| T_Void T_Identifier '(' Formals ')' StmtBlock {$$ = new FnDecl(new Identifier(@2, $2), Type::voidType, $4); ((FnDecl *)$$)->SetFunctionBody($6); }
|
||||
;
|
||||
|
||||
Formals : Variable {($$ = new List<VarDecl*>)->Append($1);}
|
||||
| Formals ',' Variable {($$ = $1)->Append($3);}
|
||||
| {$$ = new List<VarDecl*>;}
|
||||
;
|
||||
|
||||
Field : VarDecl {$$ = $1;}
|
||||
| FnDecl {$$ = $1;}
|
||||
;
|
||||
|
||||
InterfaceDecl : T_Interface T_Identifier '{' PrototypeList '}' {$$ = new InterfaceDecl(new Identifier(@2, $2), $4);};
|
||||
|
||||
PrototypeList : PrototypeList Prototype {($$=$1)->Append($2);}
|
||||
| {$$ = new List<Decl*>;}
|
||||
;
|
||||
Prototype : Type T_Identifier '(' Formals ')' ';' {$$ = new FnDecl(new Identifier(@2, $2), $1, $4);}
|
||||
| T_Void T_Identifier '(' Formals ')' ';' {$$ = new FnDecl(new Identifier(@2, $2), Type::voidType, $4);}
|
||||
;
|
||||
|
||||
StmtBlock : '{' VarDeclList StmtList '}' { $$ = new StmtBlock($2, $3);}
|
||||
| '{' VarDeclList '}' { $$ = new StmtBlock($2, new List<Stmt*>);}
|
||||
| '{' StmtList '}' { $$ = new StmtBlock(new List<VarDecl*>, $2);}
|
||||
| '{' '}' { $$ = new StmtBlock(new List<VarDecl*>, new List<Stmt*>);}
|
||||
;
|
||||
|
||||
StmtList : StmtList Stmt { ($$=$1)->Append($2);}
|
||||
| Stmt { ($$ = new List<Stmt*>)->Append($1); }
|
||||
;
|
||||
|
||||
Stmt : EmptyExpr ';' {$$ = $1; }
|
||||
| IfStmt {$$ = $1; }
|
||||
| WhileStmt {$$ = $1; }
|
||||
| ForStmt {$$ = $1; }
|
||||
| BreakStmt {$$ = $1; }
|
||||
| ReturnStmt {$$ = $1; }
|
||||
| PrintStmt {$$ = $1; }
|
||||
| StmtBlock {$$ = $1; }
|
||||
| SwitchStmt {$$ = $1; }
|
||||
;
|
||||
|
||||
IfStmt : T_If '(' Expr ')' Stmt %prec NON_ELSE {$$ = new IfStmt($3, $5, 0); }
|
||||
| T_If '(' Expr ')' Stmt T_Else Stmt { $$ = new IfStmt($3, $5, $7); }
|
||||
;
|
||||
SwitchStmt : T_Switch '(' Expr ')' '{' CaseList Default '}' { $$ = new SwitchStmt($3, $6, $7);}
|
||||
| T_Switch '(' Expr ')' '{' CaseList '}' { $$ = new SwitchStmt($3, $6, 0);};
|
||||
|
||||
CaseList : CaseList Case {($$ = $1)->Append($2);}
|
||||
| Case {($$ = new List<Case*>)->Append($1);}
|
||||
;
|
||||
|
||||
Case : T_Case T_IntConstant ':' StmtList {$$ = new Case(new IntConstant(@2, $2), $4);}
|
||||
| T_Case T_IntConstant ':' {$$ = new Case(new IntConstant(@2, $2), new List<Stmt*>);};
|
||||
|
||||
Default : T_Default ':' StmtList {$$ = new Default($3);}
|
||||
| T_Default ':' {$$ = new Default(new List<Stmt*>);};
|
||||
|
||||
WhileStmt : T_While '(' Expr ')' Stmt {$$ = new WhileStmt($3, $5); }
|
||||
;
|
||||
ForStmt : T_For '(' EmptyExpr ';' Expr ';' EmptyExpr ')' Stmt {$$ = new ForStmt($3, $5, $7, $9); }
|
||||
;
|
||||
|
||||
ReturnStmt : T_Return EmptyExpr ';' { $$ = new ReturnStmt(@1, $2); };
|
||||
|
||||
BreakStmt : T_Break ';' {$$ = new BreakStmt(@1); };
|
||||
|
||||
PrintStmt : T_Print '(' ExprList ')' ';' {$$ = new PrintStmt($3);};
|
||||
|
||||
ExprList : Expr {($$ = new List<Expr*>)->Append($1);}
|
||||
| ExprList ',' Expr {($$ = $1)->Append($3);}
|
||||
;
|
||||
|
||||
EmptyExpr : Expr {$$ = $1; }
|
||||
| {$$ = new EmptyExpr; }
|
||||
;
|
||||
|
||||
Expr : LValue '=' Expr {$$ = new AssignExpr($1, new Operator(@2, "=") , $3); };
|
||||
| Constant {$$ = $1;}
|
||||
| LValue {$$ = $1; }
|
||||
| T_This {$$ = new This(@1);}
|
||||
| Call {$$ = $1;}
|
||||
|'(' Expr ')' {$$ = $2;}
|
||||
| Expr '+' Expr {$$ = new ArithmeticExpr($1, new Operator(@2, "+"), $3);}
|
||||
| Expr '-' Expr {$$ = new ArithmeticExpr($1, new Operator(@2, "-"), $3);}
|
||||
| Expr '*' Expr {$$ = new ArithmeticExpr($1, new Operator(@2, "*"), $3);}
|
||||
| Expr '/' Expr {$$ = new ArithmeticExpr($1, new Operator(@2, "/"), $3);}
|
||||
| Expr '%' Expr {$$ = new ArithmeticExpr($1, new Operator(@2, "%"), $3);}
|
||||
| '-' Expr %prec NEG {$$ = new ArithmeticExpr(new Operator(@2, "-"), $2);}
|
||||
| Expr '<' Expr {$$ = new RelationalExpr($1, new Operator(@2, "<"), $3);}
|
||||
| Expr T_LessEqual Expr {$$ = new RelationalExpr($1, new Operator(@2, "<="), $3);}
|
||||
| Expr '>' Expr {$$ = new RelationalExpr($1, new Operator(@2, ">"), $3);}
|
||||
| Expr T_GreaterEqual Expr {$$ = new RelationalExpr($1, new Operator(@2, ">="), $3);}
|
||||
| Expr T_Equal Expr {$$ = new EqualityExpr($1, new Operator(@2, "=="), $3);}
|
||||
| Expr T_NotEqual Expr {$$ = new EqualityExpr($1, new Operator(@2, "!="), $3);}
|
||||
| Expr T_And Expr {$$ = new LogicalExpr($1, new Operator(@2, "&&"), $3);}
|
||||
| Expr T_Or Expr {$$ = new LogicalExpr($1, new Operator(@2, "||"), $3);}
|
||||
| '!' Expr {$$ = new LogicalExpr(new Operator(@1, "!"), $2);}
|
||||
| T_ReadInteger '(' ')' {$$ = new ReadIntegerExpr(@1);}
|
||||
| T_ReadLine '(' ')' {$$ = new ReadLineExpr(@1);}
|
||||
| T_New '(' T_Identifier ')' {$$ = new NewExpr(@1, new NamedType(new Identifier(@3, $3)) );}
|
||||
| T_NewArray '('Expr ',' Type')' {$$ = new NewArrayExpr(@1, $3, $5);}
|
||||
| LValue T_Increm %prec INCRDECR {$$ = new PostfixExpr($1, new Operator(@2, "++"));}
|
||||
| LValue T_Decrem %prec INCRDECR {$$ = new PostfixExpr($1, new Operator(@2, "--"));}
|
||||
;
|
||||
|
||||
LValue : T_Identifier {$$ = new FieldAccess(0, new Identifier(@1, $1)); }
|
||||
| Expr '.' T_Identifier {$$ = new FieldAccess($1, new Identifier(@3, $3));}
|
||||
| Expr '[' Expr ']' {$$ = new ArrayAccess(@1, $1, $3);}
|
||||
;
|
||||
|
||||
Call : T_Identifier '(' Actuals ')' {$$ = new Call(@1, 0, new Identifier(@1, $1), $3);}
|
||||
| Expr '.' T_Identifier '(' Actuals ')' {$$ = new Call(@1, $1, new Identifier(@3, $3), $5);}
|
||||
;
|
||||
|
||||
Actuals: ExprList {$$ = $1;}
|
||||
| {$$ = new List<Expr*>;}
|
||||
;
|
||||
|
||||
Constant: T_IntConstant {$$ = new IntConstant(@1, $1);}
|
||||
| T_DoubleConstant {$$ = new DoubleConstant(@1, $1);}
|
||||
| T_BoolConstant {$$ = new BoolConstant(@1, $1);}
|
||||
| T_StringConstant {$$ = new StringConstant(@1, $1);}
|
||||
| T_Null {$$ = new NullConstant(@1); }
|
||||
;
|
||||
%%
|
||||
|
||||
/* The closing %% above marks the end of the Rules section and the beginning
|
||||
* of the User Subroutines section. All text from here to the end of the
|
||||
* file is copied verbatim to the end of the generated y.tab.c file.
|
||||
* This section is where you put definitions of helper functions.
|
||||
*/
|
||||
|
||||
/* Function: InitParser
|
||||
* --------------------
|
||||
* This function will be called before any calls to yyparse(). It is designed
|
||||
* to give you an opportunity to do anything that must be done to initialize
|
||||
* the parser (set global variables, configure starting state, etc.). One
|
||||
* thing it already does for you is assign the value of the global variable
|
||||
* yydebug that controls whether yacc prints debugging information about
|
||||
* parser actions (shift/reduce) and contents of state stack during parser.
|
||||
* If set to false, no information is printed. Setting it to true will give
|
||||
* you a running trail that might be helpful when debugging your parser.
|
||||
* Please be sure the variable is set to false when submitting your final
|
||||
* version.
|
||||
*/
|
||||
void InitParser()
|
||||
{
|
||||
PrintDebug("parser", "Initializing parser");
|
||||
yydebug = false;
|
||||
}
|
256
filter_sandbox/scanner.l
Normal file
256
filter_sandbox/scanner.l
Normal file
@ -0,0 +1,256 @@
|
||||
/* File: scanner.l
|
||||
* ----------------
|
||||
* Lex input file to generate the scanner for the compiler.
|
||||
*/
|
||||
|
||||
%{
|
||||
#include <string.h>
|
||||
#include "scanner.h"
|
||||
#include "utility.h" // for PrintDebug()
|
||||
#include "errors.h"
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
|
||||
using std::string;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
/* Global variable: yylval
|
||||
* -----------------------
|
||||
* This global variable is how we get attribute information about the token
|
||||
* just scanned to the client. The scanner sets the global variable
|
||||
* appropriately and since it's global the client can just read it. In the
|
||||
* future, this variable will be declared for us in the y.tab.c file
|
||||
* produced by Yacc, but for now, we declare it manually.
|
||||
*/
|
||||
YYSTYPE yylval; // manually declared for pp1, later Yacc provides
|
||||
|
||||
/* Global variable: yylloc
|
||||
* -----------------------
|
||||
* This global variable is how we get position information about the token
|
||||
* just scanned to the client. (Operates similarly to yylval above)
|
||||
*/
|
||||
struct yyltype yylloc; // manually dclared for pp1, later Yacc provides
|
||||
|
||||
/* Macro: YY_USER_ACTION
|
||||
* ---------------------
|
||||
* This flex built-in macro can be defined to provide an action which is
|
||||
* always executed prior to any matched rule's action. Basically, it is
|
||||
* a way of having a piece of code common to all actions factored out to
|
||||
* this routine. We already defined it for you and left the empty
|
||||
* function DoBeforeEachAction ready for your use as needed. It will
|
||||
* be called once for each pattern scanned from the file, before
|
||||
* executing its action.
|
||||
*/
|
||||
static void DoBeforeEachAction();
|
||||
#define YY_USER_ACTION DoBeforeEachAction();
|
||||
|
||||
static void set_value(TokenType);
|
||||
|
||||
%}
|
||||
|
||||
ALPHA [a-zA-Z]
|
||||
ALPHANUM [a-zA-Z0-9]
|
||||
WORDCHAR [a-zA-Z0-9_]
|
||||
DIGIT [0-9]
|
||||
HEX 0(x|X)[0-9a-fA-F]+
|
||||
WHITESPACE [ \t\n]
|
||||
|
||||
%%
|
||||
|
||||
/* Keywords */
|
||||
void return T_Void;
|
||||
int return T_Int;
|
||||
double return T_Double;
|
||||
bool return T_Bool;
|
||||
string return T_String;
|
||||
class return T_Class;
|
||||
interface return T_Interface;
|
||||
null return T_Null;
|
||||
this return T_This;
|
||||
extends return T_Extends;
|
||||
implements return T_Implements;
|
||||
for return T_For;
|
||||
while return T_While;
|
||||
if return T_If;
|
||||
else return T_Else;
|
||||
return return T_Return;
|
||||
break return T_Break;
|
||||
New return T_New;
|
||||
NewArray return T_NewArray;
|
||||
|
||||
/* Type Constants */
|
||||
true|false {set_value(T_BoolConstant); return T_BoolConstant;}
|
||||
{HEX}|{DIGIT}+ {set_value(T_IntConstant); return T_IntConstant;}
|
||||
{DIGIT}+\.{DIGIT}*((E|e)(\+|-)?{DIGIT}+)? {set_value(T_DoubleConstant); return T_DoubleConstant;}
|
||||
\"[^\"\n]*\" {set_value(T_StringConstant); return T_StringConstant;}
|
||||
\"[^\"\n]* {ReportError::UntermString(&yylloc, yytext);}
|
||||
|
||||
/* Whitespace */
|
||||
{WHITESPACE} ;
|
||||
|
||||
/* Identifier */
|
||||
{ALPHA}{WORDCHAR}* {set_value(T_Identifier); return T_Identifier;}
|
||||
|
||||
/* Operators */
|
||||
"<=" return T_LessEqual;
|
||||
>= return T_GreaterEqual;
|
||||
== return T_Equal;
|
||||
!= return T_NotEqual;
|
||||
&& return T_And;
|
||||
"||" return T_Or;
|
||||
\+ return '+';
|
||||
- return '-';
|
||||
\* return '*';
|
||||
\/ return '/';
|
||||
% return '%';
|
||||
\< return '<';
|
||||
\> return '>';
|
||||
= return '=';
|
||||
! return '!';
|
||||
; return ';';
|
||||
, return ',';
|
||||
\. return '.';
|
||||
"[" return '[';
|
||||
"]" return ']';
|
||||
"(" return '(';
|
||||
")" return ')';
|
||||
"{" return '{';
|
||||
"}" return '}';
|
||||
|
||||
. ReportError::UnrecogChar(&yylloc, *yytext);
|
||||
|
||||
%%
|
||||
|
||||
static bool text_to_bool(char *yytext) {
|
||||
if (!strcmp(yytext, "true")) {
|
||||
return true;
|
||||
} else if (!strcmp(yytext, "false")) {
|
||||
return false;
|
||||
} else {
|
||||
Failure("Unrecognized value in function text_to_bool()");
|
||||
}
|
||||
|
||||
// This will never be called
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int text_to_int(char *yytext) {
|
||||
if (strlen(yytext) >= 2 && (yytext[1] == 'x' || yytext[1] == 'X')) {
|
||||
int num;
|
||||
int decimal = 0;
|
||||
for (int i = 2; i < yyleng; i++) {
|
||||
char c = isalpha(yytext[i]) ? toupper(yytext[i]) : yytext[i];
|
||||
switch(c) {
|
||||
case 'A': num = 10; break;
|
||||
case 'B': num = 11; break;
|
||||
case 'C': num = 12; break;
|
||||
case 'D': num = 13; break;
|
||||
case 'E': num = 14; break;
|
||||
case 'F': num = 15; break;
|
||||
default: num = yytext[i] - 48; break;
|
||||
}
|
||||
decimal += num * pow(16, yyleng - i - 1); // The exponent is the inverse of the char position
|
||||
}
|
||||
return decimal;
|
||||
}
|
||||
return atoi(yytext);
|
||||
}
|
||||
|
||||
static double text_to_double(char *yytext) {
|
||||
int i = 0;
|
||||
double ret = 0;
|
||||
bool decimal = false;
|
||||
double divisor = 1;
|
||||
bool pose = true;
|
||||
bool exponent = false;
|
||||
std::string num;
|
||||
while(i < yyleng){
|
||||
num = num + yytext[i];
|
||||
if(yytext[i] == 'E' || yytext[i] == 'e'){
|
||||
exponent = true;
|
||||
ret = ret + atoi(num.c_str())/divisor;
|
||||
num.clear();
|
||||
if(yytext[i + 1] == '-'){
|
||||
pose = false;
|
||||
i++;
|
||||
}
|
||||
else if(yytext[i + 1] == '+') i++;
|
||||
}
|
||||
if(decimal) divisor *= 10;
|
||||
if(yytext[i] == '.'){
|
||||
ret = atoi(num.c_str());
|
||||
decimal = true;
|
||||
num.clear();
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if(exponent) return ret * pow(10, atoi(num.c_str()));
|
||||
else return ret + atoi(num.c_str())/divisor;
|
||||
}
|
||||
|
||||
static void set_identifier(char *identifier) {
|
||||
int num_chars = yyleng + 1; // The characters plus the null character
|
||||
if (yyleng > MaxIdentLen) {
|
||||
ReportError::LongIdentifier(&yylloc, yytext);
|
||||
num_chars = MaxIdentLen;
|
||||
}
|
||||
|
||||
strncpy(identifier, yytext, num_chars);
|
||||
assert(identifier[MaxIdentLen + 1] == 0);
|
||||
}
|
||||
|
||||
static void set_value(TokenType t) {
|
||||
switch(t) {
|
||||
case T_BoolConstant: yylval.boolConstant = text_to_bool(yytext); break;
|
||||
case T_IntConstant: yylval.integerConstant = text_to_int(yytext); break;
|
||||
case T_DoubleConstant: yylval.doubleConstant = text_to_double(yytext); break;
|
||||
case T_StringConstant: yylval.stringConstant = yytext; break;
|
||||
case T_Identifier: set_identifier(yylval.identifier); break;
|
||||
default: Failure("Unrecognized token %d in set_value()", (int) t);
|
||||
}
|
||||
}
|
||||
|
||||
/* Function: InitScanner
|
||||
* ---------------------
|
||||
* This function will be called before any calls to yylex(). It is designed
|
||||
* to give you an opportunity to do anything that must be done to initialize
|
||||
* the scanner (set global variables, configure starting state, etc.). One
|
||||
* thing it already does for you is assign the value of the global variable
|
||||
* yy_flex_debug that controls whether flex prints debugging information
|
||||
* about each token and what rule was matched. If set to false, no information
|
||||
* is printed. Setting it to true will give you a running trail that might
|
||||
* be helpful when debugging your scanner. Please be sure the variable is
|
||||
* set to false when submitting your final version.
|
||||
*/
|
||||
void InitScanner()
|
||||
{
|
||||
yy_flex_debug = false;
|
||||
PrintDebug("lex", "Initializing scanner");
|
||||
}
|
||||
|
||||
|
||||
/* Function: DoBeforeEachAction()
|
||||
* ------------------------------
|
||||
* This function is installed as the YY_USER_ACTION. This is a place
|
||||
* to group code common to all actions.
|
||||
*/
|
||||
static void DoBeforeEachAction()
|
||||
{
|
||||
// TODO: This section looks hacky to me
|
||||
static int col_pos = 1;
|
||||
static int line_pos = 1;
|
||||
|
||||
if (*yytext == '\n') {
|
||||
line_pos++;
|
||||
col_pos = 0;
|
||||
}
|
||||
|
||||
yylloc.first_column = col_pos;
|
||||
yylloc.last_column = col_pos + yyleng - 1;
|
||||
yylloc.first_line = line_pos;
|
||||
|
||||
col_pos += yyleng;
|
||||
}
|
69
filter_sandbox/tree.c
Normal file
69
filter_sandbox/tree.c
Normal file
@ -0,0 +1,69 @@
|
||||
#include "tree.h"
|
||||
|
||||
node_t* alloc_node()
|
||||
{
|
||||
node_t *node = (node_t*) malloc(sizeof(node_t));
|
||||
memset(node, 0, sizeof(node_t));
|
||||
return node;
|
||||
}
|
||||
|
||||
node_t* make_op_node(enum operation op)
|
||||
{
|
||||
node_t* node = alloc_node();
|
||||
node->type = OP;
|
||||
node->value.op = op;
|
||||
return node;
|
||||
}
|
||||
|
||||
node_t* make_field_node(char *fieldname)
|
||||
{
|
||||
node_t *node = alloc_node();
|
||||
node->type = FIELD;
|
||||
node->value.fieldname = fieldname;
|
||||
return node;
|
||||
}
|
||||
|
||||
node_t* make_string_node(char *literal)
|
||||
{
|
||||
node_t *node = alloc_node();
|
||||
node->type = STRING;
|
||||
node->value.string_literal = literal;
|
||||
return node;
|
||||
}
|
||||
|
||||
node_t* make_int_node(int literal)
|
||||
{
|
||||
node_t *node = alloc_node();
|
||||
node->type = INT;
|
||||
node->value.int_literal = literal;
|
||||
return node;
|
||||
}
|
||||
|
||||
int evaluate_expression(node_t *root) {
|
||||
int result = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
void print_expression(node_t *root) {
|
||||
if (!root) return;
|
||||
printf("%s", "( ");
|
||||
print_expression(root->left_child);
|
||||
switch (root->type) {
|
||||
case OP:
|
||||
printf(" %i ", root->value.op);
|
||||
break;
|
||||
case FIELD:
|
||||
printf(" (%s", root->value.fieldname);
|
||||
break;
|
||||
case STRING:
|
||||
printf("%s) ", root->value.string_literal);
|
||||
break;
|
||||
case INT:
|
||||
printf(" %d) ", root->value.int_literal);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
print_expression(root->right_child);
|
||||
printf("%s", " )");
|
||||
}
|
44
filter_sandbox/tree.h
Normal file
44
filter_sandbox/tree.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef ZMAP_TREE_H
|
||||
#define ZMAP_TREE_H
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
enum operation {
|
||||
GT, LT, EQ, NEQ, AND, OR, LT_EQ, GT_EQ
|
||||
};
|
||||
|
||||
enum node_type {
|
||||
OP, FIELD, STRING, INT
|
||||
};
|
||||
|
||||
union node_value {
|
||||
enum operation op;
|
||||
char *fieldname;
|
||||
char *string_literal;
|
||||
int int_literal;
|
||||
};
|
||||
|
||||
typedef struct node {
|
||||
struct node *left_child;
|
||||
struct node *right_child;
|
||||
enum node_type type;
|
||||
union node_value value;
|
||||
} node_t;
|
||||
|
||||
node_t* alloc_node();
|
||||
|
||||
node_t* make_op_node(enum operation op);
|
||||
|
||||
node_t* make_field_node(char *fieldname);
|
||||
|
||||
node_t* make_string_node(char *literal);
|
||||
|
||||
node_t* make_int_node(int literal);
|
||||
|
||||
int evaluate_expression(node_t *root);
|
||||
|
||||
void print_expression(node_t *root);
|
||||
|
||||
#endif /* ZMAP_TREE_H */
|
303
filter_sandbox/y.output
Normal file
303
filter_sandbox/y.output
Normal file
@ -0,0 +1,303 @@
|
||||
Grammar
|
||||
|
||||
0 $accept: filter_expr $end
|
||||
|
||||
1 filter_expr: filter_expr T_OR filter_expr
|
||||
2 | filter_expr T_AND filter_expr
|
||||
3 | '(' filter_expr ')'
|
||||
4 | filter
|
||||
|
||||
5 filter: number_filter
|
||||
6 | string_filter
|
||||
|
||||
7 number_filter: T_FIELD '=' T_NUMBER
|
||||
8 | T_FIELD '>' T_NUMBER
|
||||
9 | T_FIELD '<' T_NUMBER
|
||||
10 | T_FIELD T_NOT_EQ T_NUMBER
|
||||
11 | T_FIELD T_GT_EQ T_NUMBER
|
||||
12 | T_FIELD T_LT_EQ T_NUMBER
|
||||
|
||||
13 string_filter: T_FIELD '=' T_FIELD
|
||||
14 | T_FIELD T_NOT_EQ T_FIELD
|
||||
|
||||
|
||||
Terminals, with rules where they appear
|
||||
|
||||
$end (0) 0
|
||||
'(' (40) 3
|
||||
')' (41) 3
|
||||
'<' (60) 9
|
||||
'=' (61) 7 13
|
||||
'>' (62) 8
|
||||
error (256)
|
||||
T_AND (258) 2
|
||||
T_OR (259) 1
|
||||
T_NUMBER (260) 7 8 9 10 11 12
|
||||
T_FIELD (261) 7 8 9 10 11 12 13 14
|
||||
T_NOT_EQ (262) 10 14
|
||||
T_GT_EQ (263) 11
|
||||
T_LT_EQ (264) 12
|
||||
|
||||
|
||||
Nonterminals, with rules where they appear
|
||||
|
||||
$accept (15)
|
||||
on left: 0
|
||||
filter_expr (16)
|
||||
on left: 1 2 3 4, on right: 0 1 2 3
|
||||
filter (17)
|
||||
on left: 5 6, on right: 4
|
||||
number_filter (18)
|
||||
on left: 7 8 9 10 11 12, on right: 5
|
||||
string_filter (19)
|
||||
on left: 13 14, on right: 6
|
||||
|
||||
|
||||
state 0
|
||||
|
||||
0 $accept: . filter_expr $end
|
||||
|
||||
'(' shift, and go to state 1
|
||||
T_FIELD shift, and go to state 2
|
||||
|
||||
filter_expr go to state 3
|
||||
filter go to state 4
|
||||
number_filter go to state 5
|
||||
string_filter go to state 6
|
||||
|
||||
|
||||
state 1
|
||||
|
||||
3 filter_expr: '(' . filter_expr ')'
|
||||
|
||||
'(' shift, and go to state 1
|
||||
T_FIELD shift, and go to state 2
|
||||
|
||||
filter_expr go to state 7
|
||||
filter go to state 4
|
||||
number_filter go to state 5
|
||||
string_filter go to state 6
|
||||
|
||||
|
||||
state 2
|
||||
|
||||
7 number_filter: T_FIELD . '=' T_NUMBER
|
||||
8 | T_FIELD . '>' T_NUMBER
|
||||
9 | T_FIELD . '<' T_NUMBER
|
||||
10 | T_FIELD . T_NOT_EQ T_NUMBER
|
||||
11 | T_FIELD . T_GT_EQ T_NUMBER
|
||||
12 | T_FIELD . T_LT_EQ T_NUMBER
|
||||
13 string_filter: T_FIELD . '=' T_FIELD
|
||||
14 | T_FIELD . T_NOT_EQ T_FIELD
|
||||
|
||||
T_NOT_EQ shift, and go to state 8
|
||||
'>' shift, and go to state 9
|
||||
T_GT_EQ shift, and go to state 10
|
||||
'<' shift, and go to state 11
|
||||
'=' shift, and go to state 12
|
||||
T_LT_EQ shift, and go to state 13
|
||||
|
||||
|
||||
state 3
|
||||
|
||||
0 $accept: filter_expr . $end
|
||||
1 filter_expr: filter_expr . T_OR filter_expr
|
||||
2 | filter_expr . T_AND filter_expr
|
||||
|
||||
$end shift, and go to state 14
|
||||
T_AND shift, and go to state 15
|
||||
T_OR shift, and go to state 16
|
||||
|
||||
|
||||
state 4
|
||||
|
||||
4 filter_expr: filter .
|
||||
|
||||
$default reduce using rule 4 (filter_expr)
|
||||
|
||||
|
||||
state 5
|
||||
|
||||
5 filter: number_filter .
|
||||
|
||||
$default reduce using rule 5 (filter)
|
||||
|
||||
|
||||
state 6
|
||||
|
||||
6 filter: string_filter .
|
||||
|
||||
$default reduce using rule 6 (filter)
|
||||
|
||||
|
||||
state 7
|
||||
|
||||
1 filter_expr: filter_expr . T_OR filter_expr
|
||||
2 | filter_expr . T_AND filter_expr
|
||||
3 | '(' filter_expr . ')'
|
||||
|
||||
')' shift, and go to state 17
|
||||
T_AND shift, and go to state 15
|
||||
T_OR shift, and go to state 16
|
||||
|
||||
|
||||
state 8
|
||||
|
||||
10 number_filter: T_FIELD T_NOT_EQ . T_NUMBER
|
||||
14 string_filter: T_FIELD T_NOT_EQ . T_FIELD
|
||||
|
||||
T_NUMBER shift, and go to state 18
|
||||
T_FIELD shift, and go to state 19
|
||||
|
||||
|
||||
state 9
|
||||
|
||||
8 number_filter: T_FIELD '>' . T_NUMBER
|
||||
|
||||
T_NUMBER shift, and go to state 20
|
||||
|
||||
|
||||
state 10
|
||||
|
||||
11 number_filter: T_FIELD T_GT_EQ . T_NUMBER
|
||||
|
||||
T_NUMBER shift, and go to state 21
|
||||
|
||||
|
||||
state 11
|
||||
|
||||
9 number_filter: T_FIELD '<' . T_NUMBER
|
||||
|
||||
T_NUMBER shift, and go to state 22
|
||||
|
||||
|
||||
state 12
|
||||
|
||||
7 number_filter: T_FIELD '=' . T_NUMBER
|
||||
13 string_filter: T_FIELD '=' . T_FIELD
|
||||
|
||||
T_NUMBER shift, and go to state 23
|
||||
T_FIELD shift, and go to state 24
|
||||
|
||||
|
||||
state 13
|
||||
|
||||
12 number_filter: T_FIELD T_LT_EQ . T_NUMBER
|
||||
|
||||
T_NUMBER shift, and go to state 25
|
||||
|
||||
|
||||
state 14
|
||||
|
||||
0 $accept: filter_expr $end .
|
||||
|
||||
$default accept
|
||||
|
||||
|
||||
state 15
|
||||
|
||||
2 filter_expr: filter_expr T_AND . filter_expr
|
||||
|
||||
'(' shift, and go to state 1
|
||||
T_FIELD shift, and go to state 2
|
||||
|
||||
filter_expr go to state 26
|
||||
filter go to state 4
|
||||
number_filter go to state 5
|
||||
string_filter go to state 6
|
||||
|
||||
|
||||
state 16
|
||||
|
||||
1 filter_expr: filter_expr T_OR . filter_expr
|
||||
|
||||
'(' shift, and go to state 1
|
||||
T_FIELD shift, and go to state 2
|
||||
|
||||
filter_expr go to state 27
|
||||
filter go to state 4
|
||||
number_filter go to state 5
|
||||
string_filter go to state 6
|
||||
|
||||
|
||||
state 17
|
||||
|
||||
3 filter_expr: '(' filter_expr ')' .
|
||||
|
||||
$default reduce using rule 3 (filter_expr)
|
||||
|
||||
|
||||
state 18
|
||||
|
||||
10 number_filter: T_FIELD T_NOT_EQ T_NUMBER .
|
||||
|
||||
$default reduce using rule 10 (number_filter)
|
||||
|
||||
|
||||
state 19
|
||||
|
||||
14 string_filter: T_FIELD T_NOT_EQ T_FIELD .
|
||||
|
||||
$default reduce using rule 14 (string_filter)
|
||||
|
||||
|
||||
state 20
|
||||
|
||||
8 number_filter: T_FIELD '>' T_NUMBER .
|
||||
|
||||
$default reduce using rule 8 (number_filter)
|
||||
|
||||
|
||||
state 21
|
||||
|
||||
11 number_filter: T_FIELD T_GT_EQ T_NUMBER .
|
||||
|
||||
$default reduce using rule 11 (number_filter)
|
||||
|
||||
|
||||
state 22
|
||||
|
||||
9 number_filter: T_FIELD '<' T_NUMBER .
|
||||
|
||||
$default reduce using rule 9 (number_filter)
|
||||
|
||||
|
||||
state 23
|
||||
|
||||
7 number_filter: T_FIELD '=' T_NUMBER .
|
||||
|
||||
$default reduce using rule 7 (number_filter)
|
||||
|
||||
|
||||
state 24
|
||||
|
||||
13 string_filter: T_FIELD '=' T_FIELD .
|
||||
|
||||
$default reduce using rule 13 (string_filter)
|
||||
|
||||
|
||||
state 25
|
||||
|
||||
12 number_filter: T_FIELD T_LT_EQ T_NUMBER .
|
||||
|
||||
$default reduce using rule 12 (number_filter)
|
||||
|
||||
|
||||
state 26
|
||||
|
||||
1 filter_expr: filter_expr . T_OR filter_expr
|
||||
2 | filter_expr . T_AND filter_expr
|
||||
2 | filter_expr T_AND filter_expr .
|
||||
|
||||
$default reduce using rule 2 (filter_expr)
|
||||
|
||||
|
||||
state 27
|
||||
|
||||
1 filter_expr: filter_expr . T_OR filter_expr
|
||||
1 | filter_expr T_OR filter_expr .
|
||||
2 | filter_expr . T_AND filter_expr
|
||||
|
||||
T_AND shift, and go to state 15
|
||||
|
||||
$default reduce using rule 1 (filter_expr)
|
1687
filter_sandbox/y.tab.c
Normal file
1687
filter_sandbox/y.tab.c
Normal file
File diff suppressed because it is too large
Load Diff
80
filter_sandbox/y.tab.h
Normal file
80
filter_sandbox/y.tab.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* A Bison parser, made by GNU Bison 2.3. */
|
||||
|
||||
/* Skeleton interface for Bison's Yacc-like parsers in C
|
||||
|
||||
Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* As a special exception, you may create a larger work that contains
|
||||
part or all of the Bison parser skeleton and distribute that work
|
||||
under terms of your choice, so long as that work isn't itself a
|
||||
parser generator using the skeleton or a modified version thereof
|
||||
as a parser skeleton. Alternatively, if you modify or redistribute
|
||||
the parser skeleton itself, you may (at your option) remove this
|
||||
special exception, which will cause the skeleton and the resulting
|
||||
Bison output files to be licensed under the GNU General Public
|
||||
License without this special exception.
|
||||
|
||||
This special exception was added by the Free Software Foundation in
|
||||
version 2.2 of Bison. */
|
||||
|
||||
/* Tokens. */
|
||||
#ifndef YYTOKENTYPE
|
||||
# define YYTOKENTYPE
|
||||
/* Put the tokens into the symbol table, so that GDB and other debuggers
|
||||
know about them. */
|
||||
enum yytokentype {
|
||||
T_AND = 258,
|
||||
T_OR = 259,
|
||||
T_NUMBER = 260,
|
||||
T_FIELD = 261,
|
||||
T_NOT_EQ = 262,
|
||||
T_GT_EQ = 263,
|
||||
T_LT_EQ = 264
|
||||
};
|
||||
#endif
|
||||
/* Tokens. */
|
||||
#define T_AND 258
|
||||
#define T_OR 259
|
||||
#define T_NUMBER 260
|
||||
#define T_FIELD 261
|
||||
#define T_NOT_EQ 262
|
||||
#define T_GT_EQ 263
|
||||
#define T_LT_EQ 264
|
||||
|
||||
|
||||
|
||||
|
||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
|
||||
typedef union YYSTYPE
|
||||
#line 24 "zmap.y"
|
||||
{
|
||||
int int_literal;
|
||||
char *string_literal;
|
||||
struct node *expr;
|
||||
}
|
||||
/* Line 1529 of yacc.c. */
|
||||
#line 73 "y.tab.h"
|
||||
YYSTYPE;
|
||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
|
||||
# define YYSTYPE_IS_DECLARED 1
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
22
filter_sandbox/zmap.l
Normal file
22
filter_sandbox/zmap.l
Normal file
@ -0,0 +1,22 @@
|
||||
%{
|
||||
#include <string.h>
|
||||
#include "y.tab.h"
|
||||
%}
|
||||
|
||||
%%
|
||||
[0-9]+ yylval.int_literal = atoi(yytext); return T_NUMBER;
|
||||
\n /* Ignore end of line */
|
||||
[ \t]+ /* Ignore whitespace */
|
||||
!= return T_NOT_EQ;
|
||||
>= return T_GT_EQ;
|
||||
"<=" return T_LT_EQ;
|
||||
&& return T_AND;
|
||||
"||" return T_OR;
|
||||
= return '=';
|
||||
">" return '>';
|
||||
"<" return '<';
|
||||
"(" return '(';
|
||||
")" return ')';
|
||||
[a-zA-Z][a-zA-Z0-9]+ yylval.string_literal = strdup(yytext); return T_FIELD;
|
||||
|
||||
%%
|
134
filter_sandbox/zmap.y
Normal file
134
filter_sandbox/zmap.y
Normal file
@ -0,0 +1,134 @@
|
||||
%{
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "tree.h"
|
||||
|
||||
void yyerror(const char *str)
|
||||
{
|
||||
fprintf(stderr,"error: %s\n",str);
|
||||
fprintf(stderr, "%s\n", "YOLO");
|
||||
}
|
||||
|
||||
int yywrap()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
yyparse();
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
int int_literal;
|
||||
char *string_literal;
|
||||
struct node *expr;
|
||||
}
|
||||
|
||||
%token '(' ')' T_AND T_OR
|
||||
%token <int_literal> T_NUMBER
|
||||
%token <string_literal> T_FIELD
|
||||
%token T_NOT_EQ T_GT_EQ '>' '<' '=' T_LT_EQ
|
||||
|
||||
%left T_OR
|
||||
%left T_AND
|
||||
|
||||
%type <expr> filter
|
||||
%type <expr> number_filter
|
||||
%type <expr> string_filter
|
||||
%type <expr> filter_expr
|
||||
|
||||
|
||||
%%
|
||||
|
||||
filter_expr:
|
||||
filter_expr T_OR filter_expr
|
||||
{
|
||||
$$ = make_op_node(OR);
|
||||
$$->left_child = $1;
|
||||
$$->right_child = $3;
|
||||
print_expression($$);
|
||||
printf("%s\n", "");
|
||||
}
|
||||
| filter_expr T_AND filter_expr
|
||||
{
|
||||
$$ = make_op_node(AND);
|
||||
$$->left_child = $1;
|
||||
$$->right_child = $3;
|
||||
print_expression($$);
|
||||
printf("%s\n", "");
|
||||
}
|
||||
| '(' filter_expr ')'
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| filter
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
filter: number_filter
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| string_filter
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
number_filter: T_FIELD '=' T_NUMBER
|
||||
{
|
||||
printf("number_filter: %s = %d\n", $1, $3);
|
||||
$$ = make_op_node(EQ);
|
||||
$$->left_child = make_field_node($1);
|
||||
$$->right_child = make_int_node($3);
|
||||
}
|
||||
|
|
||||
T_FIELD '>' T_NUMBER
|
||||
{
|
||||
printf("number_filter: %s > %d\n", $1, $3);
|
||||
$$ = make_op_node(GT);
|
||||
$$->left_child = make_field_node($1);
|
||||
$$->right_child = make_int_node($3);
|
||||
}
|
||||
|
|
||||
T_FIELD '<' T_NUMBER
|
||||
{
|
||||
printf("number_filter: %s < %d\n", $1, $3);
|
||||
}
|
||||
|
|
||||
T_FIELD T_NOT_EQ T_NUMBER
|
||||
{
|
||||
printf("number_filter: %s != %d\n", $1, $3);
|
||||
}
|
||||
|
|
||||
T_FIELD T_GT_EQ T_NUMBER
|
||||
{
|
||||
printf("number_filter: %s >= %d\n", $1, $3);
|
||||
}
|
||||
|
|
||||
T_FIELD T_LT_EQ T_NUMBER
|
||||
{
|
||||
printf("number_filter: %s <= %d\n", $1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
string_filter:
|
||||
T_FIELD '=' T_FIELD
|
||||
{
|
||||
printf("string_filter %s = %s\n", $1, $3);
|
||||
}
|
||||
|
|
||||
T_FIELD T_NOT_EQ T_FIELD
|
||||
{
|
||||
printf("string_filter: %s != %s\n", $1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user