// Copyright 2021 Google LLC
//
// Licensed 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
//
// https://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.
#ifndef THIRD_PARTY_CEL_CPP_PARSER_SOURCE_FACTORY_H_
#define THIRD_PARTY_CEL_CPP_PARSER_SOURCE_FACTORY_H_
#include
#include
#include
#include
#include "google/api/expr/v1alpha1/syntax.pb.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "antlr4-runtime.h"
#include "parser/internal/CelParser.h"
namespace google::api::expr::parser {
using google::api::expr::v1alpha1::Expr;
class EnrichedSourceInfo {
public:
explicit EnrichedSourceInfo(
std::map> offsets)
: offsets_(std::move(offsets)) {}
const std::map>& offsets() const {
return offsets_;
}
private:
// A map between node_id and pair of start position and end position
std::map> offsets_;
};
// Provide tools to generate expressions during parsing.
// Keeps track of ID and source location information.
// Shares functionality with //third_party/cel/go/parser/helper.go
class SourceFactory {
public:
struct SourceLocation {
SourceLocation(int32_t line, int32_t col, int32_t offset_end,
const std::vector& line_offsets)
: line(line), col(col), offset_end(offset_end) {
if (line == 1) {
offset = col;
} else if (line > 1) {
offset = line_offsets[line - 2] + col;
} else {
offset = -1;
}
}
int32_t line;
int32_t col;
int32_t offset_end;
int32_t offset;
};
struct Error {
Error(std::string message, SourceLocation location)
: message(std::move(message)), location(location) {}
std::string message;
SourceLocation location;
};
enum QuantifierKind {
QUANTIFIER_ALL,
QUANTIFIER_EXISTS,
QUANTIFIER_EXISTS_ONE
};
explicit SourceFactory(absl::string_view expression);
int64_t Id(const antlr4::Token* token);
int64_t Id(antlr4::ParserRuleContext* ctx);
int64_t Id(const SourceLocation& location);
int64_t NextMacroId(int64_t macro_id);
const SourceLocation& GetSourceLocation(int64_t id) const;
static const SourceLocation NoLocation();
Expr NewExpr(int64_t id);
Expr NewExpr(antlr4::ParserRuleContext* ctx);
Expr NewExpr(const antlr4::Token* token);
Expr NewGlobalCall(int64_t id, const std::string& function,
const std::vector& args);
Expr NewGlobalCallForMacro(int64_t macro_id, const std::string& function,
const std::vector& args);
Expr NewReceiverCall(int64_t id, const std::string& function,
const Expr& target, const std::vector& args);
Expr NewIdent(const antlr4::Token* token, const std::string& ident_name);
Expr NewIdentForMacro(int64_t macro_id, const std::string& ident_name);
Expr NewSelect(::cel_parser_internal::CelParser::SelectOrCallContext* ctx,
Expr& operand, const std::string& field);
Expr NewSelectForMacro(int64_t macro_id, const Expr& operand,
const std::string& field);
Expr NewPresenceTestForMacro(int64_t macro_id, const Expr& operand,
const std::string& field);
Expr NewObject(int64_t obj_id, const std::string& type_name,
const std::vector<:createstruct::entry>& entries);
Expr::CreateStruct::Entry NewObjectField(int64_t field_id,
const std::string& field,
const Expr& value);
Expr NewComprehension(int64_t id, const std::string& iter_var,
const Expr& iter_range, const std::string& accu_var,
const Expr& accu_init, const Expr& condition,
const Expr& step, const Expr& result);
Expr FoldForMacro(int64_t macro_id, const std::string& iter_var,
const Expr& iter_range, const std::string& accu_var,
const Expr& accu_init, const Expr& condition,
const Expr& step, const Expr& result);
Expr NewQuantifierExprForMacro(QuantifierKind kind, int64_t macro_id,
const Expr& target,
const std::vector& args);
Expr NewFilterExprForMacro(int64_t macro_id, const Expr& target,
const std::vector& args);
Expr NewList(int64_t list_id, const std::vector& elems);
Expr NewListForMacro(int64_t macro_id, const std::vector& elems);
Expr NewMap(int64_t map_id,
const std::vector<:createstruct::entry>& entries);
Expr NewMapForMacro(int64_t macro_id, const Expr& target,
const std::vector& args);
Expr::CreateStruct::Entry NewMapEntry(int64_t entry_id, const Expr& key,
const Expr& value);
Expr NewLiteralInt(antlr4::ParserRuleContext* ctx, int64_t value);
Expr NewLiteralIntForMacro(int64_t macro_id, int64_t value);
Expr NewLiteralUint(antlr4::ParserRuleContext* ctx, uint64_t value);
Expr NewLiteralDouble(antlr4::ParserRuleContext* ctx, double value);
Expr NewLiteralString(antlr4::ParserRuleContext* ctx, const std::string& s);
Expr NewLiteralBytes(antlr4::ParserRuleContext* ctx, const std::string& b);
Expr NewLiteralBool(antlr4::ParserRuleContext* ctx, bool b);
Expr NewLiteralBoolForMacro(int64_t macro_id, bool b);
Expr NewLiteralNull(antlr4::ParserRuleContext* ctx);
Expr ReportError(int64_t expr_id, absl::string_view msg);
Expr ReportError(antlr4::ParserRuleContext* ctx, absl::string_view msg);
Expr ReportError(int32_t line, int32_t col, absl::string_view msg);
Expr ReportError(const SourceLocation& loc, absl::string_view msg);
bool IsReserved(absl::string_view ident_name);
google::api::expr::v1alpha1::SourceInfo source_info() const;
EnrichedSourceInfo enriched_source_info() const;
const std::vector& errors() const { return errors_truncated_; }
std::string ErrorMessage(absl::string_view description,
absl::string_view expression) const;
Expr BuildArgForMacroCall(const Expr& expr);
void AddMacroCall(int64_t macro_id, const Expr& target,
const std::vector& args, std::string function);
private:
void CalcLineOffsets(absl::string_view expression);
absl::optional FindLineOffset(int32_t line) const;
std::string GetSourceLine(int32_t line, absl::string_view expression) const;
private:
int64_t next_id_;
std::map positions_;
// Truncated at kMaxErrorsToReport.
std::vector errors_truncated_;
int64_t num_errors_;
std::vector line_offsets_;
std::map macro_calls_;
};
} // namespace google::api::expr::parser
#endif // THIRD_PARTY_CEL_CPP_PARSER_SOURCE_FACTORY_H_