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)
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 */
34 #if defined(_WIN32) && !defined fileno
35 #define fileno(F) _fileno(F)
36 #pragma warning(disable:4102)
39 // undo the safety net in polygon.h so flex scanner can use these library functions
47 #define MAX_INPUT_DEPTH 10
50 YY_BUFFER_STATE buffer_state;
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)
61 for (i = 0; yytext[i]; i++)
62 if (yytext[i] == '\n')
70 Identifier [A-Za-z]([A-Za-z0-9_]*[A-Za-z0-9])?
76 [%#].* /* comment; do nothing */
78 {WSnotNL}+ /* white space; do nothing */
84 "["[^\]=]+=[^\]]+"]" { /* [<stuff>=<stuff>] */
86 yylval.str = safe_malloc(yyleng + 1 - 2);
87 str_slice(yylval.str, yyleng + 1 - 2, yytext, 1, -1);
112 update_line_number();
113 BEGIN(inputdirective);
169 update_line_number();
174 update_line_number();
179 update_line_number();
187 "perspective"{WS}*"(" {
188 update_line_number();
193 update_line_number();
198 update_line_number();
203 update_line_number();
208 update_line_number();
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);
225 err(line, "expected special text, found end of file");
228 while ((ch = input()) != delim && ch != EOF) {
231 if (i == max_rtn_len) {
233 rtn = safe_realloc(rtn, max_rtn_len + 1);
238 err(line, "missing end delimeter '%c' in special", delim);
246 update_line_number();
250 "translate"{WS}*"(" {
251 update_line_number();
256 update_line_number();
261 update_line_number();
266 str_slice(yylval.name, sizeof yylval.name, yytext, 0, sizeof yylval.name);
271 str_slice(yylval.name, sizeof yylval.name, yytext, 1, -1);
280 update_line_number();
286 update_line_number();
292 update_line_number();
298 str_slice(yylval.name, sizeof yylval.name, yytext, 1, -1);
303 str_slice(yylval.name, sizeof yylval.name, yytext, 1, -1);
307 "[["{Identifier}"]]" {
308 str_slice(yylval.name, sizeof yylval.name, yytext, 2, -2);
309 return DBL_BRACKET_ID;
313 str_slice(yylval.name, sizeof yylval.name, yytext, 1, -1);
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);
325 "("{WS}*{Identifier}{WS}*")" {
326 warn(line, "found parenthesized identifier '%s'; delete space if you meant a point ref", yytext);
331 "["{WS}*{Identifier}{WS}*"]" {
332 warn(line, "found id in brackets '%s'; delete space if you meant a vector ref", yytext);
337 "{"{WS}*{Identifier}{WS}*"}" {
338 warn(line, "found id in braces '%s'; delete space if you meant a drawable ref", yytext);
343 "[["{WS}*{Identifier}{WS}*"]]" {
344 warn(line, "found id in double-brackets '%s'; delete space if you meant a transform ref", yytext);
349 "<"{WS}*{Identifier}{WS}*">" {
350 warn(line, "found id in angle-brackets '%s'; delete space if you meant a tag ref", yytext);
355 [-+*/^|.()\[\]{}=,] {
359 <inputdirective>"{"[^}]*"}" {
365 if (line.file_name[0] != '/' && line.file_name[0] != '\\')
366 i = str_last_occurance(line.file_name, "/\\");
368 str_slice(buf, sizeof buf, line.file_name, 0, i + 1);
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);
384 input_stack[input_stack_ptr].buffer_state = YY_CURRENT_BUFFER;
385 input_stack[input_stack_ptr].line = line;
387 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
390 line.file_name = safe_strdup(buf);
393 err(line, "can't open input '%s'", buf);
399 if (input_stack_ptr == 0) {
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);
407 yy_switch_to_buffer(input_stack[input_stack_ptr].buffer_state);
408 line = input_stack[input_stack_ptr].line;
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);