2 Copyright (C) 2005,2006,2007,2008 Eugene K. Ressler, Jr.
4 This file is part of Sketch, a small, simple system for making
5 3d drawings with LaTeX and the PSTricks or TikZ package.
7 Sketch is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 Sketch is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Sketch; see the file COPYING.txt. If not, see
19 http://www.gnu.org/copyleft */
29 #define alloca _alloca
31 #define YYSTACK_USE_ALLOCA 1
32 // turn of warning about unused goto label in bison skeleton
33 #pragma warning(disable:4102)
43 void yyerror (char *s
) /* Called by yyparse on error */
49 static SYMBOL_TABLE
*sym_tab
;
53 // exported parse tree and global environment
54 static OBJECT
*objects
;
72 %token
<name
>ID
<name
>PAREN_ID
<name
>BRACKET_ID
73 %token
<name
>DBL_BRACKET_ID
<name
>CURLY_ID
<name
>ANGLE_ID
75 %token
<str
>OPTS_STR
<str
>SPECIAL
77 %token THEN DEF EMPTY_ANGLE
78 %token DOTS LINE CURVE POLYGON REPEAT SWEEP PUT SPECIAL
79 %token TRANSLATE ROTATE SCALE PROJECT PERSPECTIVE VIEW
80 %token SQRT SIN COS ATAN2 UNIT INVERSE
81 %token GLOBAL SET PICTUREBOX FRAME CAMERA
82 %token LANGUAGE PSTRICKS TIKZ LaTeX ConTeXt
84 %type
<name
> tagged_defs
85 %type
<opts
> options option_id_list
86 %type
<flt
> scalar scalar_expr opt_baseline
87 %type
<pt
> point point_expr
88 %type
<vec
> vector vector_expr
89 %type
<xf
> transform transform_expr
91 %type
<obj
> defs_and_decls rev_defs_and_decls decl def_or_decl
92 %type
<obj
> defable points rev_points transforms rev_transforms
94 %type
<index
> output_language comma_macro_package graphics_language macro_package
99 %left NEG
/* negation--unary minus */
100 %right
'^' /* exponentiation */
101 %left TICK
/* point and vector indexing */
105 input
: defs_and_decls global_decl_block
{ objects
= $1; }
107 /* sets global_env as a side effect */
108 global_decl_block
: GLOBAL
'{' global_decls
'}'
112 global_decls
: global_decls global_decl
116 global_decl
: SET OPTS_STR
118 set_global_env_opts
(global_env
, $2, line
);
120 | PICTUREBOX
'[' scalar_expr
']'
122 set_global_baseline
(global_env
, $3, line
);
124 | PICTUREBOX opt_baseline point point
126 set_global_baseline
(global_env
, $2, line
);
127 set_global_env_extent
(global_env
, $3, $4, line
);
129 | CAMERA transform_expr
131 set_global_env_camera
(global_env
, $2, line
);
135 set_global_env_frame
(global_env
, NULL
, line
);
139 set_global_env_frame
(global_env
, $2, line
);
141 | LANGUAGE output_language
143 set_global_output_language
(global_env
, $2, line
);
148 output_language
: graphics_language comma_macro_package
{ $$
= $1 |
$2; }
151 graphics_language
: PSTRICKS
{ $$
= GEOL_PSTRICKS
; }
152 | TIKZ
{ $$
= GEOL_TIKZ
; }
155 comma_macro_package
: ',' macro_package
{ $$
= $2; }
156 |
/* empty */ { $$
= GEOL_LATEX
; }
159 macro_package
: LaTeX
{ $$
= GEOL_LATEX
; }
160 | ConTeXt
{ $$
= GEOL_CONTEXT
; }
163 opt_baseline
: '[' scalar_expr
']' { $$
= $2; }
164 |
/* empty */ { $$
= NO_BASELINE
; }
167 defs_and_decls
: rev_defs_and_decls
{ $$
= sibling_reverse
($1); }
170 rev_defs_and_decls
: rev_defs_and_decls def_or_decl
{ $$
= cat_objects
($2, $1); }
171 | def_or_decl
{ $$
= $1; }
174 def_or_decl
: def
{ $$
= NULL
; }
178 /* slightly strange rules are to avoid inherited attributes */
179 def
: DEF ID defable
{ new_symbol
(sym_tab
, $2, 0, $3, line
); }
180 | tagged_defs EMPTY_ANGLE defable
{ new_symbol
(sym_tab
, $1, 0, $3, line
); }
181 | DEF ID EMPTY_ANGLE
{ new_symbol
(sym_tab
, $2, 0, new_tag_def
(), line
); }
184 tagged_defs
: DEF ID ANGLE_ID defable
{ strcpy
($$
, new_symbol
(sym_tab
, $2, $3, $4, line
) ?
"" : $2); }
185 | tagged_defs ANGLE_ID defable
{ strcpy
($$
, new_symbol
(sym_tab
, $1, $2, $3, line
) ?
"" : $1); }
188 defable
: expr
{ $$
= object_from_expr
(&$1); }
190 | OPTS_STR
{ $$
= new_opts_def
($1, line
); }
193 decl
: DOTS options points
{ $$
= new_dots
($2, $3); }
194 | LINE options points
{ $$
= new_line
($2, $3); }
195 | CURVE options points
{ $$
= new_curve
($2, $3); }
196 | POLYGON options points
{ $$
= new_polygon
($2, $3); }
197 | SWEEP options
'{' scalar_expr opt_star
',' transforms
'}' point
199 $$
= new_sweep
($2, $4, $5, $7, new_point_def
($9));
201 | SWEEP options
'{' scalar_expr opt_star
',' transforms
'}' decl
203 $$
= new_sweep
($2, $4, $5, $7, $9);
205 | REPEAT
'{' scalar_expr
',' transforms
'}' decl
207 $$
= new_repeat
($3, $5, $7);
209 | PUT
'{' transform_expr
'}' decl
{ $$
= new_compound
($3, $5); }
210 | SPECIAL options points
{ $$
= new_special
($1, $2, $3, line
); }
211 | SPECIAL options
{ $$
= new_special
($1, $2, new_point_def
(origin_3d
), line
); }
212 | CURLY_ID
{ look_up_drawable
(sym_tab
, &$$
, line
, $1); }
213 |
'{' { sym_tab
= new_scope
(sym_tab
); }
214 defs_and_decls
{ sym_tab
= old_scope
(sym_tab
); }
218 err
(line
, "no drawables in compound declaration");
223 opt_star
: EMPTY_ANGLE
{ $$
= 1; }
224 |
/* empty */ { $$
= 0; }
227 option_id_list
: option_id_list
',' ID
229 $$
= look_up_and_append_to_opts
(sym_tab
, &$1, line
, $3);
234 $$
= look_up_and_append_to_opts
(sym_tab
, &$$
, line
, $1);
238 options
: OPTS_STR
{ $$
= new_opts
($1, line
); }
239 | BRACKET_ID
{ look_up_opts
(sym_tab
, &$$
, line
, $1); }
240 |
'[' option_id_list
']' { $$
= $2; }
241 |
/* empty */ { $$
= NULL
; }
244 points
: rev_points
{ $$
= sibling_reverse
($1); }
247 rev_points
: rev_points point
{ $$
= cat_objects
(new_point_def
($2), $1); }
248 | point
{ $$
= new_point_def
($1); }
251 transforms
: rev_transforms
{ $$
= sibling_reverse
($1); }
254 rev_transforms
: rev_transforms
',' transform_expr
{ $$
= cat_objects
(new_transform_def
($3), $1); }
255 | transform_expr
{ $$
= new_transform_def
($1); }
258 expr
: scalar
{ set_float
(&$$
, $1); }
259 | point
{ set_point
(&$$
, $1); }
260 | vector
{ set_vector
(&$$
, $1); }
261 | transform
{ set_transform
(&$$
, $1); }
262 | expr
'+' expr
{ do_add
(&$$
, &$1, &$3, line
); }
263 | expr
'-' expr
{ do_sub
(&$$
, &$1, &$3, line
); }
264 | expr
'*' expr
{ do_mul
(&$$
, &$1, &$3, line
); }
265 | expr
'/' expr
{ do_dvd
(&$$
, &$1, &$3, line
); }
266 | expr
'.' expr
{ do_dot
(&$$
, &$1, &$3, line
); }
267 | expr THEN expr
{ do_thn
(&$$
, &$1, &$3, line
); }
268 |
'|' expr
'|' { do_mag
(&$$
, &$2, line
); }
269 |
'-' expr %prec NEG
{ do_neg
(&$$
, &$2, line
); }
270 | expr
'^' expr
{ do_pwr
(&$$
, &$1, &$3, line
); }
271 |
'(' expr
')' { $$
= $2; }
272 | UNIT expr
')' { do_unit
(&$$
, &$2, line
); }
273 | SQRT expr
')' { do_sqrt
(&$$
, &$2, line
); }
274 | SIN expr
')' { do_sin
(&$$
, &$2, line
); }
275 | COS expr
')' { do_cos
(&$$
, &$2, line
); }
276 | ATAN2 expr
',' expr
')' { do_atan2
(&$$
, &$2, &$4, line
); }
277 | expr TICK
{ do_index
(&$$
, &$1, $2, line
); }
280 scalar
: NUM
{ $$
= $1; }
281 | ID
{ look_up_scalar
(sym_tab
, &$$
, line
, $1); }
284 scalar_expr
: expr
{ coerce_to_float
(&$1, &$$
, line
); }
287 point
: '(' scalar_expr
',' scalar_expr
',' scalar_expr
')'
289 $$
[X
] = $2; $$
[Y
] = $4; $$
[Z
] = $6;
291 |
'(' scalar_expr
',' scalar_expr
')'
293 $$
[X
] = $2; $$
[Y
] = $4; $$
[Z
] = 0;
295 | PAREN_ID
{ look_up_point
(sym_tab
, $$
, line
, $1); }
298 point_expr
: expr
{ coerce_to_point
(&$1, $$
, line
); }
301 vector
: '[' scalar_expr
',' scalar_expr
',' scalar_expr
']'
303 $$
[X
] = $2; $$
[Y
] = $4; $$
[Z
] = $6;
305 |
'[' scalar_expr
',' scalar_expr
']'
307 $$
[X
] = $2; $$
[Y
] = $4; $$
[Z
] = 0;
309 | BRACKET_ID
{ look_up_vector
(sym_tab
, $$
, line
, $1); }
311 vector_expr
: expr
{ coerce_to_vector
(&$1, $$
, line
); }
315 '[' scalar_expr
',' scalar_expr
',' scalar_expr
',' scalar_expr
']'
316 '[' scalar_expr
',' scalar_expr
',' scalar_expr
',' scalar_expr
']'
317 '[' scalar_expr
',' scalar_expr
',' scalar_expr
',' scalar_expr
']'
318 '[' scalar_expr
',' scalar_expr
',' scalar_expr
',' scalar_expr
']'
320 { // transform is column major while elements are row major
321 $$
[0] = $3; $$
[4] = $5; $$
[8] = $7; $$
[12] = $9;
322 $$
[1] = $12; $$
[5] = $14; $$
[9] = $16; $$
[13] = $18;
323 $$
[2] = $21; $$
[6] = $23; $$
[10] = $25; $$
[14] = $27;
324 $$
[3] = $30; $$
[7] = $32; $$
[11] = $34; $$
[15] = $36;
326 | ROTATE scalar_expr
')'
328 set_angle_axis_rot_about_point
($$
, $2 * (PI
/180), 0, 0);
330 | ROTATE scalar_expr
',' expr
')'
332 if
(EXPR_TYPE_IS
(&$4, E_POINT
))
333 set_angle_axis_rot_about_point
($$
, $2 * (PI
/180), $4.val.pt
, 0);
334 else if
(EXPR_TYPE_IS
(&$4, E_VECTOR
))
335 set_angle_axis_rot_about_point
($$
, $2 * (PI
/180), 0, $4.val.vec
);
337 err
(line
, "expected point or vector rotation parameter, and it's a %s",
338 expr_val_type_str
[$4.tag
]);
340 | ROTATE scalar_expr
',' point_expr
',' vector_expr
')'
342 set_angle_axis_rot_about_point
($$
, $2 * (PI
/180), $4, $6);
344 | TRANSLATE vector_expr
')'
346 set_translation
($$
, $2[X
], $2[Y
], $2[Z
]);
350 if
($2.tag
== E_FLOAT
) {
351 FLOAT s
= $2.val.flt
;
352 set_scale
($$
, s
, s
, s
);
354 else if
($2.tag
== E_VECTOR
) {
355 VECTOR v
= $2.val.vec
;
356 set_scale
($$
, v
[X
], v
[Y
], v
[Z
]);
360 "expected scalar or vector scale parameter, and it's a %s",
361 expr_val_type_str
[$2.tag
]);
365 | PROJECT
')' { set_parallel_projection
($$
); }
366 | PROJECT scalar_expr
')' { set_perspective_projection
($$
, $2); }
367 | PERSPECTIVE scalar_expr
')' { set_perspective_transform
($$
, $2); }
368 | VIEW point_expr
',' expr
',' vector_expr
')'
370 if
($4.tag
== E_VECTOR
)
371 set_view_transform
($$
, $2, $4.val.vec
, $6);
372 else if
($4.tag
== E_POINT
)
373 set_view_transform_with_look_at
($$
, $2, $4.val.pt
, $6);
375 err
(line
, "expected point or vector view parameter, and it's a %s",
376 expr_val_type_str
[$4.tag
]);
378 | VIEW point_expr
',' expr
')'
380 if
($4.tag
== E_VECTOR
)
381 set_view_transform
($$
, $2, $4.val.vec
, NULL
);
382 else if
($4.tag
== E_POINT
)
383 set_view_transform_with_look_at
($$
, $2, $4.val.pt
, NULL
);
385 err
(line
, "expected point or vector view parameter, and it's a %s",
386 expr_val_type_str
[$4.tag
]);
388 | VIEW point_expr
')'
390 set_view_transform
($$
, $2, NULL
, NULL
);
393 | INVERSE transform_expr
')' { do_inverse
($$
, $2, line
); }
394 | DBL_BRACKET_ID
{ look_up_transform
(sym_tab
, $$
, line
, $1); }
397 transform_expr
: expr
{ coerce_to_transform
(&$1, $$
, line
); }
402 int parse
(SYMBOL_TABLE
*st
)
410 // should set sym_tab back to NULL
411 sym_tab
= old_scope
(sym_tab
);
413 die
(no_line
, "zombie symbol table");
418 OBJECT
*parsed_objects
(void)