initial setup of thesis repository
[cluster_expansion_thesis.git] / little_helpers / tikz / sketch-0.2.161 / sketch.l
blob5da403c29a534e75610b80c8999b7926b3ea577e
1 %{
3 /* sketch.l
4    Copyright (C) 2005,2006,2007,2008 Eugene K. Ressler, Jr.
6 This file is part of Sketch, a small, simple system for making 
7 3d drawings with LaTeX and the PSTricks or TikZ package.
9 Sketch is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3, or (at your option)
12 any later version.
14 Sketch is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Sketch; see the file COPYING.txt.  If not, see
21 http://www.gnu.org/copyleft */
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include "geometry.h"
27 #include "symbol.h"
28 #include "expr.h"
29 #include "parse.h"
30 #include "y.tab.h"
31 #include "error.h"
32 #include "opts.h"
34 #if defined(_WIN32) && !defined fileno
35 #define fileno(F) _fileno(F)
36 #pragma warning(disable:4102)
37 #endif
39 // undo the safety net in polygon.h so flex scanner can use these library functions
40 #undef malloc
41 #undef realloc
42 #undef free
43 #undef strdup
45 SRC_LINE line;
47 #define MAX_INPUT_DEPTH 10
49 struct {
50  YY_BUFFER_STATE buffer_state;
51  SRC_LINE line;
52 } input_stack[MAX_INPUT_DEPTH];
53 int input_stack_ptr = 0;
55 #define INIT_SPECIAL_BUF_SIZE 40
57 void update_line_number(void)
59   int i;
61   for (i = 0; yytext[i]; i++)
62     if (yytext[i] == '\n')
63       line.number++;
68 %x inputdirective
70 Identifier [A-Za-z]([A-Za-z0-9_]*[A-Za-z0-9])?
71 WSnotNL [ \t\r]
72 WS [ \t\r\n]
76 [%#].* /* comment; do nothing */
78 {WSnotNL}+ /* white space; do nothing */ 
80 "\n" { 
81   line.number++; 
84 "["[^\]=]+=[^\]]+"]" { /* [<stuff>=<stuff>] */
85   // elide the brackets
86   yylval.str = safe_malloc(yyleng + 1 - 2);
87   str_slice(yylval.str, yyleng + 1 - 2, yytext, 1, -1);
88   return OPTS_STR;
91 "language" {
92         return LANGUAGE;
95 "pstricks" {
96         return PSTRICKS;
99 "tikz" {
100         return TIKZ;
103 "latex" {
104         return LaTeX;
107 "context" {
108         return ConTeXt;
111 "input"{WS}* {
112   update_line_number();
113   BEGIN(inputdirective);
116 "curve" {
117   return CURVE;
120 "camera" {
121   return CAMERA;
124 "def" {
125   return DEF;
128 "dots" {
129   return DOTS;
132 "frame" {
133   return FRAME;
136 "global" {
137   return GLOBAL;
140 "line" {
141   return LINE;
144 "polygon" {
145   return POLYGON;
148 "put" {
149   return PUT;
152 "repeat" {
153   return REPEAT;
156 "set" {
157   return SET;
160 "sweep" {
161   return SWEEP;
164 "then" {
165   return THEN;
168 "atan2"{WS}*"(" {
169   update_line_number();
170   return ATAN2;
173 "cos"{WS}*"(" {
174   update_line_number();
175   return COS;
178 "inverse"{WS}*"(" {
179   update_line_number();
180   return INVERSE;
183 "picturebox" {
184   return PICTUREBOX;
187 "perspective"{WS}*"(" {
188   update_line_number();
189   return PERSPECTIVE;
192 "project"{WS}*"(" {
193   update_line_number();
194   return PROJECT;
197 "rotate"{WS}*"(" {
198   update_line_number();
199   return ROTATE;
202 "scale"{WS}*"(" {
203   update_line_number();
204   return SCALE;
207 "sin"{WS}*"(" {
208   update_line_number();
209   return SIN;
212 "special"{WS}* {  
213   char *rtn;
214   int max_rtn_len, delim, i, ch;
216   update_line_number();
218   max_rtn_len = INIT_SPECIAL_BUF_SIZE - 1;
219   rtn = safe_malloc(max_rtn_len + 1);
220   i = 0;
222   delim = input();
224   if (delim == EOF) {
225     err(line, "expected special text, found end of file");
226   }
227   else {
228     while ((ch = input()) != delim && ch != EOF) {
229       if (ch == '\n')
230         ++line.number;
231       if (i == max_rtn_len) {
232         max_rtn_len *= 2;
233         rtn = safe_realloc(rtn, max_rtn_len + 1);
234       }
235       rtn[i++] = ch;
236     }
237     if (ch != delim)
238       err(line, "missing end delimeter '%c' in special", delim);
239   }
240   rtn[i] = '\0';
241   yylval.str = rtn;
242   return SPECIAL;
245 "sqrt"{WS}*"(" {
246   update_line_number();
247   return SQRT;
250 "translate"{WS}*"(" {
251   update_line_number();
252   return TRANSLATE;
255 "unit"{WS}*"(" {
256   update_line_number();
257   return UNIT;
260 "view"{WS}*"(" {
261   update_line_number();
262   return VIEW;
265 {Identifier} { 
266   str_slice(yylval.name, sizeof yylval.name, yytext, 0, sizeof yylval.name);
267   return ID; 
270 "<"{Identifier}">" { 
271   str_slice(yylval.name, sizeof yylval.name, yytext, 1, -1);
272   return ANGLE_ID; 
275 "<>" {
276   return EMPTY_ANGLE;
279 "'"{WS}*"x" {
280   update_line_number();
281   yylval.index = 0;
282   return TICK;
285 "'"{WS}*"y" {
286   update_line_number();
287   yylval.index = 1;
288   return TICK;
291 "'"{WS}*"z" {
292   update_line_number();
293   yylval.index = 2;
294   return TICK;
297 "("{Identifier}")" { 
298   str_slice(yylval.name, sizeof yylval.name, yytext, 1, -1);
299   return PAREN_ID; 
302 "["{Identifier}"]" { 
303   str_slice(yylval.name, sizeof yylval.name, yytext, 1, -1);
304   return BRACKET_ID; 
307 "[["{Identifier}"]]" { 
308   str_slice(yylval.name, sizeof yylval.name, yytext, 2, -2);
309   return DBL_BRACKET_ID; 
312 "{"{Identifier}"}" { 
313   str_slice(yylval.name, sizeof yylval.name, yytext, 1, -1);
314   return CURLY_ID; 
317 (([0-9]+"."[0-9]*)|("."[0-9]+)|([0-9]+))([eE][-+]?[0-9]+)? { 
318   if (sscanf(yytext, FLOAT_SCAN_FMT, &yylval.flt) != 1) {
319     err(line, "numeric constant %s could not be converted (probably out of range)", yytext);
320     yylval.flt = 0;
321   }
322   return NUM;
325 "("{WS}*{Identifier}{WS}*")" {
326   warn(line, "found parenthesized identifier '%s'; delete space if you meant a point ref", yytext);
327   yyless(1);
328   return '(';
331 "["{WS}*{Identifier}{WS}*"]" {
332   warn(line, "found id in brackets '%s'; delete space if you meant a vector ref", yytext);
333   yyless(1);
334   return '[';
337 "{"{WS}*{Identifier}{WS}*"}" {
338   warn(line, "found id in braces '%s'; delete space if you meant a drawable ref", yytext);
339   yyless(1);
340   return '{';
343 "[["{WS}*{Identifier}{WS}*"]]" {
344   warn(line, "found id in double-brackets '%s'; delete space if you meant a transform ref", yytext);
345   yyless(1);
346   return '[';
349 "<"{WS}*{Identifier}{WS}*">" {
350   warn(line, "found id in angle-brackets '%s'; delete space if you meant a tag ref", yytext);
351   yyless(1);
352   return '<';
355 [-+*/^|.()\[\]{}=,]     { 
356   return yytext[0];     
359 <inputdirective>"{"[^}]*"}" {
361   FILE *f;
362   char buf[1024];
363   int i;
365   if (line.file_name[0] != '/' && line.file_name[0] != '\\')
366     i = str_last_occurance(line.file_name, "/\\");
367   if (i >= 0) {
368     str_slice(buf, sizeof buf, line.file_name, 0, i + 1);
369   }
370   else {
371     buf[0] = '\0';
372   }
374   i = strlen(buf);
375   str_slice(&buf[i], sizeof buf - i, yytext, 1, -1);
377   if (input_stack_ptr >= MAX_INPUT_DEPTH) {
378     err(line, "inputs nested too deeply (file '%s' ignored)", buf);
379   }
380   else {
381     f = fopen(buf, "r");
382     if (f) {
383       yyin = f;
384       input_stack[input_stack_ptr].buffer_state = YY_CURRENT_BUFFER;
385       input_stack[input_stack_ptr].line = line;
386       input_stack_ptr++;
387       yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
388       line.number = 1;
389       line.include_p = 1;
390       line.file_name = safe_strdup(buf);
391     }
392     else
393       err(line, "can't open input '%s'", buf);
394   }
395   BEGIN(INITIAL);
398 <<EOF>> {
399   if (input_stack_ptr == 0) {
400     yyterminate();
401   }
402   else {
403     yy_delete_buffer(YY_CURRENT_BUFFER);
404     // don't free: refs may still exist for def locs in the symbol table
405     // safe_free(line.file_name);
406     --input_stack_ptr;
407     yy_switch_to_buffer(input_stack[input_stack_ptr].buffer_state);
408     line = input_stack[input_stack_ptr].line;
409   }
412 .       {
413   die(line, "bad char '%c' (%d)\n", yytext[0], (int)yytext[0]);
418 void set_lexer_file(char *file_name, FILE *f)
420   line.file_name = safe_strdup(file_name);
421   line.include_p = 0;
422   line.number = 1;
423   yyin = f;