blob: 5b2cb89bfa612c567bef65922439576b93deaf98 [file]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// use C++ parser skeleton
%language "c++"
//use strong type, class encapsulated LALR(1) parser
%skeleton "lalr1.cc"
//store all values in std::variant (strong type)
%define api.value.type variant
//automatically generate constructor for tokens (convenient for C++)
%define api.token.constructor
//generated parser class is `wkt_::parser`
%define api.prefix {wkt_}
%defines
/* ------------------------------
* 1. Headers and forward declarations placed in the .hpp file
* **Generate location**:wkt_yacc.y.hpp(beginning)
* **Useage**:Provide types and forward declarations for the parser and external callers
* ------------------------------ */
%code requires {
#include <memory>
#include <variant>
#include <vector>
#include "exprs/function/geo/wkt_parse_ctx.h" // we need WktParseContext to pass scaninfo to lexer
#include "common/logging.h"
#include "exprs/function/geo/wkt_parse_type.h"
#include "exprs/function/geo/geo_types.h"
struct WktParseContext;
}
/* ------------------------------
* 2. The function declarations provided to the lexer for calls are placed in the .hpp file.
* **Generate location**:wkt_yacc.y.hpp(ending)
* **Useage**:The lexer interacts with the parser, returning tokens.
* ------------------------------ */
%code provides {
wkt_::parser::symbol_type wkt_lex(WktParseContext* ctx, yyscan_t scanner);
}
/* ------------------------------
* 3. The parser member function implementation is placed in the .cpp file.
* **Generate location**:wkt_yacc.y.cpp
* **Useage**:Parser internal use, for example error() implementation
* ------------------------------ */
%code {
#include <string>
#include "common/exception.h"
namespace wkt_ {
// For syntax errors(e.g., `POIN(1 2)`, `POINT(1, 2)`), parser::error() does nothing.
// The parse_wkt() function will set ctx.parse_status to GEO_PARSE_WKT_SYNTAX_ERROR.
// For semantic errors (e.g., invalid coordinates), ctx.parse_status is set
// in the grammar rules before calling YYABORT.
void parser::error(const std::string& msg) {}
} // namespace wkt_
}
%parse-param { WktParseContext* ctx }
%parse-param { yyscan_t scanner }
%lex-param { WktParseContext* ctx }
%lex-param { yyscan_t scanner }
%expect 0
%start shape
/* keyword for */
%token KW_POINT KW_LINESTRING KW_POLYGON
%token KW_MULTI_POINT KW_MULTI_LINESTRING KW_MULTI_POLYGON
%token <double> NUMERIC
%type <std::monostate> shape
%type <std::unique_ptr<doris::GeoShape>> point linestring polygon multi_polygon
%type <std::unique_ptr<doris::GeoCoordinate>> coordinate
%type <std::unique_ptr<doris::GeoCoordinateList>> coordinate_list
%type <std::unique_ptr<doris::GeoCoordinateListList>> coordinate_list_list
%type <std::unique_ptr<std::vector<doris::GeoCoordinateListList>>> multi_polygon_list
%%
shape:
point
{ ctx->shape = std::move($1); }
| linestring
{ ctx->shape = std::move($1); }
| polygon
{ ctx->shape = std::move($1); }
| multi_polygon
{ ctx->shape = std::move($1); }
;
point:
KW_POINT '(' coordinate ')'
{
std::unique_ptr<doris::GeoPoint> point = doris::GeoPoint::create_unique();
const doris::GeoCoordinate& coord = *$3;
ctx->parse_status = point->from_coord(coord);
if (ctx->parse_status != doris::GEO_PARSE_OK) {
YYABORT;
}
std::unique_ptr<doris::GeoShape> shape = std::move(point);
yylhs.value.emplace<std::unique_ptr<doris::GeoShape>>(std::move(shape));
}
;
linestring:
KW_LINESTRING '(' coordinate_list ')'
{
// to avoid memory leak
std::unique_ptr<doris::GeoCoordinateList> list = std::move($3);
std::unique_ptr<doris::GeoLine> line = doris::GeoLine::create_unique();
ctx->parse_status = line->from_coords(*list);
if (ctx->parse_status != doris::GEO_PARSE_OK) {
YYABORT;
}
std::unique_ptr<doris::GeoShape> shape = std::move(line);
yylhs.value.emplace<std::unique_ptr<doris::GeoShape>>(std::move(shape));
}
;
polygon:
KW_POLYGON '(' coordinate_list_list ')'
{
// to avoid memory leak
std::unique_ptr<doris::GeoCoordinateListList> list = std::move($3);
std::unique_ptr<doris::GeoPolygon> polygon = doris::GeoPolygon::create_unique();
ctx->parse_status = polygon->from_coords(*list);
if (ctx->parse_status != doris::GEO_PARSE_OK) {
YYABORT;
}
std::unique_ptr<doris::GeoShape> shape = std::move(polygon);
yylhs.value.emplace<std::unique_ptr<doris::GeoShape>>(std::move(shape));
}
;
multi_polygon:
KW_MULTI_POLYGON '(' multi_polygon_list ')'
{
// to avoid memory leak
std::unique_ptr<std::vector<doris::GeoCoordinateListList>> list = std::move($3);
std::unique_ptr<doris::GeoMultiPolygon> multi_polygon = doris::GeoMultiPolygon::create_unique();
ctx->parse_status = multi_polygon->from_coords(*list);
if (ctx->parse_status != doris::GEO_PARSE_OK) {
YYABORT;
}
std::unique_ptr<doris::GeoShape> shape = std::move(multi_polygon);
yylhs.value.emplace<std::unique_ptr<doris::GeoShape>>(std::move(shape));
}
;
multi_polygon_list:
multi_polygon_list ',' '(' coordinate_list_list ')'
{
auto vec = std::move($1);
auto list = std::move($4);
vec->push_back(std::move(*list));
yylhs.value.emplace<std::unique_ptr<std::vector<doris::GeoCoordinateListList>>>(std::move(vec));
}
| '(' coordinate_list_list ')'
{
auto list = std::move($2);
auto vec = std::make_unique<std::vector<doris::GeoCoordinateListList>>();
vec->push_back(std::move(*list));
yylhs.value.emplace<std::unique_ptr<std::vector<doris::GeoCoordinateListList>>>(std::move(vec));
}
;
coordinate_list_list:
coordinate_list_list ',' '(' coordinate_list ')'
{
auto outer = std::move($1);
auto inner = std::move($4);
outer->add(std::move(inner));
yylhs.value.emplace<std::unique_ptr<doris::GeoCoordinateListList>>(std::move(outer));
}
| '(' coordinate_list ')'
{
auto inner = std::move($2);
auto outer = std::make_unique<doris::GeoCoordinateListList>();
outer->add(std::move(inner));
yylhs.value.emplace<std::unique_ptr<doris::GeoCoordinateListList>>(std::move(outer));
}
;
coordinate_list:
coordinate_list ',' coordinate
{
auto list = std::move($1);
auto coord = std::move($3);
list->add(*coord);
yylhs.value.emplace<std::unique_ptr<doris::GeoCoordinateList>>(std::move(list));
}
| coordinate
{
auto coord = std::move($1);
auto list = std::make_unique<doris::GeoCoordinateList>();
list->add(*coord);
yylhs.value.emplace<std::unique_ptr<doris::GeoCoordinateList>>(std::move(list));
}
;
coordinate:
NUMERIC NUMERIC
{
auto coord = std::make_unique<doris::GeoCoordinate>();
coord->x = $1;
coord->y = $2;
yylhs.value.emplace<std::unique_ptr<doris::GeoCoordinate>>(std::move(coord));
}
;