X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=lexer.h;h=f75dff6232d4b7ea72aaac132284731006884fa9;hb=refs%2Fheads%2FTimePath%2Fparser;hp=24e29ddee4080659be406da5f073ef041ecdb115;hpb=fa14ca93d2b60f722d55c24214fde7ac84581ad0;p=xonotic%2Fgmqcc.git diff --git a/lexer.h b/lexer.h index 24e29dd..f75dff6 100644 --- a/lexer.h +++ b/lexer.h @@ -1,146 +1,188 @@ -/* - * Copyright (C) 2012, 2013 - * Wolfgang Bumiller - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is furnished to do - * so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ #ifndef GMQCC_LEXER_HDR #define GMQCC_LEXER_HDR -typedef struct token_s token; -struct token_s { - int ttype; - - char *value; - - union { - vec3_t v; - int i; - double f; - int t; /* type */ - } constval; - -#if 0 - struct token_s *next; - struct token_s *prev; -#endif - - lex_ctx_t ctx; +#include "gmqcc.h" + +#define TOKENS(X) \ + /* Other tokens which we can return: */ \ + X(NONE, =0) \ + X(CR, = '\r') \ + X(LF, = '\n') \ + X(WS, = ' ') \ + X(BACKSLASH, = '\\') \ + X(HASH, = '#') \ + X(DOLLAR, = '$') \ + X(DOT, = '.') \ + X(COMMA, = ',') \ + X(COLON, = ':') \ + X(SEMICOLON, = ';') \ + X(AND, = '&') \ + X(OR, = '|') \ + X(XOR, = '^') \ + X(BITNOT, = '~') \ + X(NOT, = '!') \ + X(LT, = '<') \ + X(GT, = '>') \ + X(EQ, = '=') \ + X(MUL, = '*') \ + X(DIV, = '/') \ + X(MOD, = '%') \ + X(ADD, = '+') \ + X(SUB, = '-') \ + X(QUOT_SINGLE, = '\'') \ + X(QUOT_DOUBLE, = '"') \ + X(QUESTION, = '?') \ + X(BRACE_OPEN, = '{') \ + X(BRACE_CLOSE, = '}') \ + X(BRACKET_OPEN, = '[') \ + X(BRACKET_CLOSE, = ']') \ + X(PAREN_OPEN, = '(') \ + X(PAREN_CLOSE, = ')') \ + X(START, = 128) \ + X(IDENT, ) \ + X(TYPENAME, ) \ + X(OPERATOR, ) \ + X(OP_AND, ) \ + X(OP_CROSS, ) \ + X(OP_LE, ) \ + X(OP_GE, ) \ + X(OP_LSH, ) \ + X(OP_RSH, ) \ + /* loop */ \ + X(KEYWORD, ) \ + /* 3 dots, ... */ \ + X(DOTS, ) \ + /* [[ */ \ + X(ATTRIBUTE_OPEN, ) \ + /* ]] */ \ + X(ATTRIBUTE_CLOSE, ) \ + /* for the ftepp only */ \ + X(VA_ARGS, ) \ + /* for the ftepp only */ \ + X(VA_ARGS_ARRAY, ) \ + /* to get the count of vaargs */ \ + X(VA_COUNT, ) \ + /* not the typename but an actual "string" */ \ + X(STRINGCONST, ) \ + X(CHARCONST, ) \ + X(VECTORCONST, ) \ + X(INTCONST, ) \ + X(FLOATCONST, ) \ + X(WHITE, ) \ + X(EOL, ) \ + /* if we add additional tokens before this, the exposed API \ + * should not be broken anyway, but EOF/ERROR/... should \ + * still be at the bottom \ + */ \ + X(END, = 1024) \ + /* We use '< ERROR', so FATAL must come after it and any \ + * other error related tokens as well \ + */ \ + X(ERROR, ) \ + /* internal error, eg out of memory */ \ + X(FATAL, ) \ + /**/ + +enum Token : int { // todo: enum class +#define X(id, val) id val, + TOKENS(X) +#undef X }; -#if 0 -token* token_new(); -void token_delete(token*); -token* token_copy(const token *cp); -void token_delete_all(token *t); -token* token_copy_all(const token *cp); -#endif - -/* Lexer - * - */ -enum { - /* Other tokens which we can return: */ - TOKEN_NONE = 0, - TOKEN_START = 128, +inline const char *TokenName(Token t) { + switch (t) { + default: + return "UNKNOWN"; +#define X(id, val) case Token::id: return #id; + TOKENS(X) +#undef X + } +} - TOKEN_IDENT, +struct cvec { + std::string value; - TOKEN_TYPENAME, + explicit cvec() = default; - TOKEN_OPERATOR, + char *mut() { + return &value[0]; + } - TOKEN_KEYWORD, /* loop */ + const char *c_str() { + return value.c_str(); + } - TOKEN_DOTS, /* 3 dots, ... */ + void shrinkto(size_t i) { + value.resize(i); + } - TOKEN_ATTRIBUTE_OPEN, /* [[ */ - TOKEN_ATTRIBUTE_CLOSE, /* ]] */ + void shrinkby(size_t i) { + value.resize(value.size() - i); + } - TOKEN_VA_ARGS, /* for the ftepp only */ - TOKEN_VA_ARGS_ARRAY, /* for the ftepp only */ - TOKEN_VA_COUNT, /* to get the count of vaargs */ - - TOKEN_STRINGCONST, /* not the typename but an actual "string" */ - TOKEN_CHARCONST, - TOKEN_VECTORCONST, - TOKEN_INTCONST, - TOKEN_FLOATCONST, - - TOKEN_WHITE, - TOKEN_EOL, - - /* if we add additional tokens before this, the exposed API - * should not be broken anyway, but EOF/ERROR/... should - * still be at the bottom - */ - TOKEN_EOF = 1024, + void push(char it) { + value.push_back(it); + } +}; - /* We use '< TOKEN_ERROR', so TOKEN_FATAL must come after it and any - * other error related tokens as well - */ - TOKEN_ERROR, - TOKEN_FATAL /* internal error, eg out of memory */ +struct token { + Token ttype; + cvec value; + union { + vec3_t v; + int i; + qcfloat_t f; + qc_type t; /* type */ + } constval; + lex_ctx_t ctx; }; -typedef struct { - char *name; - int value; -} frame_macro; +struct frame_macro { + std::string name; + int value; +}; -typedef struct lex_file_s { - FILE *file; +struct lex_file { + FILE *file; const char *open_string; - size_t open_string_length; - size_t open_string_pos; + size_t open_string_length; + size_t open_string_pos; - char *name; - size_t line; - size_t sline; /* line at the start of a token */ - size_t column; + char *name; + size_t line; + size_t sline; /* line at the start of a token */ + size_t column; - int peek[256]; - size_t peekpos; + std::array peek; + size_t peekpos; - bool eof; + bool eof; - token tok; /* not a pointer anymore */ + token tok; /* not a pointer anymore */ struct { - unsigned noops:1; - unsigned nodigraphs:1; /* used when lexing string constants */ - unsigned preprocessing:1; /* whitespace and EOLs become actual tokens */ - unsigned mergelines:1; /* backslash at the end of a line escapes the newline */ + bool noops:1; + bool nodigraphs:1; /* used when lexing string constants */ + bool preprocessing:1; /* whitespace and EOLs become actual tokens */ + bool mergelines:1; /* backslash at the end of a line escapes the newline */ } flags; /* sizeof == 1 */ int framevalue; frame_macro *frames; - char *modelname; + std::string modelname; size_t push_line; -} lex_file; +}; + +lex_file *lex_open(const char *file); + +lex_file *lex_open_string(const char *str, size_t len, const char *name); -lex_file* lex_open (const char *file); -lex_file* lex_open_string(const char *str, size_t len, const char *name); -void lex_close(lex_file *lex); -int lex_do (lex_file *lex); -void lex_cleanup(void); +void lex_close(lex_file *lex); + +Token lex_do(lex_file *lex); + +void lex_cleanup(); /* Parser * @@ -154,15 +196,15 @@ enum { #define OP_SUFFIX 1 #define OP_PREFIX 2 -typedef struct { - const char *op; +struct oper_info { + const char *op; unsigned int operands; unsigned int id; unsigned int assoc; - signed int prec; + signed int prec; unsigned int flags; - bool folds; -} oper_info; + bool folds; +}; /* * Explicit uint8_t casts since the left operand of shift operator cannot @@ -170,172 +212,172 @@ typedef struct { * possibility. */ #define opid1(a) ((uint8_t)a) -#define opid2(a,b) (((uint8_t)a<<8) |(uint8_t)b) -#define opid3(a,b,c) (((uint8_t)a<<16)|((uint8_t)b<<8)|(uint8_t)c) +#define opid2(a, b) (((uint8_t)a<<8) |(uint8_t)b) +#define opid3(a, b, c) (((uint8_t)a<<16)|((uint8_t)b<<8)|(uint8_t)c) static const oper_info c_operators[] = { - { "(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX, false}, /* paren expression - non function call */ - - { "++", 1, opid3('S','+','+'), ASSOC_LEFT, 17, OP_SUFFIX, false}, - { "--", 1, opid3('S','-','-'), ASSOC_LEFT, 17, OP_SUFFIX, false}, - { ".", 2, opid1('.'), ASSOC_LEFT, 17, 0, false}, - { "(", 0, opid1('('), ASSOC_LEFT, 17, 0, false}, /* function call */ - { "[", 2, opid1('['), ASSOC_LEFT, 17, 0, false}, /* array subscript */ + {"(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX, false}, /* paren expression - non function call */ + {"_length", 1, opid3('l', 'e', 'n'), ASSOC_RIGHT, 98, OP_PREFIX, true}, - { "++", 1, opid3('+','+','P'), ASSOC_RIGHT, 16, OP_PREFIX, false}, - { "--", 1, opid3('-','-','P'), ASSOC_RIGHT, 16, OP_PREFIX, false}, + {"++", 1, opid3('S', '+', '+'), ASSOC_LEFT, 17, OP_SUFFIX, false}, + {"--", 1, opid3('S', '-', '-'), ASSOC_LEFT, 17, OP_SUFFIX, false}, + {".", 2, opid1('.'), ASSOC_LEFT, 17, 0, false}, + {"(", 0, opid1('('), ASSOC_LEFT, 17, 0, false}, /* function call */ + {"[", 2, opid1('['), ASSOC_LEFT, 17, 0, false}, /* array subscript */ - { "**", 2, opid2('*','*'), ASSOC_RIGHT, 15, 0, true}, + {"++", 1, opid3('+', '+', 'P'), ASSOC_RIGHT, 16, OP_PREFIX, false}, + {"--", 1, opid3('-', '-', 'P'), ASSOC_RIGHT, 16, OP_PREFIX, false}, - { "!", 1, opid2('!','P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, - { "~", 1, opid2('~','P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, - { "+", 1, opid2('+','P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, - { "-", 1, opid2('-','P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, -/* { "&", 1, opid2('&','P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, */ + {"**", 2, opid2('*', '*'), ASSOC_RIGHT, 14, 0, true}, + {"!", 1, opid2('!', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, + {"~", 1, opid2('~', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, + {"+", 1, opid2('+', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, + {"-", 1, opid2('-', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, +/* { "&", 1, opid2('&','P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, */ - { "*", 2, opid1('*'), ASSOC_LEFT, 13, 0, true}, - { "/", 2, opid1('/'), ASSOC_LEFT, 13, 0, true}, - { "%", 2, opid1('%'), ASSOC_LEFT, 13, 0, true}, - { "><", 2, opid2('>','<'), ASSOC_LEFT, 13, 0, true}, + {"*", 2, opid1('*'), ASSOC_LEFT, 13, 0, true}, + {"/", 2, opid1('/'), ASSOC_LEFT, 13, 0, true}, + {"%", 2, opid1('%'), ASSOC_LEFT, 13, 0, true}, + {"><", 2, opid2('>', '<'), ASSOC_LEFT, 13, 0, true}, - { "+", 2, opid1('+'), ASSOC_LEFT, 12, 0, true}, - { "-", 2, opid1('-'), ASSOC_LEFT, 12, 0, true}, + {"+", 2, opid1('+'), ASSOC_LEFT, 12, 0, true}, + {"-", 2, opid1('-'), ASSOC_LEFT, 12, 0, true}, - { "<<", 2, opid2('<','<'), ASSOC_LEFT, 11, 0, true}, - { ">>", 2, opid2('>','>'), ASSOC_LEFT, 11, 0, true}, + {"<<", 2, opid2('<', '<'), ASSOC_LEFT, 11, 0, true}, + {">>", 2, opid2('>', '>'), ASSOC_LEFT, 11, 0, true}, - { "<", 2, opid1('<'), ASSOC_LEFT, 10, 0, false}, - { ">", 2, opid1('>'), ASSOC_LEFT, 10, 0, false}, - { "<=>", 2, opid3('<','=','>'), ASSOC_LEFT, 10, 0, true}, - { "<=", 2, opid2('<','='), ASSOC_LEFT, 10, 0, false}, - { ">=", 2, opid2('>','='), ASSOC_LEFT, 10, 0, false}, + {"<", 2, opid1('<'), ASSOC_LEFT, 10, 0, false}, + {">", 2, opid1('>'), ASSOC_LEFT, 10, 0, false}, + {"<=>", 2, opid3('<', '=', '>'), ASSOC_LEFT, 10, 0, true}, + {"<=", 2, opid2('<', '='), ASSOC_LEFT, 10, 0, false}, + {">=", 2, opid2('>', '='), ASSOC_LEFT, 10, 0, false}, - { "==", 2, opid2('=','='), ASSOC_LEFT, 9, 0, true}, - { "!=", 2, opid2('!','='), ASSOC_LEFT, 9, 0, true}, + {"==", 2, opid2('=', '='), ASSOC_LEFT, 9, 0, true}, + {"!=", 2, opid2('!', '='), ASSOC_LEFT, 9, 0, true}, - { "&", 2, opid1('&'), ASSOC_LEFT, 8, 0, true}, + {"&", 2, opid1('&'), ASSOC_LEFT, 8, 0, true}, - { "^", 2, opid1('^'), ASSOC_LEFT, 7, 0, true}, + {"^", 2, opid1('^'), ASSOC_LEFT, 7, 0, true}, - { "|", 2, opid1('|'), ASSOC_LEFT, 6, 0, true}, + {"|", 2, opid1('|'), ASSOC_LEFT, 6, 0, true}, - { "&&", 2, opid2('&','&'), ASSOC_LEFT, 5, 0, true}, + {"&&", 2, opid2('&', '&'), ASSOC_LEFT, 5, 0, true}, - { "||", 2, opid2('|','|'), ASSOC_LEFT, 4, 0, true}, + {"||", 2, opid2('|', '|'), ASSOC_LEFT, 4, 0, true}, - { "?", 3, opid2('?',':'), ASSOC_RIGHT, 3, 0, true}, + {"?", 3, opid2('?', ':'), ASSOC_RIGHT, 3, 0, true}, - { "=", 2, opid1('='), ASSOC_RIGHT, 2, 0, false}, - { "+=", 2, opid2('+','='), ASSOC_RIGHT, 2, 0, false}, - { "-=", 2, opid2('-','='), ASSOC_RIGHT, 2, 0, false}, - { "*=", 2, opid2('*','='), ASSOC_RIGHT, 2, 0, false}, - { "/=", 2, opid2('/','='), ASSOC_RIGHT, 2, 0, false}, - { "%=", 2, opid2('%','='), ASSOC_RIGHT, 2, 0, false}, - { ">>=", 2, opid3('>','>','='), ASSOC_RIGHT, 2, 0, false}, - { "<<=", 2, opid3('<','<','='), ASSOC_RIGHT, 2, 0, false}, - { "&=", 2, opid2('&','='), ASSOC_RIGHT, 2, 0, false}, - { "^=", 2, opid2('^','='), ASSOC_RIGHT, 2, 0, false}, - { "|=", 2, opid2('|','='), ASSOC_RIGHT, 2, 0, false}, + {"=", 2, opid1('='), ASSOC_RIGHT, 2, 0, false}, + {"+=", 2, opid2('+', '='), ASSOC_RIGHT, 2, 0, false}, + {"-=", 2, opid2('-', '='), ASSOC_RIGHT, 2, 0, false}, + {"*=", 2, opid2('*', '='), ASSOC_RIGHT, 2, 0, false}, + {"/=", 2, opid2('/', '='), ASSOC_RIGHT, 2, 0, false}, + {"%=", 2, opid2('%', '='), ASSOC_RIGHT, 2, 0, false}, + {">>=", 2, opid3('>', '>', '='), ASSOC_RIGHT, 2, 0, false}, + {"<<=", 2, opid3('<', '<', '='), ASSOC_RIGHT, 2, 0, false}, + {"&=", 2, opid2('&', '='), ASSOC_RIGHT, 2, 0, false}, + {"^=", 2, opid2('^', '='), ASSOC_RIGHT, 2, 0, false}, + {"|=", 2, opid2('|', '='), ASSOC_RIGHT, 2, 0, false}, - { ":", 0, opid2(':','?'), ASSOC_RIGHT, 1, 0, false}, + {":", 0, opid2(':', '?'), ASSOC_RIGHT, 1, 0, false}, - { ",", 2, opid1(','), ASSOC_LEFT, 0, 0, false} + {",", 2, opid1(','), ASSOC_LEFT, 0, 0, false} }; static const oper_info fte_operators[] = { - { "(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX, false}, /* paren expression - non function call */ - - { "++", 1, opid3('S','+','+'), ASSOC_LEFT, 15, OP_SUFFIX, false}, - { "--", 1, opid3('S','-','-'), ASSOC_LEFT, 15, OP_SUFFIX, false}, - { ".", 2, opid1('.'), ASSOC_LEFT, 15, 0, false}, - { "(", 0, opid1('('), ASSOC_LEFT, 15, 0, false}, /* function call */ - { "[", 2, opid1('['), ASSOC_LEFT, 15, 0, false}, /* array subscript */ - - { "!", 1, opid2('!','P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, - { "+", 1, opid2('+','P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, - { "-", 1, opid2('-','P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, - { "++", 1, opid3('+','+','P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, - { "--", 1, opid3('-','-','P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, - - { "*", 2, opid1('*'), ASSOC_LEFT, 13, 0, true}, - { "/", 2, opid1('/'), ASSOC_LEFT, 13, 0, true}, - { "&", 2, opid1('&'), ASSOC_LEFT, 13, 0, true}, - { "|", 2, opid1('|'), ASSOC_LEFT, 13, 0, true}, - - { "+", 2, opid1('+'), ASSOC_LEFT, 12, 0, true}, - { "-", 2, opid1('-'), ASSOC_LEFT, 12, 0, true}, - - { "<<", 2, opid2('<','<'), ASSOC_LEFT, 11, 0, true}, - { ">>", 2, opid2('>','>'), ASSOC_LEFT, 11, 0, true}, - - { "<", 2, opid1('<'), ASSOC_LEFT, 10, 0, false}, - { ">", 2, opid1('>'), ASSOC_LEFT, 10, 0, false}, - { "<=", 2, opid2('<','='), ASSOC_LEFT, 10, 0, false}, - { ">=", 2, opid2('>','='), ASSOC_LEFT, 10, 0, false}, - { "==", 2, opid2('=','='), ASSOC_LEFT, 10, 0, true}, - { "!=", 2, opid2('!','='), ASSOC_LEFT, 10, 0, true}, - - { "?", 3, opid2('?',':'), ASSOC_RIGHT, 9, 0, true}, - - { "=", 2, opid1('='), ASSOC_RIGHT, 8, 0, false}, - { "+=", 2, opid2('+','='), ASSOC_RIGHT, 8, 0, false}, - { "-=", 2, opid2('-','='), ASSOC_RIGHT, 8, 0, false}, - { "*=", 2, opid2('*','='), ASSOC_RIGHT, 8, 0, false}, - { "/=", 2, opid2('/','='), ASSOC_RIGHT, 8, 0, false}, - { "%=", 2, opid2('%','='), ASSOC_RIGHT, 8, 0, false}, - { "&=", 2, opid2('&','='), ASSOC_RIGHT, 8, 0, false}, - { "|=", 2, opid2('|','='), ASSOC_RIGHT, 8, 0, false}, - { "&~=", 2, opid3('&','~','='), ASSOC_RIGHT, 8, 0, false}, - - { "&&", 2, opid2('&','&'), ASSOC_LEFT, 5, 0, true}, - { "||", 2, opid2('|','|'), ASSOC_LEFT, 5, 0, true}, - - /* Leave precedence 3 for : with -fcorrect-ternary */ - { ",", 2, opid1(','), ASSOC_LEFT, 2, 0, false}, - { ":", 0, opid2(':','?'), ASSOC_RIGHT, 1, 0, false} + {"(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX, false}, /* paren expression - non function call */ + + {"++", 1, opid3('S', '+', '+'), ASSOC_LEFT, 15, OP_SUFFIX, false}, + {"--", 1, opid3('S', '-', '-'), ASSOC_LEFT, 15, OP_SUFFIX, false}, + {".", 2, opid1('.'), ASSOC_LEFT, 15, 0, false}, + {"(", 0, opid1('('), ASSOC_LEFT, 15, 0, false}, /* function call */ + {"[", 2, opid1('['), ASSOC_LEFT, 15, 0, false}, /* array subscript */ + + {"!", 1, opid2('!', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, + {"+", 1, opid2('+', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, + {"-", 1, opid2('-', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, + {"++", 1, opid3('+', '+', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, + {"--", 1, opid3('-', '-', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, + + {"*", 2, opid1('*'), ASSOC_LEFT, 13, 0, true}, + {"/", 2, opid1('/'), ASSOC_LEFT, 13, 0, true}, + {"&", 2, opid1('&'), ASSOC_LEFT, 13, 0, true}, + {"|", 2, opid1('|'), ASSOC_LEFT, 13, 0, true}, + + {"+", 2, opid1('+'), ASSOC_LEFT, 12, 0, true}, + {"-", 2, opid1('-'), ASSOC_LEFT, 12, 0, true}, + + {"<<", 2, opid2('<', '<'), ASSOC_LEFT, 11, 0, true}, + {">>", 2, opid2('>', '>'), ASSOC_LEFT, 11, 0, true}, + + {"<", 2, opid1('<'), ASSOC_LEFT, 10, 0, false}, + {">", 2, opid1('>'), ASSOC_LEFT, 10, 0, false}, + {"<=", 2, opid2('<', '='), ASSOC_LEFT, 10, 0, false}, + {">=", 2, opid2('>', '='), ASSOC_LEFT, 10, 0, false}, + {"==", 2, opid2('=', '='), ASSOC_LEFT, 10, 0, true}, + {"!=", 2, opid2('!', '='), ASSOC_LEFT, 10, 0, true}, + + {"?", 3, opid2('?', ':'), ASSOC_RIGHT, 9, 0, true}, + + {"=", 2, opid1('='), ASSOC_RIGHT, 8, 0, false}, + {"+=", 2, opid2('+', '='), ASSOC_RIGHT, 8, 0, false}, + {"-=", 2, opid2('-', '='), ASSOC_RIGHT, 8, 0, false}, + {"*=", 2, opid2('*', '='), ASSOC_RIGHT, 8, 0, false}, + {"/=", 2, opid2('/', '='), ASSOC_RIGHT, 8, 0, false}, + {"%=", 2, opid2('%', '='), ASSOC_RIGHT, 8, 0, false}, + {"&=", 2, opid2('&', '='), ASSOC_RIGHT, 8, 0, false}, + {"|=", 2, opid2('|', '='), ASSOC_RIGHT, 8, 0, false}, + {"&~=", 2, opid3('&', '~', '='), ASSOC_RIGHT, 8, 0, false}, + + {"&&", 2, opid2('&', '&'), ASSOC_LEFT, 5, 0, true}, + {"||", 2, opid2('|', '|'), ASSOC_LEFT, 5, 0, true}, + + /* Leave precedence 3 for : with -fcorrect-ternary */ + {",", 2, opid1(','), ASSOC_LEFT, 2, 0, false}, + {":", 0, opid2(':', '?'), ASSOC_RIGHT, 1, 0, false} }; static const oper_info qcc_operators[] = { - { "(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX, false}, /* paren expression - non function call */ - - { ".", 2, opid1('.'), ASSOC_LEFT, 15, 0, false}, - { "(", 0, opid1('('), ASSOC_LEFT, 15, 0, false}, /* function call */ - { "[", 2, opid1('['), ASSOC_LEFT, 15, 0, false}, /* array subscript */ - - { "!", 1, opid2('!','P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, - { "+", 1, opid2('+','P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, - { "-", 1, opid2('-','P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, - - { "*", 2, opid1('*'), ASSOC_LEFT, 13, 0, true}, - { "/", 2, opid1('/'), ASSOC_LEFT, 13, 0, true}, - { "&", 2, opid1('&'), ASSOC_LEFT, 13, 0, true}, - { "|", 2, opid1('|'), ASSOC_LEFT, 13, 0, true}, - - { "+", 2, opid1('+'), ASSOC_LEFT, 12, 0, true}, - { "-", 2, opid1('-'), ASSOC_LEFT, 12, 0, true}, - - { "<", 2, opid1('<'), ASSOC_LEFT, 10, 0, false}, - { ">", 2, opid1('>'), ASSOC_LEFT, 10, 0, false}, - { "<=", 2, opid2('<','='), ASSOC_LEFT, 10, 0, false}, - { ">=", 2, opid2('>','='), ASSOC_LEFT, 10, 0, false}, - { "==", 2, opid2('=','='), ASSOC_LEFT, 10, 0, true}, - { "!=", 2, opid2('!','='), ASSOC_LEFT, 10, 0, true}, - - { "=", 2, opid1('='), ASSOC_RIGHT, 8, 0, false}, - { "+=", 2, opid2('+','='), ASSOC_RIGHT, 8, 0, false}, - { "-=", 2, opid2('-','='), ASSOC_RIGHT, 8, 0, false}, - { "*=", 2, opid2('*','='), ASSOC_RIGHT, 8, 0, false}, - { "/=", 2, opid2('/','='), ASSOC_RIGHT, 8, 0, false}, - { "%=", 2, opid2('%','='), ASSOC_RIGHT, 8, 0, false}, - { "&=", 2, opid2('&','='), ASSOC_RIGHT, 8, 0, false}, - { "|=", 2, opid2('|','='), ASSOC_RIGHT, 8, 0, false}, - - { "&&", 2, opid2('&','&'), ASSOC_LEFT, 5, 0, true}, - { "||", 2, opid2('|','|'), ASSOC_LEFT, 5, 0, true}, - - { ",", 2, opid1(','), ASSOC_LEFT, 2, 0, false}, + {"(", 0, opid1('('), ASSOC_LEFT, 99, OP_PREFIX, false}, /* paren expression - non function call */ + + {".", 2, opid1('.'), ASSOC_LEFT, 15, 0, false}, + {"(", 0, opid1('('), ASSOC_LEFT, 15, 0, false}, /* function call */ + {"[", 2, opid1('['), ASSOC_LEFT, 15, 0, false}, /* array subscript */ + + {"!", 1, opid2('!', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, + {"+", 1, opid2('+', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, false}, + {"-", 1, opid2('-', 'P'), ASSOC_RIGHT, 14, OP_PREFIX, true}, + + {"*", 2, opid1('*'), ASSOC_LEFT, 13, 0, true}, + {"/", 2, opid1('/'), ASSOC_LEFT, 13, 0, true}, + {"&", 2, opid1('&'), ASSOC_LEFT, 13, 0, true}, + {"|", 2, opid1('|'), ASSOC_LEFT, 13, 0, true}, + + {"+", 2, opid1('+'), ASSOC_LEFT, 12, 0, true}, + {"-", 2, opid1('-'), ASSOC_LEFT, 12, 0, true}, + + {"<", 2, opid1('<'), ASSOC_LEFT, 10, 0, false}, + {">", 2, opid1('>'), ASSOC_LEFT, 10, 0, false}, + {"<=", 2, opid2('<', '='), ASSOC_LEFT, 10, 0, false}, + {">=", 2, opid2('>', '='), ASSOC_LEFT, 10, 0, false}, + {"==", 2, opid2('=', '='), ASSOC_LEFT, 10, 0, true}, + {"!=", 2, opid2('!', '='), ASSOC_LEFT, 10, 0, true}, + + {"=", 2, opid1('='), ASSOC_RIGHT, 8, 0, false}, + {"+=", 2, opid2('+', '='), ASSOC_RIGHT, 8, 0, false}, + {"-=", 2, opid2('-', '='), ASSOC_RIGHT, 8, 0, false}, + {"*=", 2, opid2('*', '='), ASSOC_RIGHT, 8, 0, false}, + {"/=", 2, opid2('/', '='), ASSOC_RIGHT, 8, 0, false}, + {"%=", 2, opid2('%', '='), ASSOC_RIGHT, 8, 0, false}, + {"&=", 2, opid2('&', '='), ASSOC_RIGHT, 8, 0, false}, + {"|=", 2, opid2('|', '='), ASSOC_RIGHT, 8, 0, false}, + + {"&&", 2, opid2('&', '&'), ASSOC_LEFT, 5, 0, true}, + {"||", 2, opid2('|', '|'), ASSOC_LEFT, 5, 0, true}, + + {",", 2, opid1(','), ASSOC_LEFT, 2, 0, false}, }; extern const oper_info *operators; -extern size_t operator_count; +extern size_t operator_count; #endif