#ifndef JSONNET_AST_H
#define JSONNET_AST_H
#include <cassert>
#include <cstdlib>
#include <iostream>
#include <list>
#include <map>
#include <string>
#include <vector>
#include "lexer.h"
#include "unicode.h"
enum ASTType {
AST_APPLY,
AST_APPLY_BRACE,
AST_ARRAY,
AST_ARRAY_COMPREHENSION,
AST_ARRAY_COMPREHENSION_SIMPLE,
AST_ASSERT,
AST_BINARY,
AST_BUILTIN_FUNCTION,
AST_CONDITIONAL,
AST_DESUGARED_OBJECT,
AST_DOLLAR,
AST_ERROR,
AST_FUNCTION,
AST_IMPORT,
AST_IMPORTSTR,
AST_INDEX,
AST_IN_SUPER,
AST_LITERAL_BOOLEAN,
AST_LITERAL_NULL,
AST_LITERAL_NUMBER,
AST_LITERAL_STRING,
AST_LOCAL,
AST_OBJECT,
AST_OBJECT_COMPREHENSION,
AST_OBJECT_COMPREHENSION_SIMPLE,
AST_PARENS,
AST_SELF,
AST_SUPER_INDEX,
AST_UNARY,
AST_VAR
};
static inline std::string ASTTypeToString(ASTType type)
{
switch (type) {
case AST_APPLY: return "AST_APPLY";
case AST_APPLY_BRACE: return "AST_APPLY_BRACE";
case AST_ARRAY: return "AST_ARRAY";
case AST_ARRAY_COMPREHENSION: return "AST_ARRAY_COMPREHENSION";
case AST_ARRAY_COMPREHENSION_SIMPLE: return "AST_ARRAY_COMPREHENSION_SIMPLE";
case AST_ASSERT: return "AST_ASSERT";
case AST_BINARY: return "AST_BINARY";
case AST_BUILTIN_FUNCTION: return "AST_BUILTIN_FUNCTION";
case AST_CONDITIONAL: return "AST_CONDITIONAL";
case AST_DESUGARED_OBJECT: return "AST_DESUGARED_OBJECT";
case AST_DOLLAR: return "AST_DOLLAR";
case AST_ERROR: return "AST_ERROR";
case AST_FUNCTION: return "AST_FUNCTION";
case AST_IMPORT: return "AST_IMPORT";
case AST_IMPORTSTR: return "AST_IMPORTSTR";
case AST_INDEX: return "AST_INDEX";
case AST_IN_SUPER: return "AST_IN_SUPER";
case AST_LITERAL_BOOLEAN: return "AST_LITERAL_BOOLEAN";
case AST_LITERAL_NULL: return "AST_LITERAL_NULL";
case AST_LITERAL_NUMBER: return "AST_LITERAL_NUMBER";
case AST_LITERAL_STRING: return "AST_LITERAL_STRING";
case AST_LOCAL: return "AST_LOCAL";
case AST_OBJECT: return "AST_OBJECT";
case AST_OBJECT_COMPREHENSION: return "AST_OBJECT_COMPREHENSION";
case AST_OBJECT_COMPREHENSION_SIMPLE: return "AST_OBJECT_COMPREHENSION_SIMPLE";
case AST_PARENS: return "AST_PARENS";
case AST_SELF: return "AST_SELF";
case AST_SUPER_INDEX: return "AST_SUPER_INDEX";
case AST_UNARY: return "AST_UNARY";
case AST_VAR: return "AST_VAR";
}
std::cerr << "Invalid AST type"
<< "\n";
abort();
}
struct Identifier {
UString name;
Identifier(const UString &name) : name(name) {}
};
static inline std::ostream &operator<<(std::ostream &o, const Identifier *id)
{
o << encode_utf8(id->name);
return o;
}
typedef std::vector<const Identifier *> Identifiers;
struct AST {
LocationRange location;
ASTType type;
Fodder openFodder;
Identifiers freeVariables;
AST(const LocationRange &location, ASTType type, const Fodder &open_fodder)
: location(location), type(type), openFodder(open_fodder)
{
}
virtual ~AST(void) {}
};
typedef std::list<AST *> ASTs;
struct ArgParam {
Fodder idFodder; const Identifier *id; Fodder eqFodder; AST *expr; Fodder commaFodder; ArgParam(const Fodder &id_fodder, const Identifier *id, const Fodder &comma_fodder)
: idFodder(id_fodder), id(id), expr(nullptr), commaFodder(comma_fodder)
{
}
ArgParam(AST *expr, const Fodder &comma_fodder)
: id(nullptr), expr(expr), commaFodder(comma_fodder)
{
}
ArgParam(const Fodder &id_fodder, const Identifier *id, const Fodder &eq_fodder, AST *expr,
const Fodder &comma_fodder)
: idFodder(id_fodder), id(id), eqFodder(eq_fodder), expr(expr), commaFodder(comma_fodder)
{
}
};
typedef std::vector<ArgParam> ArgParams;
struct ComprehensionSpec {
enum Kind { FOR, IF };
Kind kind;
Fodder openFodder;
Fodder varFodder; const Identifier *var; Fodder inFodder; AST *expr;
ComprehensionSpec(Kind kind, const Fodder &open_fodder, const Fodder &var_fodder,
const Identifier *var, const Fodder &in_fodder, AST *expr)
: kind(kind),
openFodder(open_fodder),
varFodder(var_fodder),
var(var),
inFodder(in_fodder),
expr(expr)
{
}
};
struct Apply : public AST {
AST *target;
Fodder fodderL;
ArgParams args;
bool trailingComma;
Fodder fodderR;
Fodder tailstrictFodder;
bool tailstrict;
Apply(const LocationRange &lr, const Fodder &open_fodder, AST *target, const Fodder &fodder_l,
const ArgParams &args, bool trailing_comma, const Fodder &fodder_r,
const Fodder &tailstrict_fodder, bool tailstrict)
: AST(lr, AST_APPLY, open_fodder),
target(target),
fodderL(fodder_l),
args(args),
trailingComma(trailing_comma),
fodderR(fodder_r),
tailstrictFodder(tailstrict_fodder),
tailstrict(tailstrict)
{
}
};
struct ApplyBrace : public AST {
AST *left;
AST *right; ApplyBrace(const LocationRange &lr, const Fodder &open_fodder, AST *left, AST *right)
: AST(lr, AST_APPLY_BRACE, open_fodder), left(left), right(right)
{
}
};
struct Array : public AST {
struct Element {
AST *expr;
Fodder commaFodder;
Element(AST *expr, const Fodder &comma_fodder) : expr(expr), commaFodder(comma_fodder) {}
};
typedef std::vector<Element> Elements;
Elements elements;
bool trailingComma;
Fodder closeFodder;
Array(const LocationRange &lr, const Fodder &open_fodder, const Elements &elements,
bool trailing_comma, const Fodder &close_fodder)
: AST(lr, AST_ARRAY, open_fodder),
elements(elements),
trailingComma(trailing_comma),
closeFodder(close_fodder)
{
}
};
struct ArrayComprehension : public AST {
AST *body;
Fodder commaFodder;
bool trailingComma;
std::vector<ComprehensionSpec> specs;
Fodder closeFodder;
ArrayComprehension(const LocationRange &lr, const Fodder &open_fodder, AST *body,
const Fodder &comma_fodder, bool trailing_comma,
const std::vector<ComprehensionSpec> &specs, const Fodder &close_fodder)
: AST(lr, AST_ARRAY_COMPREHENSION, open_fodder),
body(body),
commaFodder(comma_fodder),
trailingComma(trailing_comma),
specs(specs),
closeFodder(close_fodder)
{
assert(specs.size() > 0);
}
};
struct Assert : public AST {
AST *cond;
Fodder colonFodder;
AST *message;
Fodder semicolonFodder;
AST *rest;
Assert(const LocationRange &lr, const Fodder &open_fodder, AST *cond,
const Fodder &colon_fodder, AST *message, const Fodder &semicolon_fodder, AST *rest)
: AST(lr, AST_ASSERT, open_fodder),
cond(cond),
colonFodder(colon_fodder),
message(message),
semicolonFodder(semicolon_fodder),
rest(rest)
{
}
};
enum BinaryOp {
BOP_MULT,
BOP_DIV,
BOP_PERCENT,
BOP_PLUS,
BOP_MINUS,
BOP_SHIFT_L,
BOP_SHIFT_R,
BOP_GREATER,
BOP_GREATER_EQ,
BOP_LESS,
BOP_LESS_EQ,
BOP_IN,
BOP_MANIFEST_EQUAL,
BOP_MANIFEST_UNEQUAL,
BOP_BITWISE_AND,
BOP_BITWISE_XOR,
BOP_BITWISE_OR,
BOP_AND,
BOP_OR
};
static inline std::string bop_string(BinaryOp bop)
{
switch (bop) {
case BOP_MULT: return "*";
case BOP_DIV: return "/";
case BOP_PERCENT: return "%";
case BOP_PLUS: return "+";
case BOP_MINUS: return "-";
case BOP_SHIFT_L: return "<<";
case BOP_SHIFT_R: return ">>";
case BOP_GREATER: return ">";
case BOP_GREATER_EQ: return ">=";
case BOP_LESS: return "<";
case BOP_LESS_EQ: return "<=";
case BOP_IN: return "in";
case BOP_MANIFEST_EQUAL: return "==";
case BOP_MANIFEST_UNEQUAL: return "!=";
case BOP_BITWISE_AND: return "&";
case BOP_BITWISE_XOR: return "^";
case BOP_BITWISE_OR: return "|";
case BOP_AND: return "&&";
case BOP_OR: return "||";
default:
std::cerr << "INTERNAL ERROR: Unrecognised binary operator: " << bop << std::endl;
std::abort();
}
}
struct Binary : public AST {
AST *left;
Fodder opFodder;
BinaryOp op;
AST *right;
Binary(const LocationRange &lr, const Fodder &open_fodder, AST *left, const Fodder &op_fodder,
BinaryOp op, AST *right)
: AST(lr, AST_BINARY, open_fodder), left(left), opFodder(op_fodder), op(op), right(right)
{
}
};
struct BuiltinFunction : public AST {
std::string name;
Identifiers params;
BuiltinFunction(const LocationRange &lr, const std::string &name, const Identifiers ¶ms)
: AST(lr, AST_BUILTIN_FUNCTION, Fodder{}), name(name), params(params)
{
}
};
struct Conditional : public AST {
AST *cond;
Fodder thenFodder;
AST *branchTrue;
Fodder elseFodder;
AST *branchFalse;
Conditional(const LocationRange &lr, const Fodder &open_fodder, AST *cond,
const Fodder &then_fodder, AST *branch_true, const Fodder &else_fodder,
AST *branch_false)
: AST(lr, AST_CONDITIONAL, open_fodder),
cond(cond),
thenFodder(then_fodder),
branchTrue(branch_true),
elseFodder(else_fodder),
branchFalse(branch_false)
{
}
};
struct Dollar : public AST {
Dollar(const LocationRange &lr, const Fodder &open_fodder) : AST(lr, AST_DOLLAR, open_fodder) {}
};
struct Error : public AST {
AST *expr;
Error(const LocationRange &lr, const Fodder &open_fodder, AST *expr)
: AST(lr, AST_ERROR, open_fodder), expr(expr)
{
}
};
struct Function : public AST {
Fodder parenLeftFodder;
ArgParams params;
bool trailingComma;
Fodder parenRightFodder;
AST *body;
Function(const LocationRange &lr, const Fodder &open_fodder, const Fodder &paren_left_fodder,
const ArgParams ¶ms, bool trailing_comma, const Fodder &paren_right_fodder,
AST *body)
: AST(lr, AST_FUNCTION, open_fodder),
parenLeftFodder(paren_left_fodder),
params(params),
trailingComma(trailing_comma),
parenRightFodder(paren_right_fodder),
body(body)
{
}
};
struct LiteralString;
struct Import : public AST {
LiteralString *file;
Import(const LocationRange &lr, const Fodder &open_fodder, LiteralString *file)
: AST(lr, AST_IMPORT, open_fodder), file(file)
{
}
};
struct Importstr : public AST {
LiteralString *file;
Importstr(const LocationRange &lr, const Fodder &open_fodder, LiteralString *file)
: AST(lr, AST_IMPORTSTR, open_fodder), file(file)
{
}
};
struct Index : public AST {
AST *target;
Fodder dotFodder; bool isSlice;
AST *index;
Fodder endColonFodder; AST *end;
Fodder stepColonFodder; AST *step;
Fodder idFodder; const Identifier *id;
Index(const LocationRange &lr, const Fodder &open_fodder, AST *target, const Fodder &dot_fodder,
const Fodder &id_fodder, const Identifier *id)
: AST(lr, AST_INDEX, open_fodder),
target(target),
dotFodder(dot_fodder),
isSlice(false),
index(nullptr),
end(nullptr),
step(nullptr),
idFodder(id_fodder),
id(id)
{
}
Index(const LocationRange &lr, const Fodder &open_fodder, AST *target, const Fodder &dot_fodder,
bool is_slice, AST *index, const Fodder &end_colon_fodder, AST *end,
const Fodder &step_colon_fodder, AST *step, const Fodder &id_fodder)
: AST(lr, AST_INDEX, open_fodder),
target(target),
dotFodder(dot_fodder),
isSlice(is_slice),
index(index),
endColonFodder(end_colon_fodder),
end(end),
stepColonFodder(step_colon_fodder),
step(step),
idFodder(id_fodder),
id(nullptr)
{
}
};
struct Local : public AST {
struct Bind {
Fodder varFodder;
const Identifier *var;
Fodder opFodder;
AST *body;
bool functionSugar;
Fodder parenLeftFodder;
ArgParams params; bool trailingComma;
Fodder parenRightFodder;
Fodder closeFodder;
Bind(const Fodder &var_fodder, const Identifier *var, const Fodder &op_fodder, AST *body,
bool function_sugar, const Fodder &paren_left_fodder, const ArgParams ¶ms,
bool trailing_comma, const Fodder &paren_right_fodder, const Fodder &close_fodder)
: varFodder(var_fodder),
var(var),
opFodder(op_fodder),
body(body),
functionSugar(function_sugar),
parenLeftFodder(paren_left_fodder),
params(params),
trailingComma(trailing_comma),
parenRightFodder(paren_right_fodder),
closeFodder(close_fodder)
{
}
};
typedef std::vector<Bind> Binds;
Binds binds;
AST *body;
Local(const LocationRange &lr, const Fodder &open_fodder, const Binds &binds, AST *body)
: AST(lr, AST_LOCAL, open_fodder), binds(binds), body(body)
{
}
};
struct LiteralBoolean : public AST {
bool value;
LiteralBoolean(const LocationRange &lr, const Fodder &open_fodder, bool value)
: AST(lr, AST_LITERAL_BOOLEAN, open_fodder), value(value)
{
}
};
struct LiteralNull : public AST {
LiteralNull(const LocationRange &lr, const Fodder &open_fodder)
: AST(lr, AST_LITERAL_NULL, open_fodder)
{
}
};
struct LiteralNumber : public AST {
double value;
std::string originalString;
LiteralNumber(const LocationRange &lr, const Fodder &open_fodder, const std::string &str)
: AST(lr, AST_LITERAL_NUMBER, open_fodder),
value(strtod(str.c_str(), nullptr)),
originalString(str)
{
}
};
struct LiteralString : public AST {
UString value;
enum TokenKind { SINGLE, DOUBLE, BLOCK, VERBATIM_SINGLE, VERBATIM_DOUBLE };
TokenKind tokenKind;
std::string blockIndent; std::string blockTermIndent; LiteralString(const LocationRange &lr, const Fodder &open_fodder, const UString &value,
TokenKind token_kind, const std::string &block_indent,
const std::string &block_term_indent)
: AST(lr, AST_LITERAL_STRING, open_fodder),
value(value),
tokenKind(token_kind),
blockIndent(block_indent),
blockTermIndent(block_term_indent)
{
}
};
struct ObjectField {
enum Kind {
ASSERT,
FIELD_ID,
FIELD_EXPR,
FIELD_STR,
LOCAL,
};
enum Hide {
HIDDEN, INHERIT, VISIBLE, };
enum Kind kind;
Fodder fodder1, fodder2, fodderL, fodderR;
enum Hide hide; bool superSugar; bool methodSugar; AST *expr1; const Identifier *id;
LocationRange idLocation;
ArgParams params; bool trailingComma; Fodder opFodder; AST *expr2, *expr3; Fodder commaFodder;
ObjectField(enum Kind kind, const Fodder &fodder1, const Fodder &fodder2,
const Fodder &fodder_l, const Fodder &fodder_r, enum Hide hide, bool super_sugar,
bool method_sugar, AST *expr1, const Identifier *id, const LocationRange &id_lr,
const ArgParams ¶ms, bool trailing_comma, const Fodder &op_fodder, AST *expr2,
AST *expr3, const Fodder &comma_fodder)
: kind(kind),
fodder1(fodder1),
fodder2(fodder2),
fodderL(fodder_l),
fodderR(fodder_r),
hide(hide),
superSugar(super_sugar),
methodSugar(method_sugar),
expr1(expr1),
id(id),
idLocation(id_lr),
params(params),
trailingComma(trailing_comma),
opFodder(op_fodder),
expr2(expr2),
expr3(expr3),
commaFodder(comma_fodder)
{
assert(kind != ASSERT || (hide == VISIBLE && !superSugar && !methodSugar));
assert(kind != LOCAL || (hide == VISIBLE && !superSugar));
assert(kind != FIELD_ID || (id != nullptr && expr1 == nullptr));
assert(kind == FIELD_ID || kind == LOCAL || id == nullptr);
assert(methodSugar || (params.size() == 0 && !trailingComma));
assert(kind == ASSERT || expr3 == nullptr);
}
static ObjectField Local(const Fodder &fodder1, const Fodder &fodder2, const Fodder &fodder_l,
const Fodder &fodder_r, bool method_sugar, const Identifier *id,
const ArgParams ¶ms, bool trailing_comma, const Fodder &op_fodder,
AST *body, const Fodder &comma_fodder)
{
return ObjectField(LOCAL,
fodder1,
fodder2,
fodder_l,
fodder_r,
VISIBLE,
false,
method_sugar,
nullptr,
id,
LocationRange(),
params,
trailing_comma,
op_fodder,
body,
nullptr,
comma_fodder);
}
static ObjectField Local(const Fodder &fodder1, const Fodder &fodder2, const Identifier *id,
const Fodder &op_fodder, AST *body, const Fodder &comma_fodder)
{
return ObjectField(LOCAL,
fodder1,
fodder2,
Fodder{},
Fodder{},
VISIBLE,
false,
false,
nullptr,
id,
LocationRange(),
ArgParams{},
false,
op_fodder,
body,
nullptr,
comma_fodder);
}
static ObjectField LocalMethod(const Fodder &fodder1, const Fodder &fodder2,
const Fodder &fodder_l, const Fodder &fodder_r,
const Identifier *id, const ArgParams ¶ms,
bool trailing_comma, const Fodder &op_fodder, AST *body,
const Fodder &comma_fodder)
{
return ObjectField(LOCAL,
fodder1,
fodder2,
fodder_l,
fodder_r,
VISIBLE,
false,
true,
nullptr,
id,
LocationRange(),
params,
trailing_comma,
op_fodder,
body,
nullptr,
comma_fodder);
}
static ObjectField Assert(const Fodder &fodder1, AST *body, const Fodder &op_fodder, AST *msg,
const Fodder &comma_fodder)
{
return ObjectField(ASSERT,
fodder1,
Fodder{},
Fodder{},
Fodder{},
VISIBLE,
false,
false,
nullptr,
nullptr,
LocationRange(),
ArgParams{},
false,
op_fodder,
body,
msg,
comma_fodder);
}
};
typedef std::vector<ObjectField> ObjectFields;
struct Object : public AST {
ObjectFields fields;
bool trailingComma;
Fodder closeFodder;
Object(const LocationRange &lr, const Fodder &open_fodder, const ObjectFields &fields,
bool trailing_comma, const Fodder &close_fodder)
: AST(lr, AST_OBJECT, open_fodder),
fields(fields),
trailingComma(trailing_comma),
closeFodder(close_fodder)
{
assert(fields.size() > 0 || !trailing_comma);
if (fields.size() > 0)
assert(trailing_comma || fields[fields.size() - 1].commaFodder.size() == 0);
}
};
struct DesugaredObject : public AST {
struct Field {
enum ObjectField::Hide hide;
AST *name;
AST *body;
Field(enum ObjectField::Hide hide, AST *name, AST *body)
: hide(hide), name(name), body(body)
{
}
};
typedef std::vector<Field> Fields;
ASTs asserts;
Fields fields;
DesugaredObject(const LocationRange &lr, const ASTs &asserts, const Fields &fields)
: AST(lr, AST_DESUGARED_OBJECT, Fodder{}), asserts(asserts), fields(fields)
{
}
};
struct ObjectComprehension : public AST {
ObjectFields fields;
bool trailingComma;
std::vector<ComprehensionSpec> specs;
Fodder closeFodder;
ObjectComprehension(const LocationRange &lr, const Fodder &open_fodder,
const ObjectFields &fields, bool trailing_comma,
const std::vector<ComprehensionSpec> &specs, const Fodder &close_fodder)
: AST(lr, AST_OBJECT_COMPREHENSION, open_fodder),
fields(fields),
trailingComma(trailing_comma),
specs(specs),
closeFodder(close_fodder)
{
}
};
struct ObjectComprehensionSimple : public AST {
AST *field;
AST *value;
const Identifier *id;
AST *array;
ObjectComprehensionSimple(const LocationRange &lr, AST *field, AST *value, const Identifier *id,
AST *array)
: AST(lr, AST_OBJECT_COMPREHENSION_SIMPLE, Fodder{}),
field(field),
value(value),
id(id),
array(array)
{
}
};
struct Parens : public AST {
AST *expr;
Fodder closeFodder;
Parens(const LocationRange &lr, const Fodder &open_fodder, AST *expr,
const Fodder &close_fodder)
: AST(lr, AST_PARENS, open_fodder), expr(expr), closeFodder(close_fodder)
{
}
};
struct Self : public AST {
Self(const LocationRange &lr, const Fodder &open_fodder) : AST(lr, AST_SELF, open_fodder) {}
};
struct SuperIndex : public AST {
Fodder dotFodder;
AST *index;
Fodder idFodder;
const Identifier *id;
SuperIndex(const LocationRange &lr, const Fodder &open_fodder, const Fodder &dot_fodder,
AST *index, const Fodder &id_fodder, const Identifier *id)
: AST(lr, AST_SUPER_INDEX, open_fodder),
dotFodder(dot_fodder),
index(index),
idFodder(id_fodder),
id(id)
{
}
};
struct InSuper : public AST {
AST *element;
Fodder inFodder;
Fodder superFodder;
InSuper(const LocationRange &lr, const Fodder &open_fodder, AST *element,
const Fodder &in_fodder, const Fodder &super_fodder)
: AST(lr, AST_IN_SUPER, open_fodder),
element(element),
inFodder(in_fodder),
superFodder(super_fodder)
{
}
};
enum UnaryOp { UOP_NOT, UOP_BITWISE_NOT, UOP_PLUS, UOP_MINUS };
static inline std::string uop_string(UnaryOp uop)
{
switch (uop) {
case UOP_PLUS: return "+";
case UOP_MINUS: return "-";
case UOP_BITWISE_NOT: return "~";
case UOP_NOT: return "!";
default:
std::cerr << "INTERNAL ERROR: Unrecognised unary operator: " << uop << std::endl;
std::abort();
}
}
struct Unary : public AST {
UnaryOp op;
AST *expr;
Unary(const LocationRange &lr, const Fodder &open_fodder, UnaryOp op, AST *expr)
: AST(lr, AST_UNARY, open_fodder), op(op), expr(expr)
{
}
};
struct Var : public AST {
const Identifier *id;
Var(const LocationRange &lr, const Fodder &open_fodder, const Identifier *id)
: AST(lr, AST_VAR, open_fodder), id(id)
{
}
};
class Allocator {
std::map<UString, const Identifier *> internedIdentifiers;
ASTs allocated;
public:
template <class T, class... Args>
T *make(Args &&... args)
{
auto r = new T(std::forward<Args>(args)...);
allocated.push_back(r);
return r;
}
template <class T>
T *clone(T *ast)
{
auto r = new T(*ast);
allocated.push_back(r);
return r;
}
const Identifier *makeIdentifier(const UString &name)
{
auto it = internedIdentifiers.find(name);
if (it != internedIdentifiers.end()) {
return it->second;
}
auto r = new Identifier(name);
internedIdentifiers[name] = r;
return r;
}
~Allocator()
{
for (auto x : allocated) {
delete x;
}
allocated.clear();
for (const auto &x : internedIdentifiers) {
delete x.second;
}
internedIdentifiers.clear();
}
};
namespace {
const int APPLY_PRECEDENCE = 2; const int UNARY_PRECEDENCE = 4; const int MAX_PRECEDENCE = 15;
std::map<BinaryOp, int> build_precedence_map(void)
{
std::map<BinaryOp, int> r;
r[BOP_MULT] = 5;
r[BOP_DIV] = 5;
r[BOP_PERCENT] = 5;
r[BOP_PLUS] = 6;
r[BOP_MINUS] = 6;
r[BOP_SHIFT_L] = 7;
r[BOP_SHIFT_R] = 7;
r[BOP_GREATER] = 8;
r[BOP_GREATER_EQ] = 8;
r[BOP_LESS] = 8;
r[BOP_LESS_EQ] = 8;
r[BOP_IN] = 8;
r[BOP_MANIFEST_EQUAL] = 9;
r[BOP_MANIFEST_UNEQUAL] = 9;
r[BOP_BITWISE_AND] = 10;
r[BOP_BITWISE_XOR] = 11;
r[BOP_BITWISE_OR] = 12;
r[BOP_AND] = 13;
r[BOP_OR] = 14;
return r;
}
std::map<std::string, UnaryOp> build_unary_map(void)
{
std::map<std::string, UnaryOp> r;
r["!"] = UOP_NOT;
r["~"] = UOP_BITWISE_NOT;
r["+"] = UOP_PLUS;
r["-"] = UOP_MINUS;
return r;
}
std::map<std::string, BinaryOp> build_binary_map(void)
{
std::map<std::string, BinaryOp> r;
r["*"] = BOP_MULT;
r["/"] = BOP_DIV;
r["%"] = BOP_PERCENT;
r["+"] = BOP_PLUS;
r["-"] = BOP_MINUS;
r["<<"] = BOP_SHIFT_L;
r[">>"] = BOP_SHIFT_R;
r[">"] = BOP_GREATER;
r[">="] = BOP_GREATER_EQ;
r["<"] = BOP_LESS;
r["<="] = BOP_LESS_EQ;
r["in"] = BOP_IN;
r["=="] = BOP_MANIFEST_EQUAL;
r["!="] = BOP_MANIFEST_UNEQUAL;
r["&"] = BOP_BITWISE_AND;
r["^"] = BOP_BITWISE_XOR;
r["|"] = BOP_BITWISE_OR;
r["&&"] = BOP_AND;
r["||"] = BOP_OR;
return r;
}
auto precedence_map = build_precedence_map();
auto unary_map = build_unary_map();
auto binary_map = build_binary_map();
}
#endif