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