Skip to content

Commit

Permalink
Use bison instead of bison++
Browse files Browse the repository at this point in the history
Signed-off-by: Kunlin Yu <[email protected]>
  • Loading branch information
kunlinyu committed Dec 31, 2024
1 parent 2a9a244 commit 6f19f2d
Show file tree
Hide file tree
Showing 11 changed files with 233 additions and 180 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Build directory
build
build_dbg

# Prerequisites
*.d
Expand Down
14 changes: 11 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,23 @@ set(BISON_FILE ${CMAKE_SOURCE_DIR}/src/cql2_parser.y)
set(BISON_OUTPUT ${CMAKE_BINARY_DIR}/cql2_parser_base.cc)
add_custom_command(
OUTPUT ${BISON_OUTPUT}
COMMAND bison++ -v -d -o ${BISON_OUTPUT} ${BISON_FILE}
COMMAND bison -v -d -o ${BISON_OUTPUT} ${BISON_FILE}
DEPENDS ${BISON_FILE}
COMMENT "Generating ${BISON_OUTPUT} from ${BISON_FILE} using bison++"
COMMENT "Generating ${BISON_OUTPUT} from ${BISON_FILE} using bison"
)

add_definitions(-DUSE_UNSTABLE_GEOS_CPP_API)

set(CQL2CPP_SRC
src/id_generator.cc
src/ast_node.cc
src/global_yylex.cc
${FLEX_OUTPUT}
${BISON_OUTPUT}
)

# library
add_library(cql2cpp src/id_generator.cc src/ast_node.cc ${FLEX_OUTPUT} ${BISON_OUTPUT})
add_library(cql2cpp ${CQL2CPP_SRC})
target_compile_options(cql2cpp PRIVATE -Wno-register -Wno-write-strings)
target_link_libraries(cql2cpp GEOS::geos glog::glog)

Expand Down
2 changes: 1 addition & 1 deletion dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ RUN apt-get install -y gcc-aarch64-linux-gnu
RUN apt-get install -y g++-aarch64-linux-gnu

# install dependencies
RUN apt-get install -y flex bison++
RUN apt-get install -y flex bison
RUN apt-get install -y libgflags-dev libgoogle-glog-dev libgtest-dev
RUN apt-get install -y libgeos++-dev

Expand Down
11 changes: 4 additions & 7 deletions include/cql2cpp/cql2_lexer-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,16 @@

#pragma once

#include <cql2_parser_base.h>

#include <cql2_parser_base.hh>
#include <istream>
#include <ostream>
#include <string>
#include <list>

// This file will be part of cc file generated by flex++.
// And the #include<FlexLexer.h> will appear above this file
// https://stackoverflow.com/questions/71300080/change-yylex-in-c-flex
class Cql2Lexer : public yyFlexLexer {
private:
yy_Cql2ParserBase_stype* lval_;
std::list<std::string> token_texts_;
cql2cpp::Cql2ParserBase::value_type* yylval_;

public:
Cql2Lexer() : yyFlexLexer() {}
Expand All @@ -32,5 +28,6 @@ class Cql2Lexer : public yyFlexLexer {

int yylex();

void RegisterLval(yy_Cql2ParserBase_stype* lval) { lval_ = lval; }
void set_yylval(cql2cpp::Cql2ParserBase::value_type* yylval) { yylval_ = yylval; }

};
16 changes: 6 additions & 10 deletions include/cql2cpp/cql2_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,19 @@
#include <FlexLexer.h>
#include <glog/logging.h>

#include <cql2_parser_base.h>
#include <cql2_parser_base.hh>

class Cql2Parser : public Cql2ParserBase {
class Cql2Parser : public cql2cpp::Cql2ParserBase {
private:
FlexLexer* lexer_;
cql2cpp::AstNode* root_;

public:
Cql2Parser(FlexLexer* lexer) : lexer_(lexer) {
yydebug = false;
}
Cql2Parser() : cql2cpp::Cql2ParserBase(&root_) {}

void yyerror(char* s) override {
LOG(ERROR) << "Cql2Parser Error: " << s << std::endl;
void error(const std::string& msg) override {
LOG(ERROR) << "Cql2Parser Error: " << msg << std::endl;
}

int yylex() override { return lexer_->yylex(); }

cql2cpp::AstNode* root() const { return root_; }

void DeConstructRoot() {
Expand Down
9 changes: 5 additions & 4 deletions include/cql2cpp/cql2cpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "feature_source.h"
#include "node_evaluator.h"
#include "tree_dot.h"
#include "global_yylex.h"

namespace cql2cpp {

Expand Down Expand Up @@ -121,13 +122,13 @@ class Cql2Cpp {
std::string* error_msg) {
std::istringstream iss(cql2_query);
std::ostringstream oss;
Cql2Lexer* lexer = new Cql2Lexer(iss, oss);

set_text_lexer(new Cql2Lexer(iss, oss));

cql2cpp::AstNode::set_ostream(&oss);
Cql2Parser parser(lexer);
lexer->RegisterLval(&parser.yylval);

int ret = parser.yyparse();
Cql2Parser parser;
int ret = parser.parse();
if (error_msg != nullptr) *error_msg = oss.str();
if (ret == 0) {
*root = parser.root();
Expand Down
26 changes: 26 additions & 0 deletions include/cql2cpp/global_yylex.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* File Name: global_yylex.h
*
* Copyright (c) 2024 IndoorSpatial
*
* Author: Kunlin Yu <[email protected]>
* Create Date: 2024/12/31
*
*/

#pragma once

#include <cql2_parser_base.hh>

enum LexerInstance {
CQL2_TEXT,
};

void set_current_lexer(LexerInstance lexer);

class Cql2Lexer;
void set_text_lexer(Cql2Lexer* lexer);

// bison expect a global yylex
// https://www.gnu.org/software/bison/manual/bison.html#C_002b_002b-Scanner-Interface
int yylex(cql2cpp::Cql2ParserBase::value_type* yylval);
153 changes: 74 additions & 79 deletions src/cql2_lexer.l
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
%{
#include <cql2_parser_base.hh>
#include <cql2cpp/cql2_lexer-internal.h>
#include <cql2_parser_base.h>

using cql2cpp::Cql2ParserBase;

void print(const std::string& prefix, const char* yytext) {
LOG(INFO) << "TOKEN " << prefix << " \"" << yytext << "\"";
}

%}

%option noyywrap
Expand All @@ -12,156 +19,144 @@ CHAR_LIT \'[^\']*\'
%%

{CHAR_LIT} {
yyout << "TOKEN CHAR_LIT " << yytext << std::endl;
token_texts_.emplace_back(yytext);
lval_->str = token_texts_.back().c_str();
return Cql2ParserBase::CHAR_LIT;
print("CHAR_LIT", yytext);
yylval_->emplace<std::string>() = yytext;
return Cql2ParserBase::token::CHAR_LIT;
}

[+-]?{DIGIT}+ {
yyout << "TOKEN NUMBER_INT " << yytext << std::endl;
lval_->num_int = atoi(yytext);
return Cql2ParserBase::NUMBER_INT;
print("DIGIT_INT", yytext);
yylval_->emplace<int>() = atoi(yytext);
return Cql2ParserBase::token::NUMBER_INT;
}

[+-]?{DIGIT}+"."{DIGIT}* {
yyout << "TOKEN NUMBER_FLOAT " << yytext << std::endl;
lval_->num_float = atof(yytext);
return Cql2ParserBase::NUMBER_FLOAT;
print("DIGIT_FLOAT", yytext);
yylval_->emplace<double>() = atof(yytext);
return Cql2ParserBase::token::NUMBER_FLOAT;
}

[+-]?"."{DIGIT}* {
yyout << "TOKEN NUMBER_FLOAT " << yytext << std::endl;
lval_->num_float = atof(yytext);
return Cql2ParserBase::NUMBER_FLOAT;
print("DIGIT_FLOAT", yytext);
yylval_->emplace<double>() = atof(yytext);
return Cql2ParserBase::token::NUMBER_FLOAT;
}

"TRUE" {
yyout << "TOKEN " << yytext << std::endl;
lval_->boolean = true;
return Cql2ParserBase::TRUE;
print("BOOL_LIT", yytext);
yylval_->emplace<bool>() = true;
return Cql2ParserBase::token::TRUE;
}
"FALSE" {
yyout << "TOKEN " << yytext << std::endl;
lval_->boolean = false;
return Cql2ParserBase::FALSE;
print("BOOL_LIT", yytext);
yylval_->emplace<bool>() = false;
return Cql2ParserBase::token::FALSE;
}

"AND" {
yyout << "TOKEN " << yytext << std::endl;
return Cql2ParserBase::AND;
print("BOOL_EXPR", yytext);
return Cql2ParserBase::token::AND;
}

"OR" {
yyout << "TOKEN " << yytext << std::endl;
return Cql2ParserBase::OR;
print("BOOL_EXPR", yytext);
return Cql2ParserBase::token::OR;
}

"NOT" {
yyout << "TOKEN " << yytext << std::endl;
return Cql2ParserBase::NOT;
print("BOOL_EXPR", yytext);
return Cql2ParserBase::token::NOT;
}

"CASEI" {
yyout << "TOKEN " << yytext << std::endl;
return Cql2ParserBase::CASEI;
print("", yytext);
return Cql2ParserBase::token::CASEI;
}

"ACCENTI" {
yyout << "TOKEN " << yytext << std::endl;
return Cql2ParserBase::ACCENTI;
print("", yytext);
return Cql2ParserBase::token::ACCENTI;
}

"(" {
yyout << "TOKEN LPT " << yytext << std::endl;
lval_->c = '(';
return Cql2ParserBase::LPT;
print("LPT", yytext);
return Cql2ParserBase::token::LPT;
}

")" {
yyout << "TOKEN RPT " << yytext << std::endl;
lval_->c = ')';
return Cql2ParserBase::RPT;
print("RPT", yytext);
return Cql2ParserBase::token::RPT;
}

"\"" {
yyout << "TOKEN DQUOTE " << yytext << std::endl;
return Cql2ParserBase::DQUOTE;
print("DQUOTE", yytext);
return Cql2ParserBase::token::DQUOTE;
}
"'" {
yyout << "TOKEN SQUOTE " << yytext << std::endl;
return Cql2ParserBase::SQUOTE;
print("SQUOTE", yytext);
return Cql2ParserBase::token::SQUOTE;
}

"," {
yyout << "TOKEN COMMA " << yytext << std::endl;
lval_->c = ',';
return Cql2ParserBase::COMMA;
print("COMMA", yytext);
return Cql2ParserBase::token::COMMA;
}


S_INTERSECTS|S_EQUALS|S_DISJOINT|S_TOUCHES|S_WITHIN|S_OVERLAPS|S_CROSSES|S_CONTAINS {
yyout << "TOKEN " << yytext << std::endl;
token_texts_.emplace_back(yytext);
lval_->str = token_texts_.back().c_str();
return Cql2ParserBase::SPT_FUNC;
print("SPATIAL", yytext);
yylval_->emplace<std::string>(yytext);
return Cql2ParserBase::token::SPT_FUNC;
}


POINT[Z]?"("[0-9. +\-\n]+")" {
yyout << "TOKEN " << yytext << std::endl;
token_texts_.emplace_back(yytext);
lval_->str = token_texts_.back().c_str();
return Cql2ParserBase::POINT_WKT;
print("GEOMETRY", yytext);
yylval_->emplace<std::string>() = yytext;
return Cql2ParserBase::token::POINT_WKT;
}

LINESTRING[Z]?"("[0-9. +\-,\n]+")" {
yyout << "TOKEN " << yytext << std::endl;
token_texts_.emplace_back(yytext);
lval_->str = token_texts_.back().c_str();
return Cql2ParserBase::LINESTRING_WKT;
print("GEOMETRY", yytext);
yylval_->emplace<std::string>() = yytext;
return Cql2ParserBase::token::LINESTRING_WKT;
}

POLYGON[Z]?"(("[0-9. +\-,\n]+"))" {
yyout << "TOKEN " << yytext << std::endl;
token_texts_.emplace_back(yytext);
lval_->str = token_texts_.back().c_str();
return Cql2ParserBase::POLYGON_WKT;
print("GEOMETRY", yytext);
yylval_->emplace<std::string>() = yytext;
return Cql2ParserBase::token::POLYGON_WKT;
}

BBOX"("[0-9. +\-,\n]+")" {
yyout << "TOKEN " << yytext << std::endl;
token_texts_.emplace_back(yytext);
lval_->str = token_texts_.back().c_str();
return Cql2ParserBase::BBOX_TEXT;
print("BBOX", yytext);
yylval_->emplace<std::string>() = yytext;
return Cql2ParserBase::token::BBOX_TEXT;
}

IN {
yyout << "TOKEN " << yytext << std::endl;
token_texts_.emplace_back(yytext);
lval_->str = token_texts_.back().c_str();
return Cql2ParserBase::IN;
print("IN", yytext);
return Cql2ParserBase::token::IN;
}

{ID} {
yyout << "TOKEN ID " << yytext << std::endl;
token_texts_.emplace_back(yytext);
lval_->str = token_texts_.back().c_str();
return Cql2ParserBase::ID;
print("ID", yytext);
yylval_->emplace<std::string>(yytext);
return Cql2ParserBase::token::ID;
}

"+" { yyout << "TOKEN " << yytext << std::endl; return Cql2ParserBase::PLUS; }
"-" { yyout << "TOKEN " << yytext << std::endl; return Cql2ParserBase::MINUS;}
"*" { yyout << "TOKEN " << yytext << std::endl; return Cql2ParserBase::MULT; }
"/" { yyout << "TOKEN " << yytext << std::endl; return Cql2ParserBase::DIV; }
"=" { yyout << "TOKEN " << yytext << std::endl; return Cql2ParserBase::EQ; }
"<" { yyout << "TOKEN " << yytext << std::endl; return Cql2ParserBase::LT; }
">" { yyout << "TOKEN " << yytext << std::endl; return Cql2ParserBase::GT; }
"+" { print("OP", yytext); return Cql2ParserBase::token::PLUS; }
"-" { print("OP", yytext); return Cql2ParserBase::token::MINUS;}
"*" { print("OP", yytext); return Cql2ParserBase::token::MULT; }
"/" { print("OP", yytext); return Cql2ParserBase::token::DIV; }
"=" { print("OP", yytext); return Cql2ParserBase::token::EQ; }
"<" { print("OP", yytext); return Cql2ParserBase::token::LT; }
">" { print("OP", yytext); return Cql2ParserBase::token::GT; }

"{"[^{}\n]*"}" {/* eat up one-line comments */}

[ \t\n]+ {/* eat up whitespace */}

. { yyout << "Unrecognized character: " << yytext << std::endl; }
. { LOG(INFO) << "Unrecognized character: " << yytext << std::endl; }

%%
Loading

0 comments on commit 6f19f2d

Please sign in to comment.