Statement *ParserContext::parse_statement() { Statement *statement = 0; switch (curtok()->type()) { case tok_while: { statement = parse_while(); break; } case tok_if: { statement = parse_if(); break; } case tok_return: { statement = parse_return(); eat_token(tok_semicolon); break; } case tok_def: { statement = parse_def(); break; } default: { Expression *expression = parse_expression(); if (expression) { statement = new ExpressionStatement(expression); eat_token(tok_semicolon); } else { throw UnexpectedToken("parse_statement", curtok()); } break; } } return statement; }
/*----------------------------------------------------------------------*/ static ast_statement_t *parse_statement(parse_state_t *p) { token_t *token; token = peek_token(p); if (token == NULL) { return NULL; } else if (test_token(token, TK_ELSE) || test_token(token, TK_END)) { return NULL; } else if (test_token(token, TK_VAR)) { return parse_declare_var(p); } else if (test_token(token, TK_FUNCTION)) { return parse_define_function(p); } else if (test_token(token, TK_RETURN)) { return parse_return(p); } else if (test_token(token, TK_IF)) { return parse_if(p); } else if (test_token(token, TK_FOR)) { return parse_for(p); } else if (test_token(token, TK_IDENTIFIER)) { return parse_assignment(p); } next_token(p); error(p, "statement expected"); return NULL; /* unreachable */ }
instruction_ptr Parser::parse_instruction() { if (!ErrorHandler::is_ok()) return instruction_ptr(); save(); instruction_ptr result = parse_assignment(); if (!result) { restore(); result = parse_expression(); } if (!result) result = parse_if_block(); if (!result) result = parse_while_block(); if (!result) result = parse_return(); if (!result) result = parse_print(); if (!result) result = parse_read(); if (result) next_line(); return result; }
// Statement // Parses a single full statement. In general this means a declaration // or an expression, but also includes things like return and break // statements. StatementNode* Parser::parse_statement() { switch (token_iter->type) { // Return statement case K_RETURN: { return parse_return(); } // Declaration case K_CONST: case K_VAL: case K_VAR: case K_FN: case K_STRUCT: case K_TYPE: { return parse_declaration(); } // Expression case INTEGER_LIT: case FLOAT_LIT: case STRING_LIT: case RAW_STRING_LIT: case LPAREN: case IDENTIFIER: case OPERATOR: case DOLLAR: { return parse_expression(); } default: { // Error std::ostringstream msg; msg << "Unknown statement '" << token_iter->text << "'."; parsing_error(*token_iter, msg.str()); throw 0; // Silence warnings about not returning, parsing_error throws anyway } } }
/** Parse statement. * * @param parse Parser object. * @return New syntax tree node. */ stree_stat_t *parse_stat(parse_t *parse) { stree_stat_t *stat; stree_vdecl_t *vdecl_s; stree_if_t *if_s; stree_switch_t *switch_s; stree_while_t *while_s; stree_for_t *for_s; stree_raise_t *raise_s; stree_break_t *break_s; stree_return_t *return_s; stree_wef_t *wef_s; stree_exps_t *exp_s; #ifdef DEBUG_PARSE_TRACE printf("Parse statement.\n"); #endif switch (lcur_lc(parse)) { case lc_var: vdecl_s = parse_vdecl(parse); stat = stree_stat_new(st_vdecl); stat->u.vdecl_s = vdecl_s; break; case lc_if: if_s = parse_if(parse); stat = stree_stat_new(st_if); stat->u.if_s = if_s; break; case lc_switch: switch_s = parse_switch(parse); stat = stree_stat_new(st_switch); stat->u.switch_s = switch_s; break; case lc_while: while_s = parse_while(parse); stat = stree_stat_new(st_while); stat->u.while_s = while_s; break; case lc_for: for_s = parse_for(parse); stat = stree_stat_new(st_for); stat->u.for_s = for_s; break; case lc_raise: raise_s = parse_raise(parse); stat = stree_stat_new(st_raise); stat->u.raise_s = raise_s; break; case lc_break: break_s = parse_break(parse); stat = stree_stat_new(st_break); stat->u.break_s = break_s; break; case lc_return: return_s = parse_return(parse); stat = stree_stat_new(st_return); stat->u.return_s = return_s; break; case lc_do: case lc_with: wef_s = parse_wef(parse); stat = stree_stat_new(st_wef); stat->u.wef_s = wef_s; break; default: exp_s = parse_exps(parse); stat = stree_stat_new(st_exps); stat->u.exp_s = exp_s; break; } #ifdef DEBUG_PARSE_TRACE printf("Parsed statement %p\n", stat); #endif return stat; }
/* * Parse one statement. 'foo = bar', or 'if (...) {...}', or '{...}', * and so on. */ static int parse_statement(policy_lex_file_t *lexer, policy_item_t **tail) { int rcode; policy_reserved_word_t reserved; policy_lex_t token, assign; char lhs[256], rhs[256]; policy_assignment_t *this; /* * See what kind of token we have. */ token = policy_lex_file(lexer, 0, lhs, sizeof(lhs)); switch (token) { case POLICY_LEX_LC_BRACKET: rcode = parse_block(lexer, tail); if (!rcode) { return 0; } break; case POLICY_LEX_BARE_WORD: reserved = fr_str2int(policy_reserved_words, lhs, POLICY_RESERVED_UNKNOWN); switch (reserved) { case POLICY_RESERVED_IF: if (parse_if(lexer, tail)) { return 1; } return 0; break; case POLICY_RESERVED_CONTROL: case POLICY_RESERVED_REQUEST: case POLICY_RESERVED_REPLY: case POLICY_RESERVED_PROXY_REQUEST: case POLICY_RESERVED_PROXY_REPLY: if (parse_attribute_block(lexer, tail, reserved)) return 1; return 0; break; case POLICY_RESERVED_PRINT: if (parse_print(lexer, tail)) { return 1; } return 0; break; case POLICY_RESERVED_RETURN: if (parse_return(lexer, tail)) { return 1; } return 0; break; case POLICY_RESERVED_MODULE: if (parse_module(lexer, tail)) { return 1; } return 0; break; case POLICY_RESERVED_UNKNOWN: /* wasn't a reserved word */ /* * Is a named policy, parse the reference to it. */ if (rlm_policy_find(lexer->policies, lhs) != NULL) { if (!parse_call(lexer, tail, lhs)) { return 0; } return 1; } { const DICT_ATTR *dattr; /* * Bare words MUST be dictionary attributes */ dattr = dict_attrbyname(lhs); if (!dattr) { fprintf(stderr, "%s[%d]: Expected attribute name, got \"%s\"\n", lexer->filename, lexer->lineno, lhs); return 0; } debug_tokens("%s[%d]: Got attribute %s\n", lexer->filename, lexer->lineno, lhs); } break; default: fprintf(stderr, "%s[%d]: Unexpected reserved word \"%s\"\n", lexer->filename, lexer->lineno, lhs); return 0; } /* switch over reserved words */ break; /* * Return from nested blocks. */ case POLICY_LEX_RC_BRACKET: policy_lex_push_token(lexer, token); return 2; /* magic */ case POLICY_LEX_EOF: /* nothing more to do */ return 3; default: fprintf(stderr, "%s[%d]: Unexpected %s\n", lexer->filename, lexer->lineno, fr_int2str(policy_explanations, token, "string")); break; } /* * Parse a bare statement. */ assign = policy_lex_file(lexer, 0, rhs, sizeof(rhs)); switch (assign) { case POLICY_LEX_ASSIGN: case POLICY_LEX_SET_EQUALS: case POLICY_LEX_AND_EQUALS: case POLICY_LEX_OR_EQUALS: case POLICY_LEX_PLUS_EQUALS: break; default: fprintf(stderr, "%s[%d]: Unexpected assign %s\n", lexer->filename, lexer->lineno, fr_int2str(policy_explanations, assign, "string")); return 0; } this = rad_malloc(sizeof(*this)); memset(this, 0, sizeof(*this)); this->item.type = POLICY_TYPE_ASSIGNMENT; this->item.lineno = lexer->lineno; token = policy_lex_file(lexer, 0, rhs, sizeof(rhs)); if ((token != POLICY_LEX_BARE_WORD) && (token != POLICY_LEX_DOUBLE_QUOTED_STRING)) { fprintf(stderr, "%s[%d]: Unexpected rhs %s\n", lexer->filename, lexer->lineno, fr_int2str(policy_explanations, token, "string")); rlm_policy_free_item((policy_item_t *) this); return 0; } this->rhs_type = token; this->rhs = strdup(rhs); token = policy_lex_file(lexer, POLICY_LEX_FLAG_RETURN_EOL, rhs, sizeof(rhs)); if (token != POLICY_LEX_EOL) { fprintf(stderr, "%s[%d]: Expected EOL\n", lexer->filename, lexer->lineno); rlm_policy_free_item((policy_item_t *) this); return 0; } debug_tokens("[ASSIGN %s %s %s]\n", lhs, fr_int2str(rlm_policy_tokens, assign, "?"), rhs); /* * Fill in the assignment struct */ this->lhs = strdup(lhs); this->assign = assign; *tail = (policy_item_t *) this; return 1; }
struct node *parse_factor(struct compiler *compiler) { switch (lexer_current(compiler)) { case T_BEGIN: return parse_begin(compiler); case T_IF: return parse_if(compiler); case T_UNLESS: return parse_unless(compiler); case T_CASE: return parse_case(compiler); case T_CLASS: return parse_class(compiler); case T_MODULE: return parse_module(compiler); case T_DEF: return parse_method(compiler); case T_YIELD: return parse_yield(compiler); case T_RETURN: return parse_return(compiler); case T_BREAK: return parse_break(compiler); case T_NEXT: return parse_next(compiler); case T_REDO: return parse_redo(compiler); case T_SQUARE_OPEN: { struct node *result = alloc_node(compiler, N_ARRAY); lexer_next(compiler); if(lexer_current(compiler) == T_SQUARE_CLOSE) result->left = 0; else result->left = parse_array_element(compiler); lexer_match(compiler, T_SQUARE_CLOSE); return result; } case T_STRING: { struct node *result = alloc_node(compiler, N_STRING); result->left = (void *)lexer_token(compiler)->start; lexer_next(compiler); return result; } case T_STRING_START: { struct node *result = alloc_node(compiler, N_STRING_CONTINUE); result->left = 0; result->middle = (void *)lexer_token(compiler)->start; lexer_next(compiler); result->right = parse_statements(compiler); while(lexer_current(compiler) == T_STRING_CONTINUE) { struct node *node = alloc_node(compiler, N_STRING_CONTINUE); node->left = result; node->middle = (void *)lexer_token(compiler)->start; lexer_next(compiler); node->right = parse_statements(compiler); result = node; } if(lexer_require(compiler, T_STRING_END)) { struct node *node = alloc_node(compiler, N_STRING_START); node->left = result; node->right = (void *)lexer_token(compiler)->start; lexer_next(compiler); return node; } return result; } case T_SELF: { lexer_next(compiler); return &self_node; } case T_TRUE: { lexer_next(compiler); return alloc_node(compiler, N_TRUE); } case T_FALSE: { lexer_next(compiler); return alloc_node(compiler, N_FALSE); } case T_NIL: { lexer_next(compiler); return &nil_node; } case T_NUMBER: { struct node *result = alloc_node(compiler, N_NUMBER); char *text = get_token_str(lexer_token(compiler)); result->left = (void* )atoi(text); lexer_next(compiler); return result; } case T_IVAR: { rt_value symbol = rt_symbol_from_lexer(compiler); lexer_next(compiler); switch (lexer_current(compiler)) { case T_ASSIGN_ADD: case T_ASSIGN_SUB: case T_ASSIGN_MUL: case T_ASSIGN_DIV: { struct node *result; enum token_type op_type = lexer_current(compiler) - OP_TO_ASSIGN; lexer_next(compiler); result = alloc_node(compiler, N_IVAR_ASSIGN); result->right = alloc_node(compiler, N_BINARY_OP); result->right->op = op_type; result->right->left = alloc_node(compiler, N_IVAR); result->right->left->left = (void *)symbol; result->right->right = parse_expression(compiler); result->left = (void *)symbol; return result; } case T_ASSIGN: { struct node *result; lexer_next(compiler); result = alloc_node(compiler, N_IVAR_ASSIGN); result->left = (void *)symbol; result->right = parse_expression(compiler); return result; } default: { struct node *result = alloc_node(compiler, N_IVAR); result->left = (void *)symbol; return result; } } } case T_IDENT: return parse_identifier(compiler); case T_EXT_IDENT: return parse_call(compiler, 0, &self_node, false); case T_PARAM_OPEN: { lexer_next(compiler); struct node *result = parse_statements(compiler); lexer_match(compiler, T_PARAM_CLOSE); return result; } default: { COMPILER_ERROR(compiler, "Expected expression but found %s", token_type_names[lexer_current(compiler)]); lexer_next(compiler); return 0; } } }
bool Parser::parse_statement(StatementList *list) { lexer.identify_keywords(); switch(lexeme()) { case Lexeme::KW_IF: parse_if(list); break; case Lexeme::KW_WHILE: parse_while(list); break; case Lexeme::KW_DO: parse_do(list); parse_terminator(); break; case Lexeme::KW_RETURN: parse_return(list); parse_terminator(); break; case Lexeme::KW_BREAK: parse_break(list); parse_terminator(); break; case Lexeme::KW_CONTINUE: parse_continue(list); parse_terminator(); break; case Lexeme::KW_CONST: step(); parse_local(true, parse_expression(), list); parse_terminator(); break; case Lexeme::BRACET_OPEN: list->append(parse_block<true, false>(Scope::EMPTY)); break; case Lexeme::SEMICOLON: step(); break; case Lexeme::END: case Lexeme::BRACET_CLOSE: return false; default: if(is_expression(lexeme())) { ExpressionNode *node = parse_expression(); if(lexeme() == Lexeme::IDENT && node->is_type_name(document, false)) parse_local(false, node, list); else list->append(node); parse_terminator(); } else return false; } return true; }