diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/sketch/sketch.y |
Initial commit
Diffstat (limited to 'graphics/sketch/sketch.y')
-rw-r--r-- | graphics/sketch/sketch.y | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/graphics/sketch/sketch.y b/graphics/sketch/sketch.y new file mode 100644 index 0000000000..b3494753c4 --- /dev/null +++ b/graphics/sketch/sketch.y @@ -0,0 +1,416 @@ +/* sketch.y + Copyright (C) 2005,2006,2007 Eugene K. Ressler, Jr. + +This file is part of Sketch, a small, simple system for making +3d drawings with LaTeX and the PSTricks or TikZ package. + +Sketch is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +Sketch is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Sketch; see the file COPYING.txt. If not, see +http://www.gnu.org/copyleft */ + +%{ + +#include <stdio.h> +#include <stdlib.h> + +#if defined(_WIN32) +#include <malloc.h> +#if !defined(alloca) +#define alloca _alloca +#endif +#define YYSTACK_USE_ALLOCA 1 +// turn of warning about unused goto label in bison skeleton +#pragma warning(disable:4102) +#endif + +#include "parse.h" +#include "expr.h" +#include "bsp.h" +#include "global.h" + +int yylex(void); + +void yyerror (char *s) /* Called by yyparse on error */ +{ + extern SRC_LINE line; + err(line, "%s", s); +} + +static SYMBOL_TABLE *sym_tab; +static BSP_TREE bsp; +static FILE *yyout; + +// exported parse tree and global environment +static OBJECT *objects; + +%} + +%union { + char *str; + FLOAT flt; + POINT_3D pt; + VECTOR_3D vec; + TRANSFORM xf; + EXPR_VAL exv; + SYMBOL_NAME name; + SYMBOL_NAME_NODE *name_list; + OBJECT *obj; + OPTS *opts; + int bool; + int index; +} + +%token <name>ID <name>PAREN_ID <name>BRACKET_ID +%token <name>DBL_BRACKET_ID <name>CURLY_ID <name>ANGLE_ID +%token <name_list>BRACKET_ID_LIST +%token <flt>NUM +%token <str>OPTS_STR <str>SPECIAL +%token <index>TICK +%token THEN DEF EMPTY_ANGLE +%token DOTS LINE CURVE POLYGON REPEAT SWEEP PUT SPECIAL +%token TRANSLATE ROTATE SCALE PROJECT PERSPECTIVE VIEW +%token SQRT SIN COS ATAN2 UNIT INVERSE +%token GLOBAL SET PICTUREBOX FRAME CAMERA +%token LANGUAGE PSTRICKS TIKZ LaTeX ConTeXt + +%type <name> tagged_defs +%type <opts> options +%type <flt> scalar scalar_expr opt_baseline +%type <pt> point point_expr +%type <vec> vector vector_expr +%type <xf> transform transform_expr +%type <exv> expr +%type <obj> defs_and_decls rev_defs_and_decls decl def_or_decl +%type <obj> defable points rev_points transforms rev_transforms +%type <bool> opt_star +%type <index> output_language comma_macro_package graphics_language macro_package + +%right THEN +%left '-' '+' +%left '*' '/' '.' +%left NEG /* negation--unary minus */ +%right '^' /* exponentiation */ +%left TICK /* point and vector indexing */ + +%% + +input : defs_and_decls global_decl_block { objects = $1; } + + /* sets global_env as a side effect */ +global_decl_block : GLOBAL '{' global_decls '}' + | /* empty */ + ; + +global_decls : global_decls global_decl + | global_decl + ; + +global_decl : SET OPTS_STR + { + set_global_env_opts(global_env, $2, line); + } + | PICTUREBOX '[' scalar_expr ']' + { + set_global_baseline(global_env, $3, line); + } + | PICTUREBOX opt_baseline point point + { + set_global_baseline(global_env, $2, line); + set_global_env_extent(global_env, $3, $4, line); + } + | CAMERA transform_expr + { + set_global_env_camera(global_env, $2, line); + } + | FRAME + { + set_global_env_frame(global_env, NULL, line); + } + | FRAME OPTS_STR + { + set_global_env_frame(global_env, $2, line); + } + | LANGUAGE output_language + { + set_global_output_language(global_env, $2, line); + } + | def + ; + +output_language : graphics_language comma_macro_package { $$ = $1 | $2; } + ; + +graphics_language : PSTRICKS { $$ = GEOL_PSTRICKS; } + | TIKZ { $$ = GEOL_TIKZ; } + ; + +comma_macro_package : ',' macro_package { $$ = $2; } + | /* empty */ { $$ = GEOL_LATEX; } + ; + +macro_package : LaTeX { $$ = GEOL_LATEX; } + | ConTeXt { $$ = GEOL_CONTEXT; } + ; + +opt_baseline : '[' scalar_expr ']' { $$ = $2; } + | /* empty */ { $$ = NO_BASELINE; } + ; + +defs_and_decls : rev_defs_and_decls { $$ = sibling_reverse($1); } + ; + +rev_defs_and_decls : rev_defs_and_decls def_or_decl { $$ = cat_objects($2, $1); } + | def_or_decl { $$ = $1; } + ; + +def_or_decl : def { $$ = NULL; } + | decl { $$ = $1; } + ; + + /* slightly strange rules are to avoid inherited attributes */ +def : DEF ID defable { new_symbol(sym_tab, $2, 0, $3, line); } + | tagged_defs EMPTY_ANGLE defable { new_symbol(sym_tab, $1, 0, $3, line); } + | DEF ID EMPTY_ANGLE { new_symbol(sym_tab, $2, 0, new_tag_def(), line); } + ; + +tagged_defs : DEF ID ANGLE_ID defable { strcpy($$, new_symbol(sym_tab, $2, $3, $4, line) ? "" : $2); } + | tagged_defs ANGLE_ID defable { strcpy($$, new_symbol(sym_tab, $1, $2, $3, line) ? "" : $1); } + ; + +defable : expr { $$ = object_from_expr(&$1); } + | decl { $$ = $1; } + | OPTS_STR { $$ = new_opts_def($1, line); } + ; + +decl : DOTS options points { $$ = new_dots($2, $3); } + | LINE options points { $$ = new_line($2, $3); } + | CURVE options points { $$ = new_curve($2, $3); } + | POLYGON options points { $$ = new_polygon($2, $3); } + | SWEEP options '{' scalar_expr opt_star ',' transforms '}' point + { + $$ = new_sweep($2, $4, $5, $7, new_point_def($9)); + } + | SWEEP options '{' scalar_expr opt_star ',' transforms '}' decl + { + $$ = new_sweep($2, $4, $5, $7, $9); + } + | REPEAT '{' scalar_expr ',' transforms '}' decl + { + $$ = new_repeat($3, $5, $7); + } + | PUT '{' transform_expr '}' decl { $$ = new_compound($3, $5); } + | SPECIAL options points { $$ = new_special($1, $2, $3, line); } + | SPECIAL options { $$ = new_special($1, $2, new_point_def(origin_3d), line); } + | CURLY_ID { look_up_drawable(sym_tab, &$$, line, $1); } + | '{' { sym_tab = new_scope(sym_tab); } + defs_and_decls { sym_tab = old_scope(sym_tab); } + '}' + { + if ($3 == NULL) + err(line, "no drawables in compound declaration"); + $$ = $3; + } + ; + +opt_star : EMPTY_ANGLE { $$ = 1; } + | /* empty */ { $$ = 0; } + ; + +options : OPTS_STR { $$ = new_opts($1, line); } + | BRACKET_ID { look_up_opts(sym_tab, &$$, line, $1); } + | BRACKET_ID_LIST + { + look_up_multiple_opts(sym_tab, &$$, line, $1); + delete_symbol_name_list(&$1); + } + | /* empty */ { $$ = NULL; } + ; + +points : rev_points { $$ = sibling_reverse($1); } + ; + +rev_points : rev_points point { $$ = cat_objects(new_point_def($2), $1); } + | point { $$ = new_point_def($1); } + ; + +transforms : rev_transforms { $$ = sibling_reverse($1); } + ; + +rev_transforms : rev_transforms ',' transform_expr { $$ = cat_objects(new_transform_def($3), $1); } + | transform_expr { $$ = new_transform_def($1); } + ; + +expr : scalar { set_float(&$$, $1); } + | point { set_point(&$$, $1); } + | vector { set_vector(&$$, $1); } + | transform { set_transform(&$$, $1); } + | expr '+' expr { do_add(&$$, &$1, &$3, line); } + | expr '-' expr { do_sub(&$$, &$1, &$3, line); } + | expr '*' expr { do_mul(&$$, &$1, &$3, line); } + | expr '/' expr { do_dvd(&$$, &$1, &$3, line); } + | expr '.' expr { do_dot(&$$, &$1, &$3, line); } + | expr THEN expr { do_thn(&$$, &$1, &$3, line); } + | '|' expr '|' { do_mag(&$$, &$2, line); } + | '-' expr %prec NEG { do_neg(&$$, &$2, line); } + | expr '^' expr { do_pwr(&$$, &$1, &$3, line); } + | '(' expr ')' { $$ = $2; } + | UNIT expr ')' { do_unit(&$$, &$2, line); } + | SQRT expr ')' { do_sqrt(&$$, &$2, line); } + | SIN expr ')' { do_sin(&$$, &$2, line); } + | COS expr ')' { do_cos(&$$, &$2, line); } + | ATAN2 expr ',' expr ')' { do_atan2(&$$, &$2, &$4, line); } + | expr TICK { do_index(&$$, &$1, $2, line); } + ; + +scalar : NUM { $$ = $1; } + | ID { look_up_scalar(sym_tab, &$$, line, $1); } + ; + +scalar_expr : expr { coerce_to_float(&$1, &$$, line); } + ; + +point : '(' scalar_expr ',' scalar_expr ',' scalar_expr ')' + { + $$[X] = $2; $$[Y] = $4; $$[Z] = $6; + } + | '(' scalar_expr ',' scalar_expr ')' + { + $$[X] = $2; $$[Y] = $4; $$[Z] = 0; + } + | PAREN_ID { look_up_point(sym_tab, $$, line, $1); } + ; + +point_expr : expr { coerce_to_point(&$1, $$, line); } + ; + +vector : '[' scalar_expr ',' scalar_expr ',' scalar_expr ']' + { + $$[X] = $2; $$[Y] = $4; $$[Z] = $6; + } + | '[' scalar_expr ',' scalar_expr ']' + { + $$[X] = $2; $$[Y] = $4; $$[Z] = 0; + } + | BRACKET_ID { look_up_vector(sym_tab, $$, line, $1); } + +vector_expr : expr { coerce_to_vector(&$1, $$, line); } + ; + +transform : '[' + '[' scalar_expr ',' scalar_expr ',' scalar_expr',' scalar_expr ']' + '[' scalar_expr ',' scalar_expr ',' scalar_expr',' scalar_expr ']' + '[' scalar_expr ',' scalar_expr ',' scalar_expr',' scalar_expr ']' + '[' scalar_expr ',' scalar_expr ',' scalar_expr',' scalar_expr ']' + ']' + { // transform is column major while elements are row major + $$[0] = $3; $$[4] = $5; $$[8] = $7; $$[12] = $9; + $$[1] = $12; $$[5] = $14; $$[9] = $16; $$[13] = $18; + $$[2] = $21; $$[6] = $23; $$[10] = $25; $$[14] = $27; + $$[3] = $30; $$[7] = $32; $$[11] = $34; $$[15] = $36; + } + | ROTATE scalar_expr ')' + { + set_angle_axis_rot_about_point($$, $2 * (PI/180), 0, 0); + } + | ROTATE scalar_expr ',' expr ')' + { + if (EXPR_TYPE_IS(&$4, E_POINT)) + set_angle_axis_rot_about_point($$, $2 * (PI/180), $4.val.pt, 0); + else if (EXPR_TYPE_IS(&$4, E_VECTOR)) + set_angle_axis_rot_about_point($$, $2 * (PI/180), 0, $4.val.vec); + else + err(line, "expected point or vector rotation parameter, and it's a %s", + expr_val_type_str[$4.tag]); + } + | ROTATE scalar_expr ',' point_expr ',' vector_expr ')' + { + set_angle_axis_rot_about_point($$, $2 * (PI/180), $4, $6); + } + | TRANSLATE vector_expr ')' + { + set_translation($$, $2[X], $2[Y], $2[Z]); + } + | SCALE expr ')' + { + if ($2.tag == E_FLOAT) { + FLOAT s = $2.val.flt; + set_scale($$, s, s, s); + } + else if ($2.tag == E_VECTOR) { + VECTOR v = $2.val.vec; + set_scale($$, v[X], v[Y], v[Z]); + } + else { + err(line, + "expected scalar or vector scale parameter, and it's a %s", + expr_val_type_str[$2.tag]); + set_ident($$); + } + } + | PROJECT ')' { set_parallel_projection($$); } + | PROJECT scalar_expr ')' { set_perspective_projection($$, $2); } + | PERSPECTIVE scalar_expr ')' { set_perspective_transform($$, $2); } + | VIEW point_expr ',' expr ',' vector_expr ')' + { + if ($4.tag == E_VECTOR) + set_view_transform($$, $2, $4.val.vec, $6); + else if ($4.tag == E_POINT) + set_view_transform_with_look_at($$, $2, $4.val.pt, $6); + else + err(line, "expected point or vector view parameter, and it's a %s", + expr_val_type_str[$4.tag]); + } + | VIEW point_expr ',' expr ')' + { + if ($4.tag == E_VECTOR) + set_view_transform($$, $2, $4.val.vec, NULL); + else if ($4.tag == E_POINT) + set_view_transform_with_look_at($$, $2, $4.val.pt, NULL); + else + err(line, "expected point or vector view parameter, and it's a %s", + expr_val_type_str[$4.tag]); + } + | VIEW point_expr ')' + { + set_view_transform($$, $2, NULL, NULL); + } + + | INVERSE transform_expr ')' { do_inverse($$, $2, line); } + | DBL_BRACKET_ID { look_up_transform(sym_tab, $$, line, $1); } + ; + +transform_expr : expr { coerce_to_transform(&$1, $$, line); } + ; + +%% + +int parse(SYMBOL_TABLE *st) +{ + int ret; + + objects = NULL; + sym_tab = st; + ret = yyparse(); + + // should set sym_tab back to NULL + sym_tab = old_scope(sym_tab); + if (sym_tab) + die(no_line, "zombie symbol table"); + + return ret; +} + +OBJECT *parsed_objects(void) +{ + return objects; +} |