+enum precedence_t {
+ PREC_BOTTOM = 0,
+ PREC_COMMA = 2, /* , left to right */
+ PREC_ASSIGN = 4, /* = += -= *= /= %= <<= >>= &= ^= |= right to left */
+ PREC_COND = 6, /* ?: right to left */
+ PREC_LOG_OR = 8, /* || left to right */
+ PREC_LOG_AND = 10, /* && left to right */
+ PREC_BIT_OR = 12, /* | left to right */
+ PREC_BIT_XOR = 14, /* ^ left to right */
+ PREC_BIT_AND = 16, /* & left to right */
+ PREC_EQ = 18, /* == != left to right */
+ PREC_CMP = 20, /* < <= > >= left to right */
+ PREC_SHF = 22, /* << >> left to right */
+ PREC_PLUS = 24, /* + - left to right */
+ PREC_MUL = 26, /* * / % left to right */
+ PREC_UNARY = 28, /* ! ~ ++ -- + - (type) * & sizeof right to left */
+ PREC_ACCESS = 30, /* () [] -> . left to right */
+ PREC_PRIM = 32, /* primary */
+ PREC_TOP = 34
+};
+
+/**
+ * Returns 1 if a given precedence level has right-to-left
+ * associativity, else -1.
+ *
+ * @param precedence the operator precedence
+ */
+static int right_to_left(unsigned precedence) {
+ return (precedence == PREC_ASSIGN || precedence == PREC_COND ||
+ precedence == PREC_UNARY) ? 1 : -1;
+}
+
+/**
+ * Return the precedence of an expression given by its kind.
+ *
+ * @param kind the expression kind
+ */
+static unsigned get_expression_precedence(expression_kind_t kind)
+{
+ static const unsigned prec[] = {
+ [EXPR_UNKNOWN] = PREC_PRIM,
+ [EXPR_INVALID] = PREC_PRIM,
+ [EXPR_REFERENCE] = PREC_PRIM,
+ [EXPR_CHARACTER_CONSTANT] = PREC_PRIM,
+ [EXPR_WIDE_CHARACTER_CONSTANT] = PREC_PRIM,
+ [EXPR_CONST] = PREC_PRIM,
+ [EXPR_STRING_LITERAL] = PREC_PRIM,
+ [EXPR_WIDE_STRING_LITERAL] = PREC_PRIM,
+ [EXPR_COMPOUND_LITERAL] = PREC_UNARY,
+ [EXPR_CALL] = PREC_PRIM,
+ [EXPR_CONDITIONAL] = PREC_COND,
+ [EXPR_SELECT] = PREC_ACCESS,
+ [EXPR_ARRAY_ACCESS] = PREC_ACCESS,
+ [EXPR_SIZEOF] = PREC_UNARY,
+ [EXPR_CLASSIFY_TYPE] = PREC_UNARY,
+ [EXPR_ALIGNOF] = PREC_UNARY,
+
+ [EXPR_FUNCTION] = PREC_PRIM,
+ [EXPR_PRETTY_FUNCTION] = PREC_PRIM,
+ [EXPR_BUILTIN_SYMBOL] = PREC_PRIM,
+ [EXPR_BUILTIN_CONSTANT_P] = PREC_PRIM,
+ [EXPR_BUILTIN_PREFETCH] = PREC_PRIM,
+ [EXPR_OFFSETOF] = PREC_PRIM,
+ [EXPR_VA_START] = PREC_PRIM,
+ [EXPR_VA_ARG] = PREC_PRIM,
+ [EXPR_STATEMENT] = PREC_ACCESS,
+
+ [EXPR_UNARY_NEGATE] = PREC_UNARY,
+ [EXPR_UNARY_PLUS] = PREC_UNARY,
+ [EXPR_UNARY_BITWISE_NEGATE] = PREC_UNARY,
+ [EXPR_UNARY_NOT] = PREC_UNARY,
+ [EXPR_UNARY_DEREFERENCE] = PREC_UNARY,
+ [EXPR_UNARY_TAKE_ADDRESS] = PREC_UNARY,
+ [EXPR_UNARY_POSTFIX_INCREMENT] = PREC_UNARY,
+ [EXPR_UNARY_POSTFIX_DECREMENT] = PREC_UNARY,
+ [EXPR_UNARY_PREFIX_INCREMENT] = PREC_UNARY,
+ [EXPR_UNARY_PREFIX_DECREMENT] = PREC_UNARY,
+ [EXPR_UNARY_CAST] = PREC_UNARY,
+ [EXPR_UNARY_CAST_IMPLICIT] = PREC_UNARY,
+ [EXPR_UNARY_ASSUME] = PREC_PRIM,
+ [EXPR_UNARY_BITFIELD_EXTRACT] = PREC_ACCESS,
+
+ [EXPR_BINARY_ADD] = PREC_PLUS,
+ [EXPR_BINARY_SUB] = PREC_PLUS,
+ [EXPR_BINARY_MUL] = PREC_MUL,
+ [EXPR_BINARY_DIV] = PREC_MUL,
+ [EXPR_BINARY_MOD] = PREC_MUL,
+ [EXPR_BINARY_EQUAL] = PREC_EQ,
+ [EXPR_BINARY_NOTEQUAL] = PREC_EQ,
+ [EXPR_BINARY_LESS] = PREC_CMP,
+ [EXPR_BINARY_LESSEQUAL] = PREC_CMP,
+ [EXPR_BINARY_GREATER] = PREC_CMP,
+ [EXPR_BINARY_GREATEREQUAL] = PREC_CMP,
+ [EXPR_BINARY_BITWISE_AND] = PREC_BIT_AND,
+ [EXPR_BINARY_BITWISE_OR] = PREC_BIT_OR,
+ [EXPR_BINARY_BITWISE_XOR] = PREC_BIT_XOR,
+ [EXPR_BINARY_LOGICAL_AND] = PREC_LOG_AND,
+ [EXPR_BINARY_LOGICAL_OR] = PREC_LOG_OR,
+ [EXPR_BINARY_SHIFTLEFT] = PREC_SHF,
+ [EXPR_BINARY_SHIFTRIGHT] = PREC_SHF,
+ [EXPR_BINARY_ASSIGN] = PREC_ASSIGN,
+ [EXPR_BINARY_MUL_ASSIGN] = PREC_ASSIGN,
+ [EXPR_BINARY_DIV_ASSIGN] = PREC_ASSIGN,
+ [EXPR_BINARY_MOD_ASSIGN] = PREC_ASSIGN,
+ [EXPR_BINARY_ADD_ASSIGN] = PREC_ASSIGN,
+ [EXPR_BINARY_SUB_ASSIGN] = PREC_ASSIGN,
+ [EXPR_BINARY_SHIFTLEFT_ASSIGN] = PREC_ASSIGN,
+ [EXPR_BINARY_SHIFTRIGHT_ASSIGN] = PREC_ASSIGN,
+ [EXPR_BINARY_BITWISE_AND_ASSIGN] = PREC_ASSIGN,
+ [EXPR_BINARY_BITWISE_XOR_ASSIGN] = PREC_ASSIGN,
+ [EXPR_BINARY_BITWISE_OR_ASSIGN] = PREC_ASSIGN,
+ [EXPR_BINARY_COMMA] = PREC_COMMA,
+
+ [EXPR_BINARY_BUILTIN_EXPECT] = PREC_PRIM,
+ [EXPR_BINARY_ISGREATER] = PREC_PRIM,
+ [EXPR_BINARY_ISGREATEREQUAL] = PREC_PRIM,
+ [EXPR_BINARY_ISLESS] = PREC_PRIM,
+ [EXPR_BINARY_ISLESSEQUAL] = PREC_PRIM,
+ [EXPR_BINARY_ISLESSGREATER] = PREC_PRIM,
+ [EXPR_BINARY_ISUNORDERED] = PREC_PRIM
+ };
+ assert((unsigned)kind < (sizeof(prec)/sizeof(prec[0])));
+ unsigned res = prec[kind];
+
+ assert(res != PREC_BOTTOM);
+ return res;
+}
+
+/**
+ * Print a constant expression.
+ *
+ * @param cnst the constant expression
+ */