📄 pic.y
字号:
/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com)This file is part of groff.groff is free software; you can redistribute it and/or modify it underthe terms of the GNU General Public License as published by the FreeSoftware Foundation; either version 2, or (at your option) any laterversion.groff is distributed in the hope that it will be useful, but WITHOUT ANYWARRANTY; without even the implied warranty of MERCHANTABILITY orFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public Licensefor more details.You should have received a copy of the GNU General Public License alongwith groff; see the file COPYING. If not, write to the Free SoftwareFoundation, 675 Mass Ave, Cambridge, MA 02139, USA. */%{#include "pic.h"#include "ptable.h"#include "object.h"extern int delim_flag;extern void do_copy(const char *);extern void copy_rest_thru(const char *, const char *);extern void copy_file_thru(const char *, const char *, const char *);extern void push_body(const char *);extern void do_for(char *var, double from, double to, int by_is_multiplicative, double by, char *body);extern void do_lookahead();#undef fmod#undef randextern "C" { double fmod(double, double); int rand();}/* Maximum number of characters produced by printf("%g") */#define GDIGITS 14int yylex();void yyerror(const char *);void reset(const char *nm);void reset_all();place *lookup_label(const char *);void define_label(const char *label, const place *pl);direction current_direction;position current_position;implement_ptable(place)PTABLE(place) top_table;PTABLE(place) *current_table = &top_table;saved_state *current_saved_state = 0;object_list olist;const char *ordinal_postfix(int n);const char *object_type_name(object_type type);char *format_number(const char *form, double n);char *do_sprintf(const char *form, const double *v, int nv);%}%union { char *str; int n; double x; struct { double x, y; } pair; struct { double x; char *body; } if_data; struct { char *str; const char *filename; int lineno; } lstr; struct { double *v; int nv; int maxv; } dv; struct { double val; int is_multiplicative; } by; place pl; object *obj; corner crn; path *pth; object_spec *spec; saved_state *pstate; graphics_state state; object_type obtype;}%token <str> LABEL%token <str> VARIABLE%token <x> NUMBER%token <lstr> TEXT%token <lstr> COMMAND_LINE%token <str> DELIMITED%token <n> ORDINAL%token TH%token LEFT_ARROW_HEAD%token RIGHT_ARROW_HEAD%token DOUBLE_ARROW_HEAD%token LAST%token UP%token DOWN%token LEFT%token RIGHT%token BOX%token CIRCLE%token ELLIPSE%token ARC%token LINE%token ARROW%token MOVE%token SPLINE%token HEIGHT%token RADIUS%token WIDTH%token DIAMETER%token UP%token DOWN%token RIGHT%token LEFT%token FROM%token TO%token AT%token WITH%token BY%token THEN%token DOTTED%token DASHED%token CHOP%token SAME%token INVISIBLE%token LJUST%token RJUST%token ABOVE%token BELOW%token OF%token THE%token WAY%token BETWEEN%token AND%token HERE%token DOT_N%token DOT_E %token DOT_W%token DOT_S%token DOT_NE%token DOT_SE%token DOT_NW%token DOT_SW%token DOT_C%token DOT_START%token DOT_END%token DOT_X%token DOT_Y%token DOT_HT%token DOT_WID%token DOT_RAD%token SIN%token COS%token ATAN2%token LOG%token EXP%token SQRT%token K_MAX%token K_MIN%token INT%token RAND%token COPY%token THRU%token TOP%token BOTTOM%token UPPER%token LOWER%token SH%token PRINT%token CW%token CCW%token FOR%token DO%token IF%token ELSE%token ANDAND%token OROR%token NOTEQUAL%token EQUALEQUAL%token LESSEQUAL%token GREATEREQUAL%token LEFT_CORNER%token RIGHT_CORNER%token CENTER%token END%token START%token RESET%token UNTIL%token PLOT%token THICKNESS%token FILL%token ALIGNED%token SPRINTF%token COMMAND%token DEFINE%token UNDEF/* this ensures that plot 17 "%g" parses as (plot 17 "%g") */%left PLOT%left TEXT SPRINTF/* give text adjustments higher precedence than TEXT, so thatbox "foo" above ljust == box ("foo" above ljust)*/%left LJUST RJUST ABOVE BELOW%left LEFT RIGHT/* Give attributes that take an optional expression a higherprecedence than left and right, so that eg `line chop left'parses properly. */%left CHOP DASHED DOTTED UP DOWN FILL%left LABEL%left VARIABLE NUMBER '(' SIN COS ATAN2 LOG EXP SQRT K_MAX K_MIN INT RAND LAST %left ORDINAL HERE '`'/* these need to be lower than '-' */%left HEIGHT RADIUS WIDTH DIAMETER FROM TO AT THICKNESS/* these must have higher precedence than CHOP so that `label %prec CHOP'works */%left DOT_N DOT_E DOT_W DOT_S DOT_NE DOT_SE DOT_NW DOT_SW DOT_C%left DOT_START DOT_END TOP BOTTOM LEFT_CORNER RIGHT_CORNER%left UPPER LOWER CENTER START END%left ','%left OROR%left ANDAND%left EQUALEQUAL NOTEQUAL%left '<' '>' LESSEQUAL GREATEREQUAL%left BETWEEN OF%left AND%left '+' '-'%left '*' '/' '%'%right '!'%right '^'%type <x> expr any_expr text_expr%type <by> optional_by%type <pair> expr_pair position_not_place%type <if_data> simple_if%type <obj> nth_primitive%type <crn> corner%type <pth> path label_path relative_path%type <pl> place label element element_list middle_element_list%type <spec> object_spec%type <pair> position%type <obtype> object_type%type <n> optional_ordinal_last ordinal%type <str> until%type <dv> sprintf_args%type <lstr> text print_args print_arg%%top: optional_separator | element_list { if (olist.head) print_picture(olist.head); } ;element_list: optional_separator middle_element_list optional_separator { $$ = $2; } ;middle_element_list: element { $$ = $1; } | middle_element_list separator element { $$ = $1; } ;optional_separator: /* empty */ | separator ;separator: ';' | separator ';' ;placeless_element: VARIABLE '=' any_expr { define_variable($1, $3); a_delete $1; } | VARIABLE ':' '=' any_expr { place *p = lookup_label($1); if (!p) { lex_error("variable `%1' not defined", $1); YYABORT; } p->obj = 0; p->x = $4; p->y = 0.0; a_delete $1; } | UP { current_direction = UP_DIRECTION; } | DOWN { current_direction = DOWN_DIRECTION; } | LEFT { current_direction = LEFT_DIRECTION; } | RIGHT { current_direction = RIGHT_DIRECTION; } | COMMAND_LINE { olist.append(make_command_object($1.str, $1.filename, $1.lineno)); } | COMMAND print_args { olist.append(make_command_object($2.str, $2.filename, $2.lineno)); } | PRINT print_args { fprintf(stderr, "%s\n", $2.str); a_delete $2.str; fflush(stderr); } | SH { delim_flag = 1; } DELIMITED { delim_flag = 0; system($3); a_delete $3; } | COPY TEXT { if (yychar < 0) do_lookahead(); do_copy($2.str); // do not delete the filename } | COPY TEXT THRU { delim_flag = 2; } DELIMITED { delim_flag = 0; } until { if (yychar < 0) do_lookahead(); copy_file_thru($2.str, $5, $7); // do not delete the filename a_delete $5; a_delete $7; } | COPY THRU { delim_flag = 2; } DELIMITED { delim_flag = 0; } until { if (yychar < 0) do_lookahead(); copy_rest_thru($4, $6); a_delete $4; a_delete $6; } | FOR VARIABLE '=' expr TO expr optional_by DO { delim_flag = 1; } DELIMITED { delim_flag = 0; if (yychar < 0) do_lookahead(); do_for($2, $4, $6, $7.is_multiplicative, $7.val, $10); } | simple_if { if (yychar < 0) do_lookahead(); if ($1.x != 0.0) push_body($1.body); a_delete $1.body; } | simple_if ELSE { delim_flag = 1; } DELIMITED { delim_flag = 0; if (yychar < 0) do_lookahead(); if ($1.x != 0.0) push_body($1.body); else push_body($4); a_delete $1.body; a_delete $4; } | reset_variables | RESET { define_variable("scale", 1.0); } ;reset_variables: RESET VARIABLE { reset($2); a_delete $2; } | reset_variables VARIABLE { reset($2); a_delete $2; } | reset_variables ',' VARIABLE { reset($3); a_delete $3; } ;print_args: print_arg { $$ = $1; } | print_args print_arg { $$.str = new char[strlen($1.str) + strlen($2.str) + 1]; strcpy($$.str, $1.str); strcat($$.str, $2.str); a_delete $1.str; a_delete $2.str; if ($1.filename) { $$.filename = $1.filename; $$.lineno = $1.lineno; } else if ($2.filename) { $$.filename = $2.filename; $$.lineno = $2.lineno; } } ;print_arg: expr %prec ',' { $$.str = new char[GDIGITS + 1]; sprintf($$.str, "%g", $1); $$.filename = 0; $$.lineno = 0; } | text { $$ = $1; } | position %prec ',' { $$.str = new char[GDIGITS + 2 + GDIGITS + 1]; sprintf($$.str, "%g, %g", $1.x, $1.y); $$.filename = 0; $$.lineno = 0; }simple_if: IF any_expr THEN { delim_flag = 1; } DELIMITED { delim_flag = 0; $$.x = $2; $$.body = $5; } ;until: /* empty */ { $$ = 0; } | UNTIL TEXT { $$ = $2.str; } ; any_expr: expr { $$ = $1; } | text_expr { $$ = $1; } ; text_expr: text EQUALEQUAL text { $$ = strcmp($1.str, $3.str) == 0; a_delete $1.str; a_delete $3.str; } | text NOTEQUAL text { $$ = strcmp($1.str, $3.str) != 0; a_delete $1.str; a_delete $3.str; } | text_expr ANDAND text_expr { $$ = ($1 != 0.0 && $3 != 0.0); } | text_expr ANDAND expr { $$ = ($1 != 0.0 && $3 != 0.0); } | expr ANDAND text_expr { $$ = ($1 != 0.0 && $3 != 0.0); } | text_expr OROR text_expr { $$ = ($1 != 0.0 || $3 != 0.0); } | text_expr OROR expr { $$ = ($1 != 0.0 || $3 != 0.0); } | expr OROR text_expr { $$ = ($1 != 0.0 || $3 != 0.0); } | '!' text_expr { $$ = ($2 == 0.0); } ;optional_by: /* empty */ { $$.val = 1.0; $$.is_multiplicative = 0; } | BY expr { $$.val = $2; $$.is_multiplicative = 0; } | BY '*' expr { $$.val = $3; $$.is_multiplicative = 1; } ;element: object_spec { $$.obj = $1->make_object(¤t_position, ¤t_direction); if ($$.obj == 0) YYABORT; delete $1; if ($$.obj) olist.append($$.obj); else { $$.x = current_position.x; $$.y = current_position.y; } } | LABEL ':' optional_separator element { $$ = $4; define_label($1, & $$); a_delete $1; } | LABEL ':' optional_separator position_not_place { $$.obj = 0; $$.x = $4.x; $$.y = $4.y; define_label($1, & $$); a_delete $1; } | LABEL ':' optional_separator place { $$ = $4; define_label($1, & $$); a_delete $1; } | '{' { $<state>$.x = current_position.x; $<state>$.y = current_position.y; $<state>$.dir = current_direction; } element_list '}' { current_position.x = $<state>2.x; current_position.y = $<state>2.y; current_direction = $<state>2.dir; } optional_element { $$ = $3; } | placeless_element { $$.obj = 0; $$.x = current_position.x; $$.y = current_position.y; } ;optional_element: /* empty */ {} | element {} ;object_spec: BOX { $$ = new object_spec(BOX_OBJECT); } | CIRCLE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -