📄 pic.y
字号:
} ;object_type: BOX { $$ = BOX_OBJECT; } | CIRCLE { $$ = CIRCLE_OBJECT; } | ELLIPSE { $$ = ELLIPSE_OBJECT; } | ARC { $$ = ARC_OBJECT; } | LINE { $$ = LINE_OBJECT; } | ARROW { $$ = ARROW_OBJECT; } | SPLINE { $$ = SPLINE_OBJECT; } | '[' ']' { $$ = BLOCK_OBJECT; } | TEXT { $$ = TEXT_OBJECT; } ;label_path: '.' LABEL { $$ = new path($2); } | label_path '.' LABEL { $$ = $1; $$->append($3); } ;relative_path: corner { $$ = new path($1); } /* give this a lower precedence than LEFT and RIGHT so that [A: box] with .A left == [A: box] with (.A left) */ | label_path %prec TEXT { $$ = $1; } | label_path corner { $$ = $1; $$->append($2); } ;path: relative_path { $$ = $1; } /* The rest of these rules are a compatibility sop. */ | ORDINAL LAST object_type relative_path { lex_warning("`%1%2 last %3' in `with' argument ignored", $1, ordinal_postfix($1), object_type_name($3)); $$ = $4; } | LAST object_type relative_path { lex_warning("`last %1' in `with' argument ignored", object_type_name($2)); $$ = $3; } | ORDINAL object_type relative_path { lex_warning("`%1%2 %3' in `with' argument ignored", $1, ordinal_postfix($1), object_type_name($2)); $$ = $3; } | LABEL relative_path { lex_warning("initial `%1' in `with' argument ignored", $1); a_delete $1; $$ = $2; } ;corner: DOT_N { $$ = &object::north; } | DOT_E { $$ = &object::east; } | DOT_W { $$ = &object::west; } | DOT_S { $$ = &object::south; } | DOT_NE { $$ = &object::north_east; } | DOT_SE { $$ = &object:: south_east; } | DOT_NW { $$ = &object::north_west; } | DOT_SW { $$ = &object::south_west; } | DOT_C { $$ = &object::center; } | DOT_START { $$ = &object::start; } | DOT_END { $$ = &object::end; } | TOP { $$ = &object::north; } | BOTTOM { $$ = &object::south; } | LEFT { $$ = &object::west; } | RIGHT { $$ = &object::east; } | UPPER LEFT { $$ = &object::north_west; } | LOWER LEFT { $$ = &object::south_west; } | UPPER RIGHT { $$ = &object::north_east; } | LOWER RIGHT { $$ = &object::south_east; } | LEFT_CORNER { $$ = &object::west; } | RIGHT_CORNER { $$ = &object::east; } | UPPER LEFT_CORNER { $$ = &object::north_west; } | LOWER LEFT_CORNER { $$ = &object::south_west; } | UPPER RIGHT_CORNER { $$ = &object::north_east; } | LOWER RIGHT_CORNER { $$ = &object::south_east; } | CENTER { $$ = &object::center; } | START { $$ = &object::start; } | END { $$ = &object::end; } ;expr: VARIABLE { if (!lookup_variable($1, & $$)) { lex_error("there is no variable `%1'", $1); YYABORT; } a_delete $1; } | NUMBER { $$ = $1; } | place DOT_X { if ($1.obj != 0) $$ = $1.obj->origin().x; else $$ = $1.x; } | place DOT_Y { if ($1.obj != 0) $$ = $1.obj->origin().y; else $$ = $1.y; } | place DOT_HT { if ($1.obj != 0) $$ = $1.obj->height(); else $$ = 0.0; } | place DOT_WID { if ($1.obj != 0) $$ = $1.obj->width(); else $$ = 0.0; } | place DOT_RAD { if ($1.obj != 0) $$ = $1.obj->radius(); else $$ = 0.0; } | expr '+' expr { $$ = $1 + $3; } | expr '-' expr { $$ = $1 - $3; } | expr '*' expr { $$ = $1 * $3; } | expr '/' expr { if ($3 == 0.0) { lex_error("division by zero"); YYABORT; } $$ = $1/$3; } | expr '%' expr { if ($3 == 0.0) { lex_error("modulus by zero"); YYABORT; } $$ = fmod($1, $3); } | expr '^' expr { errno = 0; $$ = pow($1, $3); if (errno == EDOM) { lex_error("arguments to `^' operator out of domain"); YYABORT; } if (errno == ERANGE) { lex_error("result of `^' operator out of range"); YYABORT; } } | '-' expr %prec '!' { $$ = -$2; } | '(' any_expr ')' { $$ = $2; } | SIN '(' any_expr ')' { errno = 0; $$ = sin($3); if (errno == ERANGE) { lex_error("sin result out of range"); YYABORT; } } | COS '(' any_expr ')' { errno = 0; $$ = cos($3); if (errno == ERANGE) { lex_error("cos result out of range"); YYABORT; } } | ATAN2 '(' any_expr ',' any_expr ')' { errno = 0; $$ = atan2($3, $5); if (errno == EDOM) { lex_error("atan2 argument out of domain"); YYABORT; } if (errno == ERANGE) { lex_error("atan2 result out of range"); YYABORT; } } | LOG '(' any_expr ')' { errno = 0; $$ = log10($3); if (errno == ERANGE) { lex_error("log result out of range"); YYABORT; } } | EXP '(' any_expr ')' { errno = 0; $$ = pow(10.0, $3); if (errno == ERANGE) { lex_error("exp result out of range"); YYABORT; } } | SQRT '(' any_expr ')' { errno = 0; $$ = sqrt($3); if (errno == EDOM) { lex_error("sqrt argument out of domain"); YYABORT; } } | K_MAX '(' any_expr ',' any_expr ')' { $$ = $3 > $5 ? $3 : $5; } | K_MIN '(' any_expr ',' any_expr ')' { $$ = $3 < $5 ? $3 : $5; } | INT '(' any_expr ')' { $$ = floor($3); } | RAND '(' any_expr ')' { $$ = 1.0 + floor(((rand()&0x7fff)/double(0x7fff))*$3); } | RAND '(' ')' { /* return a random number in the range [0,1) */ /* portable, but not very random */ $$ = (rand() & 0x7fff) / double(0x8000); } | expr '<' expr { $$ = ($1 < $3); } | expr LESSEQUAL expr { $$ = ($1 <= $3); } | expr '>' expr { $$ = ($1 > $3); } | expr GREATEREQUAL expr { $$ = ($1 >= $3); } | expr EQUALEQUAL expr { $$ = ($1 == $3); } | expr NOTEQUAL expr { $$ = ($1 != $3); } | expr ANDAND expr { $$ = ($1 != 0.0 && $3 != 0.0); } | expr OROR expr { $$ = ($1 != 0.0 || $3 != 0.0); } | '!' expr { $$ = ($2 == 0.0); } ;%%/* bison defines const to be empty unless __STDC__ is defined, which itisn't under cfront */#ifdef const#undef const#endifstatic struct { const char *name; double val; int scaled; // non-zero if val should be multiplied by scale} defaults_table[] = { "arcrad", .25, 1, "arrowht", .1, 1, "arrowwid", .05, 1, "circlerad", .25, 1, "boxht", .5, 1, "boxwid", .75, 1, "boxrad", 0.0, 1, "dashwid", .05, 1, "ellipseht", .5, 1, "ellipsewid", .75, 1, "moveht", .5, 1, "movewid", .5, 1, "lineht", .5, 1, "linewid", .5, 1, "textht", 0.0, 1, "textwid", 0.0, 1, "scale", 1.0, 0, "linethick", -1.0, 0, // in points "fillval", .5, 0, "arrowhead", 1.0, 0, "maxpswid", 8.5, 0, "maxpsht", 11.0, 0,};place *lookup_label(const char *label){ saved_state *state = current_saved_state; PTABLE(place) *tbl = current_table; for (;;) { place *pl = tbl->lookup(label); if (pl) return pl; if (!state) return 0; tbl = state->tbl; state = state->prev; }}void define_label(const char *label, const place *pl){ place *p = new place; *p = *pl; current_table->define(label, p);}int lookup_variable(const char *name, double *val){ place *pl = lookup_label(name); if (pl) { *val = pl->x; return 1; } return 0;}void define_variable(const char *name, double val){ place *p = new place; p->obj = 0; p->x = val; p->y = 0.0; current_table->define(name, p); if (strcmp(name, "scale") == 0) { // When the scale changes, reset all scaled pre-defined variables to // their default values. for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++) if (defaults_table[i].scaled) define_variable(defaults_table[i].name, val*defaults_table[i].val); }}// called once only (not once per parse)void parse_init(){ current_direction = RIGHT_DIRECTION; current_position.x = 0.0; current_position.y = 0.0; // This resets everything to its default value. reset_all();}void reset(const char *nm){ for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++) if (strcmp(nm, defaults_table[i].name) == 0) { double val = defaults_table[i].val; if (defaults_table[i].scaled) { double scale; lookup_variable("scale", &scale); val *= scale; } define_variable(defaults_table[i].name, val); return; } lex_error("`%1' is not a predefined variable", nm);}void reset_all(){ // We only have to explicitly reset the pre-defined variables that // aren't scaled because `scale' is not scaled, and changing the // value of `scale' will reset all the pre-defined variables that // are scaled. for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++) if (!defaults_table[i].scaled) define_variable(defaults_table[i].name, defaults_table[i].val);}// called after each parsevoid parse_cleanup(){ while (current_saved_state != 0) { delete current_table; current_table = current_saved_state->tbl; saved_state *tem = current_saved_state; current_saved_state = current_saved_state->prev; delete tem; } assert(current_table == &top_table); PTABLE_ITERATOR(place) iter(current_table); const char *key; place *pl; while (iter.next(&key, &pl)) if (pl->obj != 0) { position pos = pl->obj->origin(); pl->obj = 0; pl->x = pos.x; pl->y = pos.y; } while (olist.head != 0) { object *tem = olist.head; olist.head = olist.head->next; delete tem; } olist.tail = 0; current_direction = RIGHT_DIRECTION; current_position.x = 0.0; current_position.y = 0.0;}const char *ordinal_postfix(int n){ if (n < 10 || n > 20) switch (n % 10) { case 1: return "st"; case 2: return "nd"; case 3: return "rd"; } return "th";}const char *object_type_name(object_type type){ switch (type) { case BOX_OBJECT: return "box"; case CIRCLE_OBJECT: return "circle"; case ELLIPSE_OBJECT: return "ellipse"; case ARC_OBJECT: return "arc"; case SPLINE_OBJECT: return "spline"; case LINE_OBJECT: return "line"; case ARROW_OBJECT: return "arrow"; case MOVE_OBJECT: return "move"; case TEXT_OBJECT: return "\"\""; case BLOCK_OBJECT: return "[]"; case OTHER_OBJECT: case MARK_OBJECT: default: break; } return "object";}static char sprintf_buf[1024];char *format_number(const char *form, double n){ if (form == 0) form = "%g"; else { // this is a fairly feeble attempt at validation of the format int nspecs = 0; for (const char *p = form; *p != '\0'; p++) if (*p == '%') { if (p[1] == '%') p++; else nspecs++; } if (nspecs > 1) { lex_error("bad format `%1'", form); return strsave(form); } } sprintf(sprintf_buf, form, n); return strsave(sprintf_buf);}char *do_sprintf(const char *form, const double *v, int nv){ string result; int i = 0; string one_format; while (*form) { if (*form == '%') { one_format += *form++; for (; *form != '\0' && strchr("#-+ 0123456789.", *form) != 0; form++) one_format += *form; if (*form == '\0' || strchr("eEfgG%", *form) == 0) { lex_error("bad sprintf format"); result += one_format; result += form; break; } if (*form == '%') { one_format += *form++; one_format += '\0'; sprintf(sprintf_buf, one_format.contents()); } else { if (i >= nv) { lex_error("too few arguments to sprintf"); result += one_format; result += form; break; } one_format += *form++; one_format += '\0'; sprintf(sprintf_buf, one_format.contents(), v[i++]); } one_format.clear(); result += sprintf_buf; } else result += *form++; } result += '\0'; return strsave(result.contents());}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -