summaryrefslogtreecommitdiff
path: root/graphics/sketch/sketch.y
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /graphics/sketch/sketch.y
Initial commit
Diffstat (limited to 'graphics/sketch/sketch.y')
-rw-r--r--graphics/sketch/sketch.y416
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;
+}