static bool is_statement(void) { PATTERN last; int count; count = tree_length; if (count == 0) return FALSE; count--; last = tree[count]; while (PATTERN_is_param(last) && (count > 0)) { count--; last = tree[count]; } if (PATTERN_is(last, RS_PT)) goto _ADD_BRACE; if (PATTERN_is_identifier(last)) { if (count == 0) goto _ADD_BRACE; if (count >= 2) { last = tree[count - 1]; if (PATTERN_is_param(last) && (PATTERN_index(last) == 0) && PATTERN_is(tree[count - 2], RS_PT)) goto _ADD_BRACE; } } else if (PATTERN_is_subr(last) || PATTERN_is(last, RS_LBRA) || PATTERN_is(last, RS_RBRA) || PATTERN_is(last, RS_AT) || PATTERN_is(last, RS_COMMA)) return TRUE; #ifdef DEBUG printf("Last = "); READ_dump_pattern(&last); printf("%08X %08X %d\n", last, PATTERN_make(RT_RESERVED, RS_LBRA), PATTERN_is(last, RS_LBRA)); #endif return FALSE; _ADD_BRACE: add_operator(RS_LBRA, 0); #ifdef DEBUG printf("Add ()\n"); #endif return TRUE; }
void read_token(t_env *env, char *str, int *i) { while (str[*i] == ' ' || str[*i] == '\t') (*i)++; if (is_number(str[*i])) add_to_queue(env, read_number(str, i)); else if (is_operator(str[*i])) add_operator(env, str, i); else add_paranthesis(env, str, i); }
static void analyze_array() { int i; check_last_first(1); for(i = 0; i < MAX_ARRAY_DIM; i++) { analyze_expr(0, RS_NONE); if (!PATTERN_is(*current, RS_COMMA)) break; current++; } if (!PATTERN_is(*current, RS_RSQR)) THROW(E_MISSING, "',' or ')'"); current++; add_operator(RS_LSQR, i + 2); }
static ParserState state_redirections(ParserContext *ctx, char *token) { switch (token_class(token)) { case TC_REDIRECT: ctx->redirect_type = token; return ST_REDIRECT_FILENAME; case TC_OPERATOR: add_operator(ctx, token); return ST_COMMAND; case TC_SUBSHELL_END: if (close_subshell(ctx)) return ST_REDIRECTIONS; else return ST_ERROR; default: return ST_ERROR; } }
static void analyze_expr(short priority, short op_main) { short op, op_curr, op_not; short prio; short nparam; inc_level(); op_curr = op_main; op_not = RS_NONE; nparam = (op_main == RS_NONE || op_main == RS_UNARY) ? 0 : 1; if (PATTERN_is(*current, RS_NEW)) THROW("Cannot use NEW operator there"); READ_OPERAND: //analyze_expr_check_first(op_curr); analyze_single(op_curr); nparam++; if (nparam > MAX_PARAM_OP) THROW("Expression too complex. Too many operands"); READ_OPERATOR: if (!PATTERN_is_reserved(*current)) goto OPERATOR_END; op = PATTERN_index(*current); if (!RES_is_operator(op)) goto OPERATOR_END; if (op == RS_AND || op == RS_OR) if (PATTERN_is(current[1], RS_IF)) goto OPERATOR_END; current++; if (op == RS_NOT && PATTERN_is_reserved(*current)) { op_not = PATTERN_index(*current); if (RES_is_operator(op_not) && RES_can_have_not_before(op_not)) { op = op_not + 1; current++; } } if (priority) prio = priority; else if (op_curr == RS_NONE) prio = 0; else prio = RES_priority(op_curr); if (op_curr == RS_NONE) { if (RES_is_binary(op) || RES_is_n_ary(op)) { op_curr = op; goto READ_OPERAND; } } if (op_curr == op) { if (!(RES_is_binary(op) && nparam == 2)) goto READ_OPERAND; } if (RES_priority(op) > prio) { if (op == RS_LSQR) analyze_array(); else if (op == RS_LBRA) analyze_call(); else analyze_expr(RES_priority(op), op); goto READ_OPERATOR; } if (RES_priority(op) == prio) { add_operator(op_curr, nparam); if (op == RS_LSQR) { analyze_array(); goto READ_OPERATOR; } else if (op == RS_LBRA) { analyze_call(); goto READ_OPERATOR; } else { if (RES_is_only(op_curr) || RES_is_only(op)) THROW("Ambiguous expression. Please use brackets"); nparam = 1; op_curr = op; goto READ_OPERAND; } } if (RES_priority(op) < prio) { if ((op_main != RS_NONE) || (priority > 0)) { add_operator(op_curr, nparam); current--; if (op_not != RS_NONE) current--; goto END; } add_operator(op_curr, nparam); if (op == RS_LSQR) { analyze_array(); nparam = 1; op_curr = op_main; goto READ_OPERATOR; } else if (op == RS_LBRA) { analyze_call(); nparam = 1; op_curr = op_main; goto READ_OPERATOR; } else { nparam = 1; op_curr = op; goto READ_OPERAND; } } dec_level(); return; OPERATOR_END: add_operator(op_curr, nparam); END: dec_level(); return; }
static void analyze_single(int op) { PATTERN *pattern; bool jump_newline; jump_newline = PATTERN_is_newline(*current); if (jump_newline) { add_pattern(PATTERN_make(RT_NEWLINE, 0)); JOB->line++; current++; } if (op == RS_PT && !PATTERN_is_identifier(*current)) THROW("The '.' operator must be followed by an identifier"); else if (op == RS_EXCL && !PATTERN_is_string(*current)) THROW("The '!' operator must be followed by an identifier"); /* ( expr ) */ if (PATTERN_is(*current, RS_LBRA)) { int old_length = tree_length; PATTERN last; current++; analyze_expr(0, RS_NONE); if (!PATTERN_is(*current, RS_RBRA)) THROW(E_MISSING, "')'"); current++; if (tree_length == (old_length + 1)) { last = get_last_pattern(1); if (PATTERN_is_string(last)) change_last_pattern(1, PATTERN_make(RT_TSTRING, PATTERN_index(last))); } } /* [ expr, expr, ... ] */ else if (PATTERN_is(*current, RS_LSQR)) { current++; analyze_make_array(); } /* - expr | NOT expr */ else if (PATTERN_is(*current, RS_MINUS) || PATTERN_is(*current, RS_NOT)) { pattern = current; current++; analyze_expr(RES_priority(RS_NOT), RS_UNARY); add_operator(PATTERN_index(*pattern), 1); } // . symbol else if (PATTERN_is(*current, RS_PT) && PATTERN_is_identifier(current[1])) { add_operator(PATTERN_index(current[0]), 0); add_pattern(PATTERN_set_flag(current[1], RT_POINT)); current += 2; } // . [ ... ] else if (PATTERN_is(*current, RS_PT) && PATTERN_is(current[1], RS_LSQR)) { add_operator(PATTERN_index(current[0]), 0); //add_pattern(PATTERN_set_flag(RS_RSQR, RT_POINT)); current += 2; analyze_array(); } // ! symbol else if (PATTERN_is(*current, RS_EXCL) && PATTERN_is_string(current[1])) { add_operator(RS_PT, 0); add_pattern(PATTERN_set_flag(current[1], RT_POINT)); add_operator(RS_EXCL, 0); current += 2; } /* NULL, TRUE, FALSE, ME, PARENT, LAST, ERROR */ /* number, string or symbol */ else if (PATTERN_is(*current, RS_NULL) || PATTERN_is(*current, RS_ME) || PATTERN_is(*current, RS_LAST) || PATTERN_is(*current, RS_TRUE) || PATTERN_is(*current, RS_FALSE) || PATTERN_is(*current, RS_PINF) || PATTERN_is(*current, RS_MINF) || PATTERN_is(*current, RS_ERROR) || (!PATTERN_is_reserved(*current) && !PATTERN_is_newline(*current) && !PATTERN_is_end(*current))) { add_pattern(*current); if (PATTERN_is_identifier(*current)) { /*if ((op == RS_NONE || op == RS_UNARY) && (PATTERN_is_identifier(*current))) change_last_pattern(1, PATTERN_set_flag(get_last_pattern(1), RT_FIRST));*/ if (op == RS_PT) { change_last_pattern(1, PATTERN_set_flag(get_last_pattern(1), RT_POINT)); check_last_first(2); } } current++; } else if (PATTERN_is(*current, RS_SUPER)) { add_pattern(*current); current++; if (!PATTERN_is(*current, RS_PT) && !PATTERN_is(*current, RS_EXCL) && !PATTERN_is(*current, RS_LBRA) && !PATTERN_is(*current, RS_LSQR)) THROW("SUPER cannot be used alone"); } else { if (jump_newline) { current--; JOB->line--; } THROW_UNEXPECTED(current); } }
static void analyze_make_array() { int n = 0; bool checked = FALSE; bool collection = FALSE; /*if (PATTERN_is(*current, RS_RSQR)) { current++; add_pattern(PATTERN_make(RT_RESERVED, RS_NULL)); return; }*/ if (!PATTERN_is(*current, RS_RSQR)) { for(;;) { n++; /*if (n > MAX_PARAM_OP) THROW("Too many arguments");*/ analyze_expr(0, RS_NONE); if (!checked) { collection = PATTERN_is(*current, RS_COLON); checked = TRUE; } if (collection) { if (!PATTERN_is(*current, RS_COLON)) THROW(E_MISSING, "':'"); current++; n++; /*if (n > MAX_PARAM_OP) THROW("Too many arguments");*/ analyze_expr(0, RS_NONE); } if (!PATTERN_is(*current, RS_COMMA)) break; current++; if (collection) { if (n == (MAX_PARAM_OP - 1)) { add_operator(RS_COLON, MAX_PARAM_OP + 1); n = 0; } } else { if (n == MAX_PARAM_OP) { add_operator(RS_RSQR, MAX_PARAM_OP + 1); n = 0; } } } } if (!PATTERN_is(*current, RS_RSQR)) THROW(E_MISSING, "']'"); current++; add_operator(collection ? RS_COLON : RS_RSQR, n); }
/* evaluate: * Top level evaluation function. */ double evaluate(char *equation, int *error, double (*variable)(char *name)) { char buf[256]; double val; int i; stack_depth = 0; current_val = 0; current_valid = FALSE; evaluate_error = FALSE; while ((*equation) && (!evaluate_error)) { /* skip whitespace */ while (isspace(*equation)) equation++; switch (*equation) { case '+': /* addition */ add_operator(OP_PLUS); equation++; break; case '-': /* subtraction */ add_operator(OP_MINUS); equation++; break; case '*': /* multiplication */ add_operator(OP_MUL); equation++; break; case '/': /* division */ add_operator(OP_DIV); equation++; break; case '^': /* rasing to a power (_not_ XOR!) */ add_operator(OP_POWER); equation++; break; case '%': /* modulus */ add_operator(OP_MOD); equation++; break; case '|': /* logical or */ add_operator(OP_OR); equation++; break; case '&': /* logical and */ add_operator(OP_AND); equation++; break; case '=': /* equality test (requires dual ==) */ if (equation[1] == '=') { add_operator(OP_EQUALS); equation += 2; } else evaluate_error = TRUE; break; case '!': /* could be inequality test or logical not */ if (equation[1] == '=') { add_operator(OP_NOT_EQUALS); equation += 2; } else { add_operator(OP_NOT); equation++; } break; case '<': /* could be less than or less/equal test */ if (equation[1] == '=') { add_operator(OP_LESS_EQUALS); equation += 2; } else { add_operator(OP_LESS); equation++; } break; case '>': /* could be greater than or greater/equal test */ if (equation[1] == '=') { add_operator(OP_GREATER_EQUALS); equation += 2; } else { add_operator(OP_GREATER); equation++; } break; case '(': /* open bracket */ add_operator(OP_OPEN_PAREN); equation++; break; case ')': /* close bracket */ add_operator(OP_CLOSE_PAREN); equation++; break; case '0': /* special case for hex constants (0x prefix) */ if (equation[1] == 'x') { equation += 2; for (i=0; isxdigit(equation[i]); i++) buf[i] = equation[i]; buf[i] = 0; equation += i; val = strtol(buf, NULL, 16); add_value(val); break; } /* else fall through */ case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* floating point constant */ for (i=0; isdigit(equation[i]) || (equation[i] == '.'); i++) buf[i] = equation[i]; buf[i] = 0; equation += i; val = atof(buf); add_value(val); break; default: /* this is a string, could be a variable or function */ for (i=0; (isalpha(equation[i])) || (equation[i] == '_'); i++) buf[i] = tolower(equation[i]); buf[i] = 0; equation += i; if (strcmp(buf, "pi") == 0) { /* pi (built in constant) */ add_value(M_PI); } else if (strcmp(buf, "e") == 0) { /* e (built in constant) */ add_value(M_E); } else if (strcmp(buf, "sqrt") == 0) { /* square root function */ add_operator(OP_SQRT); } else if (strcmp(buf, "sin") == 0) { /* sin function */ add_operator(OP_SIN); } else if (strcmp(buf, "cos") == 0) { /* cos function */ add_operator(OP_COS); } else if (strcmp(buf, "tan") == 0) { /* tan function */ add_operator(OP_TAN); } else if (strcmp(buf, "asin") == 0) { /* inverse sin function */ add_operator(OP_ASIN); } else if (strcmp(buf, "acos") == 0) { /* inverse cos function */ add_operator(OP_ACOS); } else if (strcmp(buf, "atan") == 0) { /* inverse tan function */ add_operator(OP_ATAN); } else if (strcmp(buf, "log") == 0) { /* base 10 logarithm function */ add_operator(OP_LOG); } else if (strcmp(buf, "ln") == 0) { /* natural logarithm function */ add_operator(OP_LN); } else if (strcmp(buf, "ceil") == 0) { /* round upwards function */ add_operator(OP_CEIL); } else if (strcmp(buf, "floor") == 0) { /* round downwards function */ add_operator(OP_FLOOR); } else if (strcmp(buf, "round") == 0) { /* round to nearest integer function */ add_operator(OP_ROUND); } else if (strcmp(buf, "abs") == 0) { /* absolute value function */ add_operator(OP_ABS); } else if (strcmp(buf, "rand") == 0) { /* random number between 0 and 1 */ add_value((rand()&32767)/32767.0); } else { /* user-supplied callback for looking up variables */ if ((buf[0]) && (variable)) { add_value(variable(buf)); } else { if (error) *error = TRUE; return 0; } } break; } } if ((evaluate_error) || (!current_valid)) { if (error) *error = TRUE; return 0; } /* force a stack flush */ add_operator(OP_TERMINATOR); if (stack_depth != 1) { if (error) *error = TRUE; return 0; } if (error) *error = FALSE; return value_stack[0]; }
int ged_comb_std(struct ged *gedp, int argc, const char *argv[]) { char *comb_name; int ch; int region_flag = -1; struct directory *dp = RT_DIR_NULL; struct rt_db_internal intern; struct rt_comb_internal *comb = NULL; struct tokens tok_hd; short last_tok; int i; union tree *final_tree; static const char *usage = "[-cr] comb_name <boolean_expr>"; GED_CHECK_DATABASE_OPEN(gedp, GED_ERROR); GED_CHECK_READ_ONLY(gedp, GED_ERROR); GED_CHECK_ARGC_GT_0(gedp, argc, GED_ERROR); /* initialize result */ bu_vls_trunc(gedp->ged_result_str, 0); /* must be wanting help */ if (argc == 1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_HELP; } if (argc < 3) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_ERROR; } /* Parse options */ bu_optind = 1; /* re-init bu_getopt() */ while ((ch = bu_getopt(argc, (char * const *)argv, "cgr?")) != -1) { switch (ch) { case 'c': case 'g': region_flag = 0; break; case 'r': region_flag = 1; break; /* XXX How about -p and -v for FASTGEN? */ case '?': default: bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_OK; } } argc -= (bu_optind + 1); argv += bu_optind; comb_name = (char *)*argv++; if (argc == -1) { bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage); return GED_OK; } if ((region_flag != -1) && (argc == 0)) { /* * Set/Reset the REGION flag of an existing combination */ GED_DB_LOOKUP(gedp, dp, comb_name, LOOKUP_NOISY, GED_ERROR & GED_QUIET); if (!(dp->d_flags & RT_DIR_COMB)) { bu_vls_printf(gedp->ged_result_str, "%s is not a combination\n", comb_name); return GED_ERROR; } GED_DB_GET_INTERNAL(gedp, &intern, dp, (fastf_t *)NULL, &rt_uniresource, GED_ERROR); comb = (struct rt_comb_internal *)intern.idb_ptr; RT_CK_COMB(comb); if (region_flag) { if (!comb->region_flag) { /* assign values from the defaults */ comb->region_id = gedp->ged_wdbp->wdb_item_default++; comb->aircode = gedp->ged_wdbp->wdb_air_default; comb->GIFTmater = gedp->ged_wdbp->wdb_mat_default; comb->los = gedp->ged_wdbp->wdb_los_default; } comb->region_flag = 1; } else comb->region_flag = 0; GED_DB_PUT_INTERNAL(gedp, dp, &intern, &rt_uniresource, GED_ERROR); return GED_OK; } /* * At this point, we know we have a Boolean expression. * If the combination already existed and region_flag is -1, * then leave its region_flag alone. * If the combination didn't exist yet, * then pretend region_flag was 0. * Otherwise, make sure to set its c_flags according to region_flag. */ GED_CHECK_EXISTS(gedp, comb_name, LOOKUP_QUIET, GED_ERROR); dp = RT_DIR_NULL; /* parse Boolean expression */ BU_LIST_INIT(&tok_hd.l); tok_hd.type = TOK_NULL; last_tok = TOK_LPAREN; for (i = 0; i < argc; i++) { char *ptr; ptr = (char *)argv[i]; while (*ptr) { while (*ptr == '(' || *ptr == ')') { switch (*ptr) { case '(': append_lparen(&tok_hd.l); last_tok = TOK_LPAREN; break; case ')': append_rparen(&tok_hd.l); last_tok = TOK_RPAREN; break; } ptr++; } if (*ptr == '\0') continue; if (last_tok == TOK_RPAREN) { /* next token MUST be an operator */ if (add_operator(gedp, &tok_hd.l, *ptr, &last_tok) == GED_ERROR) { free_tokens(&tok_hd.l); return GED_ERROR; } ptr++; } else if (last_tok == TOK_LPAREN) { /* next token MUST be an operand */ int name_len; name_len = add_operand(gedp, &tok_hd.l, ptr); if (name_len < 1) { free_tokens(&tok_hd.l); return GED_ERROR; } last_tok = TOK_TREE; ptr += name_len; } else if (last_tok == TOK_TREE) { /* must be an operator */ if (add_operator(gedp, &tok_hd.l, *ptr, &last_tok) == GED_ERROR) { free_tokens(&tok_hd.l); return GED_ERROR; } ptr++; } else if (last_tok == TOK_UNION || last_tok == TOK_INTER || last_tok == TOK_SUBTR) { /* must be an operand */ int name_len; name_len = add_operand(gedp, &tok_hd.l, ptr); if (name_len < 1) { free_tokens(&tok_hd.l); return GED_ERROR; } last_tok = TOK_TREE; ptr += name_len; } } } if (check_syntax(gedp, &tok_hd.l, comb_name, dp)) { free_tokens(&tok_hd.l); return GED_ERROR; } final_tree = eval_bool(&tok_hd.l); { int flags; flags = RT_DIR_COMB; BU_ALLOC(comb, struct rt_comb_internal); RT_COMB_INTERNAL_INIT(comb); comb->tree = final_tree; comb->region_id = -1; if (region_flag == (-1)) comb->region_flag = 0; else comb->region_flag = region_flag; if (comb->region_flag) { comb->region_flag = 1; comb->region_id = gedp->ged_wdbp->wdb_item_default++; comb->aircode = gedp->ged_wdbp->wdb_air_default; comb->los = gedp->ged_wdbp->wdb_los_default; comb->GIFTmater = gedp->ged_wdbp->wdb_mat_default; bu_vls_printf(gedp->ged_result_str, "Creating region with attrs: region_id=%d, ", comb->region_id); if (comb->aircode) bu_vls_printf(gedp->ged_result_str, "air=%d, ", comb->aircode); bu_vls_printf(gedp->ged_result_str, "los=%d, material_id=%d\n", comb->los, comb->GIFTmater); flags |= RT_DIR_REGION; } RT_DB_INTERNAL_INIT(&intern); intern.idb_major_type = DB5_MAJORTYPE_BRLCAD; intern.idb_type = ID_COMBINATION; intern.idb_meth = &OBJ[ID_COMBINATION]; intern.idb_ptr = (void *)comb; GED_DB_DIRADD(gedp, dp, comb_name, RT_DIR_PHONY_ADDR, 0, flags, (void *)&intern.idb_type, GED_ERROR); GED_DB_PUT_INTERNAL(gedp, dp, &intern, &rt_uniresource, GED_ERROR); } return GED_OK; }
// 私有读取下一个词语的方法 Token TokenAnalyze::_next_token() { if(!filein) // 输入流打开错误 { return Token("",token_type::ENDOFFILE,line_number); } char ch; // 首先过滤空白符 while(filein.get(ch) && is_space(ch)) if(ch == '\n') line_number ++ ; if(is_letter(ch)) { return identifier(ch); } else if(is_digit(ch)) { return number(ch); } else { switch(ch) { case '\'': return char_con(ch);break; case '"': return string_con(ch);break; case '+': case '-': return add_operator(ch);break; case '*': case '/': return multiply_operator(ch);break; case '=': return assign_equal_operator(ch);break; case '<': case '>': case '!': return relation_operator(ch);break; case ';': return is_semicn(ch);break; case ',': return is_comma(ch);break; case '(': return left_parent(ch);break; case ')': return right_parent(ch);break; case '[': return left_brack(ch);break; case ']': return right_brack(ch);break; case '{': return left_brace(ch);break; case '}': return right_brace(ch);break; default: return Token(""+ch,token_type::UNKNOWN,line_number); } } }