/* Impl format: * "impl" [<type_bounds>] <qualified_ident>[<type_bounds>] ["for" <qualified_ident>[<type_bounds>]] "{" [<body>] "}" */ static void parseImpl (lexerState *lexer, vString *scope, int parent_kind) { unsigned long line; fpos_t pos; vString *name; advanceToken(lexer, TRUE); line = lexer->line; pos = lexer->pos; skipTypeBlock(lexer); name = vStringNew(); parseQualifiedType(lexer, name); if (lexer->cur_token == TOKEN_IDENT && strcmp(lexer->token_str->buffer, "for") == 0) { advanceToken(lexer, TRUE); parseQualifiedType(lexer, name); } addTag(name, NULL, K_IMPL, line, pos, scope, parent_kind); addToScope(scope, name); parseBlock(lexer, TRUE, K_IMPL, scope); vStringDelete(name); }
static struct exp *parseRelation() /* Parse key=wildcard. */ { struct kxTok *key, *match; if (token == NULL) return NULL; if (token->type != kxtString) errAbort("Expecting key got %s", token->string); key = token; advanceToken(); if (token->type == kxtEquals) { advanceToken(); if (token->type == kxtString || token->type == kxtWildString) { struct exp *exp; match = token; advanceToken(); AllocVar(exp); exp->left = key->string; exp->right = match->string; exp->type = (match->type == kxtString ? kxMatch : kxWildMatch); return exp; } else { errAbort("Expecting string to match in key=match expression,\ngot %s", token->string); } } else if (token->type == kxtGT || token->type == kxtGE || token->type == kxtLT || token->type == kxtLE) { enum kxTokType relation = token->type; advanceToken(); if (isdigit(token->string[0])) { struct exp *exp; match = token; advanceToken(); AllocVar(exp); exp->left = key->string; exp->right = match->string; if (relation == kxtGT) exp->type = kxGT; else if (relation == kxtGE) exp->type = kxGE; else if (relation == kxtLT) exp->type = kxLT; else if (relation == kxtLE) exp->type = kxLE; return exp; } else { errAbort("Expecting number got %s", token->string); } } else errAbort("Expecting = got %s", token->string); return NULL; }
/* Mod format: * "mod" <ident> "{" [<body>] "}" * "mod" <ident> ";"*/ static void parseMod (lexerState *lexer, vString *scope, int parent_kind) { advanceToken(lexer, TRUE); if (lexer->cur_token != TOKEN_IDENT) return; addTag(lexer->token_str, NULL, K_MOD, lexer->line, lexer->pos, scope, parent_kind); addToScope(scope, lexer->token_str); advanceToken(lexer, TRUE); parseBlock(lexer, TRUE, K_MOD, scope); }
/* Static format: * "static" ["mut"] <ident> */ static void parseStatic (lexerState *lexer, vString *scope, int parent_kind) { advanceToken(lexer, TRUE); if (lexer->cur_token != TOKEN_IDENT) return; if (strcmp(lexer->token_str->buffer, "mut") == 0) { advanceToken(lexer, TRUE); } if (lexer->cur_token != TOKEN_IDENT) return; addTag(lexer->token_str, NULL, K_STATIC, lexer->line, lexer->pos, scope, parent_kind); }
static struct exp *parseOrExp() /* Parse lowest level of precedent expressions - or and xor. */ { struct exp *left; struct exp *right, *exp; struct kxTok *tok; enum kxTokType type; if ((left = parseAndExp()) == NULL) return NULL; if ((tok = token) == NULL) return left; type = token->type; if (type == kxtOr || type == kxtXor) { advanceToken(); right = nextExp(); if (right == NULL) errAbort("Expecting expression on the other side of %s", tok->string); AllocVar(exp); exp->left = left; exp->right = right; if (type == kxtOr) exp->type = kxOr; else exp->type = kxXor; return exp; } else return left; }
static struct exp *parseAndExp() /* Parse and level expressions. */ { struct exp *left; struct exp *right, *exp; struct kxTok *tok; enum kxTokType type; if ((left = parseNot()) == NULL) return NULL; if ((tok = token) == NULL) return left; type = token->type; if (type == kxtAnd) { advanceToken(); right = nextExp(); if (right == NULL) errAbort("Expecting expression on the other side of %s", tok->string); AllocVar(exp); exp->left = left; exp->right = right; exp->type = kxAnd; return exp; } else return left; }
bool Tokenizer::setCurrentPos(U32 pos) { mCurrPos = pos; mTokenIsCurrent = false; return advanceToken(true); }
/* * Macro rules format: * "macro_rules" "!" <ident> <macro_body> */ static void parseMacroRules (lexerState *lexer, vString *scope, int parent_kind) { advanceToken(lexer, TRUE); if (lexer->cur_token != '!') return; advanceToken(lexer, TRUE); if (lexer->cur_token != TOKEN_IDENT) return; addTag(lexer->token_str, NULL, K_MACRO, lexer->line, lexer->pos, scope, parent_kind); skipMacro(lexer); }
// operator // : PLUS | DASH | STAR | SLASH | ... bool HlslGrammar::acceptOperator(TOperator& op) { switch (token.tokenClass) { case EHTokEqual: op = EOpAssign; break; case EHTokPlus: op = EOpAdd; break; case EHTokDash: op = EOpSub; break; case EHTokStar: op = EOpMul; break; case EHTokSlash: op = EOpDiv; break; default: return false; } advanceToken(); return true; }
// Accept an assignment expression, where assignment operations // associate right-to-left. This is, it is implicit, for example // // a op (b op (c op d)) // // assigment_expression // : binary_expression op binary_expression op binary_expression ... // bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node) { if (! acceptBinaryExpression(node, PlLogicalOr)) return false; TOperator assignOp = HlslOpMap::assignment(peek()); if (assignOp == EOpNull) return true; // ... op TSourceLoc loc = token.loc; advanceToken(); // ... binary_expression // But, done by recursing this function, which automatically // gets the right-to-left associativity. TIntermTyped* rightNode = nullptr; if (! acceptAssignmentExpression(rightNode)) { expected("assignment expression"); return false; } node = intermediate.addAssign(assignOp, node, rightNode, loc); if (! peekTokenClass(EHTokComma)) return true; return true; }
// Accept a binary expression, for binary operations that // associate left-to-right. This is, it is implicit, for example // // ((a op b) op c) op d // // binary_expression // : expression op expression op expression ... // // where 'expression' is the next higher level in precedence. // bool HlslGrammar::acceptBinaryExpression(TIntermTyped*& node, PrecedenceLevel precedenceLevel) { if (precedenceLevel > PlMul) return acceptUnaryExpression(node); // assignment_expression if (! acceptBinaryExpression(node, (PrecedenceLevel)(precedenceLevel + 1))) return false; TOperator op = HlslOpMap::binary(peek()); PrecedenceLevel tokenLevel = HlslOpMap::precedenceLevel(op); if (tokenLevel < precedenceLevel) return true; do { // ... op TSourceLoc loc = token.loc; advanceToken(); // ... expression TIntermTyped* rightNode = nullptr; if (! acceptBinaryExpression(rightNode, (PrecedenceLevel)(precedenceLevel + 1))) { expected("expression"); return false; } node = intermediate.addBinaryMath(op, node, rightNode, loc); if (! peekTokenClass(EHTokComma)) return true; } while (true); }
// The top-level full expression recognizer. // // expression // : assignment_expression COMMA assignment_expression COMMA assignment_expression ... // bool HlslGrammar::acceptExpression(TIntermTyped*& node) { // assignment_expression if (! acceptAssignmentExpression(node)) return false; if (! peekTokenClass(EHTokComma)) return true; do { // ... COMMA TSourceLoc loc = token.loc; advanceToken(); // ... assignment_expression TIntermTyped* rightNode = nullptr; if (! acceptAssignmentExpression(rightNode)) { expected("assignment expression"); return false; } node = intermediate.addComma(node, rightNode, loc); if (! peekTokenClass(EHTokComma)) return true; } while (true); }
/* Type format: * "type" <ident> */ static void parseType (lexerState *lexer, vString *scope, int parent_kind) { advanceToken(lexer, TRUE); if (lexer->cur_token != TOKEN_IDENT) return; addTag(lexer->token_str, NULL, K_TYPE, lexer->line, lexer->pos, scope, parent_kind); }
/* Skips type blocks of the form <T:T<T>, ...> */ static void skipTypeBlock (lexerState *lexer) { if (lexer->cur_token == '<') { skipUntil(lexer, NULL, 0); advanceToken(lexer, TRUE); } }
/* Trait format: * "trait" <ident> [<type_bounds>] "{" [<body>] "}" */ static void parseTrait (lexerState *lexer, vString *scope, int parent_kind) { int goal_tokens[] = {'{'}; advanceToken(lexer, TRUE); if (lexer->cur_token != TOKEN_IDENT) return; addTag(lexer->token_str, NULL, K_TRAIT, lexer->line, lexer->pos, scope, parent_kind); addToScope(scope, lexer->token_str); advanceToken(lexer, TRUE); skipUntil(lexer, goal_tokens, 1); parseBlock(lexer, TRUE, K_TRAIT, scope); }
static void initLexer (lexerState *lexer) { advanceNChar(lexer, 2); lexer->token_str = vStringNew(); if (lexer->cur_c == '#' && lexer->next_c == '!') scanComments(lexer); advanceToken(lexer, TRUE); }
// Return true and advance to the next token if the current token is the // expected (passed in) token class. bool HlslGrammar::acceptTokenClass(EHlslTokenClass tokenClass) { if (token.tokenClass == tokenClass) { advanceToken(); return true; } return false; }
// Only process the next token if it is an identifier. // Return true if it was an identifier. bool HlslGrammar::acceptIdentifier(HlslToken& idToken) { if (peekTokenClass(EHTokIdentifier)) { idToken = token; advanceToken(); return true; } return false; }
static struct exp *parseParenthesized() /* Parse parenthesized expressions. */ { struct exp *exp; if (token == NULL) return NULL; if (token->type == kxtOpenParen) { advanceToken(); exp = nextExp(); if (token->type != kxtCloseParen) errAbort("Unmatched parenthesis"); advanceToken(); return exp; } else { return parseRelation(); } }
struct expression *parse() { init(); advanceToken(); struct expression *prop = parse_prop(); if (is_empty_expression(prop) || current_token == NULL || current_token->type != End) { return NULL; } return prop; }
/* Skip the body of the macro. Can't use skipUntil here as * the body of the macro may have arbitrary code which confuses it (e.g. * bitshift operators/function return arrows) */ static void skipMacro (lexerState *lexer) { int level = 0; int plus_token = 0; int minus_token = 0; advanceToken(lexer, TRUE); switch (lexer->cur_token) { case '(': plus_token = '('; minus_token = ')'; break; case '{': plus_token = '{'; minus_token = '}'; break; case '[': plus_token = '['; minus_token = ']'; break; default: return; } while (lexer->cur_token != TOKEN_EOF) { if (lexer->cur_token == plus_token) level++; else if (lexer->cur_token == minus_token) level--; if (level == 0) break; advanceToken(lexer, TRUE); } advanceToken(lexer, TRUE); }
struct expression *parse_term() { struct expression *term; if (current_token == NULL) return NULL; switch (current_token->type) { case Var: term = new_var_expression(current_token->u.var_id); advanceToken(); return term; case LeftParen: advanceToken(); term = parse_prop(); if (is_empty_expression(term)) { return NULL; } switch (current_token->type) { case RightParen: advanceToken(); return term; default: return NULL; } case OpNot: advanceToken(); term = new_op_expression(NotExp, parse_term(), NULL); if (is_left_child_empty(term)) { destroy_expression(term); return NULL; } return term; default: return NULL; } }
// If token is a qualifier, return its token class and advance to the next // qualifier. Otherwise, return false, and don't advance. void HlslGrammar::acceptQualifier(TQualifier& qualifier) { switch (token.tokenClass) { case EHTokUniform: qualifier.storage = EvqUniform; break; case EHTokConst: qualifier.storage = EvqConst; break; default: return; } advanceToken(); }
bool Tokenizer::findToken(U32 start, const char* pCmp) { // Move to the start setCurrentPos(start); // In case the first token is what we are looking for if (tokenICmp(pCmp)) return true; // Loop through the file and see if the token exists while (advanceToken(true)) { if (tokenICmp(pCmp)) return true; } return false; }
/* Essentially grabs the last ident before 'for', '<' and '{', which * tends to correspond to what we want as the impl tag entry name */ static void parseQualifiedType (lexerState *lexer, vString* name) { while (lexer->cur_token != TOKEN_EOF) { if (lexer->cur_token == TOKEN_IDENT) { if (strcmp(lexer->token_str->buffer, "for") == 0) break; vStringClear(name); vStringCat(name, lexer->token_str); } else if (lexer->cur_token == '<' || lexer->cur_token == '{') { break; } advanceToken(lexer, TRUE); } skipTypeBlock(lexer); }
static struct exp *parseNot() /* Parse not */ { struct exp *exp; struct exp *right; if (token == NULL) return NULL; if (token->type == kxtNot) { advanceToken(); right = nextExp(); AllocVar(exp); exp->right = right; exp->type = kxNot; return exp; } else return parseParenthesized(); }
struct expression *parse_prop() { struct expression *exp = parse_exp(); if (is_empty_expression(exp) || current_token == NULL) return NULL; switch (current_token->type) { case OpOr: advanceToken(); struct expression *prop = new_op_expression(OrExp, exp, parse_prop()); if (is_right_child_empty(prop)) { destroy_expression(exp); return NULL; } return prop; default: return exp; } }
struct expression *parse_exp() { struct expression *term = parse_term(); if (is_empty_expression(term)) return NULL; if (current_token == NULL) return NULL; switch (current_token->type) { case OpAnd: advanceToken(); struct expression *exp = new_op_expression(AndExp, term, parse_exp()); if (is_right_child_empty(exp)) { destroy_expression(exp); return NULL; } return exp; default: return term; } }
// unary_expression // : + unary_expression // | - unary_expression // | ! unary_expression // | ~ unary_expression // | ++ unary_expression // | -- unary_expression // | postfix_expression // bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node) { TOperator unaryOp = HlslOpMap::preUnary(peek()); // postfix_expression if (unaryOp == EOpNull) return acceptPostfixExpression(node); // op unary_expression TSourceLoc loc = token.loc; advanceToken(); if (! acceptUnaryExpression(node)) return false; // + is a no-op if (unaryOp == EOpAdd) return true; node = intermediate.addUnaryMath(unaryOp, node, loc); return node != nullptr; }
bool HlslGrammar::acceptLiteral(TIntermTyped*& node) { switch (token.tokenClass) { case EHTokIntConstant: node = intermediate.addConstantUnion(token.i, token.loc, true); break; case EHTokFloatConstant: node = intermediate.addConstantUnion(token.d, EbtFloat, token.loc, true); break; case EHTokDoubleConstant: node = intermediate.addConstantUnion(token.d, EbtDouble, token.loc, true); break; case EHTokBoolConstant: node = intermediate.addConstantUnion(token.b, token.loc, true); break; default: return false; } advanceToken(); return true; }