#ifndef OPERATOR_HH #define OPERATOR_HH #include "permstr.hh" class Compiler; class Node; class Writer; enum OperatorValue { // Some groups of OperatorValues must be contiguous. They are marked with // a comment. // Nonexistent operator & nonexistent token. opNone = 0, // characters = 1..255 // Internal tokenizer types opPunctuation = 256, opNumber, opSlashStarComment, opEOLComment, opLastInternal, // Generic tokens opString = opLastInternal, opIdentifier, opExpr, // Keywords opEnd, opIn, opLet, // Actual operators opCopy, opCastParen, opCall, opNegate, opPower, opLt, opLe, opGt, opGe, opEq, opNe, opLogAnd, opLogOr, opFlip, opPin, opAssign, opAddAssign, opSubAssign, opMulAssign, opDivAssign, opPowerAssign, opLast, }; class Operator { int _op; static PermString all_name[opLast - 256]; static int all_precedence[opLast]; static int all_flags[opLast]; static Operator all_terminator[opLast]; public: enum Flags { fPrefix = 1, fUnary = 2, fRightAssoc = 4, fTakesID = 8, fTakesSpecial = 16, fOptionalArg = 32, fFunctionish = 64, fAssignVariant = 128, }; Operator() : _op(0) { } Operator(int op); void set_data(PermString name); void set_data(PermString name, int prec, int flags, Operator terminator); operator bool() const { return _op != 0; } operator int() const { return _op; } PermString name() const; int precedence() const { return all_precedence[_op]; } Operator terminator() const { return all_terminator[_op]; } bool test(int flag) const { return all_flags[_op] & flag; } bool right_assoc() const { return test(fRightAssoc); } bool prefix() const { return test(fPrefix); } bool unary() const { return test(fUnary); } bool takes_id() const { return test(fTakesID); } bool takes_special() const { return test(fTakesSpecial); } bool optional_arg() const { return test(fOptionalArg); } bool functionish() const { return test(fFunctionish); } bool assign_variant() const { return test(fAssignVariant); } bool tokenizer_internal() const; bool assignment() const; }; class OperatorGroup { Operator *_ops; int _nops; public: OperatorGroup(); ~OperatorGroup(); void add(Operator op); Operator find(bool isprefix); }; inline Operator::Operator(int op) : _op(op) { assert(_op >= 0 && _op < opLast); } inline bool Operator::tokenizer_internal() const { return _op >= 256 && _op < opLastInternal; } inline bool Operator::assignment() const { return _op >= opAssign && _op <= opPowerAssign; } #endif