/* parse_statement Checks the current token to be able to parse the correct statement Parameters: none Return: none */ void parse_statement(Tree &cst){ cst.add_branch_node("statement"); if(!(curr_token -> desc).compare("print")){ parse_print(cst); } else if(!(curr_token -> type).compare("identifier")){ parse_assingment(cst); } else if(types.find(curr_token -> desc) != types.end()){ parse_var_decl(cst); } else if(!(curr_token -> desc).compare("while")){ parse_while(cst); } else if(!(curr_token -> desc).compare("if")){ parse_if(cst); } else if(!(curr_token -> type).compare("open_block")){ parse_block(cst); } else{ std::cout << "Parse Error on line " << curr_token -> line_number << ".\nExpected statement, found " << curr_token -> desc << "\nStatements begin with:\n\tprint\n\tidentifier -- [a-z]\n\t" << "int, string, boolean\n\twhile\n\tif\n\t{" << "\n\nCompilation unsuccessful" << std::endl; exit(EXIT_FAILURE); } cst.kill_all_children(); }
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; }
/** слово: список в скобках {} подстановка выражения в скобках [] */ int parse_word(char *text,char **endptr,Tag *toptag) { char *p,*s; Tag *tag; tag=NULL; s=text; if (s==NULL || isblank(*s)||strchr(EXPTERM,*s)) return 1; if (toptag) tag=mark(WORD,text,text,toptag); while(*s) { p=s; switch(*s) { case '{' : parse_list(s,&s,tag);break; case '[' : parse_command(s,&s,tag);break; case '\'': parse_string(s,&s,tag);break; case '\"': parse_subst(s,&s,tag);break; case '$' : parse_variable(s,&s,tag);break; default: if (s[0]=='#' && s[1]!='#' && s[1]!='!') { parse_macro(s,&s,tag); } else if (s[0]=='#' && s[1]=='?' && s[2]=='>') { parse_print(s,&s,tag); } else if ((s[0]=='-' && isdigit(s[1])) || isdigit(*s)) parse_numeric(s,&s,tag); else mark_cspn(CHARS,BLANK EXPTERM "(",s,&s,tag); } if (strchr(BLANK EXPTERM,*s)) break; if (p==s) break; } if (endptr) *endptr=s; return 0; }
/** разобрать "выражение" выражение: последовательность слов разделённых пробелами **/ int parse_expression(char *text,char **endptr,Tag *toptag) { char *s,*p; Tag *tag; int comma; TRACE(""); if (!text) return 0; s=text; tag=NULL; comma=1; if (toptag) tag=mark(EXPR,text,text,toptag); while(*s) { p=s; mark_ctype(NULL,isblank,s,&s,tag); if (s[0]==',') { /* слова в выражении разделены , */ if (comma) { mark(NIL,s,s,tag); } mark_len(NULL,1,s,&s,tag); // отметить , mark_ctype(NULL,isspace,s,&s,tag); // после , разрешён \n comma=1; continue; } else { comma=0; } if (s[0]=='#' && s[1]=='!') parse_comment(s,&s,tag); if (s[0]=='#' && s[1]=='?' && s[2]=='>') parse_print(s,&s,tag); if (strchr(EXPTERM,*s)) break; if ('('==*s) { parse_tuple(s,&s,tag); } else parse_word(s,&s,tag); if (p==s) break; } if (comma) { mark(NIL,s,s,tag); s++; } if (endptr) *endptr=s; return 0; }
struct predicate* build_expression_tree (int argc, char *argv[], int end_of_leading_options) { const struct parser_table *parse_entry; /* Pointer to the parsing table entry for this expression. */ char *predicate_name; /* Name of predicate being parsed. */ struct predicate *cur_pred; const struct parser_table *entry_close, *entry_print, *entry_open; int i, oldi; predicates = NULL; /* Find where in ARGV the predicates begin by skipping the list of * start points. As a side effect, also figure out which is the * first and last start point. */ start_points = argv + end_of_leading_options; for (i = end_of_leading_options; i < argc && !looks_like_expression(argv[i], true); i++) { ++num_start_points; } /* Enclose the expression in `( ... )' so a default -print will apply to the whole expression. */ entry_open = find_parser ("("); entry_close = find_parser (")"); entry_print = find_parser ("print"); assert (entry_open != NULL); assert (entry_close != NULL); assert (entry_print != NULL); parse_openparen (entry_open, argv, &argc); last_pred->p_name = "("; predicates->artificial = true; parse_begin_user_args (argv, argc, last_pred, predicates); pred_sanity_check (last_pred); /* Build the input order list. */ while (i < argc ) { state.already_issued_stat_error_msg = false; if (!looks_like_expression (argv[i], false)) { error (0, 0, _("paths must precede expression: %s"), argv[i]); usage (stderr, 1, NULL); } predicate_name = argv[i]; parse_entry = find_parser (predicate_name); if (parse_entry == NULL) { /* Command line option not recognized */ error (EXIT_FAILURE, 0, _("unknown predicate `%s'"), predicate_name); } /* We have recognised a test of the form -foo. Eat that, * unless it is a predicate like -newerXY. */ if (parse_entry->type != ARG_SPECIAL_PARSE) { i++; } oldi = i; if (!(*(parse_entry->parser_func)) (parse_entry, argv, &i)) { if (argv[i]) { if ( (ARG_SPECIAL_PARSE == parse_entry->type) && (i == oldi) ) { /* The special parse function spat out the * predicate. It must be invalid, or not tasty. */ error (EXIT_FAILURE, 0, _("invalid predicate `%s'"), predicate_name); } else { error (EXIT_FAILURE, 0, _("invalid argument `%s' to `%s'"), argv[i], predicate_name); } } else { /* Command line option requires an argument */ error (EXIT_FAILURE, 0, _("missing argument to `%s'"), predicate_name); } } else { last_pred->p_name = predicate_name; /* If the parser consumed an argument, save it. */ if (i != oldi) last_pred->arg_text = argv[oldi]; else last_pred->arg_text = NULL; } pred_sanity_check(last_pred); pred_sanity_check(predicates); /* XXX: expensive */ } parse_end_user_args (argv, argc, last_pred, predicates); if (predicates->pred_next == NULL) { /* No predicates that do something other than set a global variable were given; remove the unneeded initial `(' and add `-print'. */ cur_pred = predicates; predicates = last_pred = predicates->pred_next; free (cur_pred); parse_print (entry_print, argv, &argc); last_pred->p_name = "-print"; pred_sanity_check(last_pred); pred_sanity_check(predicates); /* XXX: expensive */ } else if (!default_prints (predicates->pred_next)) { /* One or more predicates that produce output were given; remove the unneeded initial `('. */ cur_pred = predicates; predicates = predicates->pred_next; pred_sanity_check (predicates); /* XXX: expensive */ free (cur_pred); } else { /* `( user-supplied-expression ) -print'. */ parse_closeparen (entry_close, argv, &argc); last_pred->p_name = ")"; last_pred->artificial = true; pred_sanity_check (last_pred); parse_print (entry_print, argv, &argc); last_pred->p_name = "-print"; last_pred->artificial = true; pred_sanity_check (last_pred); pred_sanity_check (predicates); /* XXX: expensive */ } if (options.debug_options & (DebugExpressionTree|DebugTreeOpt)) { fprintf (stderr, "Predicate List:\n"); print_list (stderr, predicates); } /* do a sanity check */ check_option_combinations (predicates); pred_sanity_check (predicates); /* Done parsing the predicates. Build the evaluation tree. */ cur_pred = predicates; eval_tree = get_expr (&cur_pred, NO_PREC, NULL); calculate_derived_rates (eval_tree); /* Check if we have any left-over predicates (this fixes * Debian bug #185202). */ if (cur_pred != NULL) { /* cur_pred->p_name is often NULL here */ if (pred_is (cur_pred, pred_closeparen)) { /* e.g. "find \( -true \) \)" */ error (EXIT_FAILURE, 0, _("you have too many ')'")); } else { if (cur_pred->p_name) error (EXIT_FAILURE, 0, _("unexpected extra predicate '%s'"), cur_pred->p_name); else error (EXIT_FAILURE, 0, _("unexpected extra predicate")); } } if (options.debug_options & (DebugExpressionTree|DebugTreeOpt)) { fprintf (stderr, "Eval Tree:\n"); print_tree (stderr, eval_tree, 0); } estimate_costs (eval_tree); /* Rearrange the eval tree in optimal-predicate order. */ opt_expr (&eval_tree); /* Check that the tree is in normalised order (opt_expr does this) */ check_normalization (eval_tree, true); do_arm_swaps (eval_tree); /* Check that the tree is still in normalised order */ check_normalization (eval_tree, true); if (options.debug_options & (DebugExpressionTree|DebugTreeOpt)) { fprintf (stderr, "Optimized Eval Tree:\n"); print_tree (stderr, eval_tree, 0); fprintf (stderr, "Optimized command line:\n"); print_optlist (stderr, eval_tree); fprintf (stderr, "\n"); } return eval_tree; }
/* * 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; }