blob: df84ef895e149f7315b56c47cf9f3fc883780071 [file] [log] [blame]
/**
* 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.
*/
%skeleton "lalr1.cc"
%require "3.0"
%define api.namespace {org::apache::nifi::minifi::expression}
%parse-param {Driver* driver}
%locations
%define parser_class_name {Parser}
%define parse.error verbose
%define api.value.type variant
%define parse.assert
%define api.token.prefix {TOK_}
%code requires
{
#include <string>
#include <expression/Expression.h>
#include "location.hh"
namespace org {
namespace apache {
namespace nifi {
namespace minifi {
namespace expression {
class Driver;
} /* namespace expression */
} /* namespace minifi */
} /* namespace nifi */
} /* namespace apache */
} /* namespace org */
}
%code
{
#include <utility>
#include <memory>
#include <functional>
#include <expression/Expression.h>
#include "Driver.h"
#undef yylex
#define yylex driver->lex
}
%token
END 0 "eof"
NEWLINE "\n"
DOLLAR "$"
LCURLY "{"
RCURLY "}"
LPAREN "("
RPAREN ")"
LSQUARE "["
RSQUARE "]"
PIPE "|"
MINUS "-"
COMMA ","
COLON ":"
SEMI ";"
FSLASH "/"
BSLASH "\\"
STAR "*"
HASH "#"
SQUOTE "'"
DQUOTE "\""
;
%token <std::string> TRUE "true"
%token <std::string> FALSE "false"
%token <std::string> IDENTIFIER "identifier"
%token <std::string> MISC "misc"
%token <std::string> WHITESPACE "whitespace"
%token <std::string> NUMBER "number"
%type <std::string> exp_whitespace
%type <std::string> exp_whitespaces
%type <std::string> attr_id
%type <Expression> fn_call
%type <Expression> fn_arg
%type <std::vector<Expression>> fn_args
%type <Expression> exp_content
%type <Expression> exp_content_val
%type <Expression> exp
%type <Expression> exps
%type <std::string> text_no_quote_no_dollar
%type <std::string> text_inc_quote_escaped_dollar
%type <std::string> text_inc_dollar
%type <std::string> quoted_text
%type <std::string> quoted_text_content
%type <Expression> text_or_exp
%type <std::vector<std::pair<std::string, std::vector<Expression>>>> fn_calls
%%
%start root;
root: exps { driver->result = $1; }
;
text_no_quote_no_dollar: IDENTIFIER { std::swap($$, $1); }
| WHITESPACE { std::swap($$, $1); }
| NEWLINE { $$ = "\n"; }
| MISC { std::swap($$, $1); }
| LCURLY { $$ = "{"; }
| RCURLY { $$ = "}"; }
| LPAREN { $$ = "("; }
| RPAREN { $$ = ")"; }
| LSQUARE { $$ = "["; }
| RSQUARE { $$ = "]"; }
| PIPE { $$ = "|"; }
| COMMA { $$ = ","; }
| COLON { $$ = ":"; }
| TRUE { $$ = std::string("true"); }
| FALSE { $$ = std::string("false"); }
| SEMI { $$ = ";"; }
| FSLASH { $$ = "/"; }
| STAR { $$ = "*"; }
| HASH { $$ = "#"; }
| NUMBER { std::swap($$, $1); }
;
text_inc_quote_escaped_dollar: text_no_quote_no_dollar { std::swap($$, $1); }
| SQUOTE { $$ = "'"; }
| DQUOTE { $$ = "\""; }
| BSLASH { $$ = "\\"; }
| DOLLAR DOLLAR { $$ = "$"; }
;
text_inc_dollar: text_no_quote_no_dollar { std::swap($$, $1); }
| DOLLAR { $$ = "$"; }
| BSLASH SQUOTE { $$ = "'"; }
| BSLASH DQUOTE { $$ = "\""; }
| BSLASH BSLASH { $$ = "\\"; }
;
quoted_text_content: %empty {}
| quoted_text_content text_inc_dollar { $$ = $1 + $2; }
;
quoted_text: SQUOTE quoted_text_content SQUOTE { std::swap($$, $2); }
| DQUOTE quoted_text_content DQUOTE { std::swap($$, $2); }
;
text_or_exp: text_inc_quote_escaped_dollar { $$ = make_static(std::move($1)); }
| exp { $$ = $1; }
;
exps: %empty {}
| exps text_or_exp { $$ = $1 + $2; }
;
exp_whitespace: WHITESPACE {}
| NEWLINE {}
;
exp_whitespaces: %empty {}
| exp_whitespaces exp_whitespace {}
;
attr_id: quoted_text exp_whitespaces { std::swap($$, $1); }
| IDENTIFIER exp_whitespaces { std::swap($$, $1); }
;
fn_arg: quoted_text exp_whitespaces { $$ = make_static($1); }
| NUMBER exp_whitespaces { $$ = make_static($1); }
| TRUE { $$ = Expression(Value(true)); }
| FALSE { $$ = Expression(Value(false)); }
| exp exp_whitespaces { $$ = $1; }
;
fn_args: %empty {}
| fn_args COMMA exp_whitespaces fn_arg { $$.insert($$.end(), $1.begin(), $1.end()); $$.push_back($4); }
| fn_arg { $$.push_back($1); }
fn_call: attr_id LPAREN exp_whitespaces fn_args RPAREN exp_whitespaces { $$ = make_dynamic_function(std::move($1), $4); }
fn_calls: %empty {}
| COLON exp_whitespaces attr_id LPAREN exp_whitespaces fn_args RPAREN exp_whitespaces fn_calls { $$.push_back({$3, $6}); $$.insert($$.end(), $9.begin(), $9.end()); }
;
exp_content_val: attr_id { $$ = make_dynamic_attr(std::move($1)); }
| fn_call { $$ = $1; }
;
exp_content: exp_content_val fn_calls { $$ = make_function_composition($1, $2); }
;
exp: DOLLAR LCURLY exp_whitespaces exp_content RCURLY { $$ = $4; }
;
%%
void org::apache::nifi::minifi::expression::Parser::error(const location_type &location,
const std::string &message) {
std::stringstream err_msg;
err_msg << location;
err_msg << ": ";
err_msg << message;
throw std::runtime_error(err_msg.str());
}