%{ /* TikZiT - a GUI diagram editor for TikZ Copyright (C) 2018 Aleks Kissinger, Chris Heunen, K. Johan Paulsson, Alex Merry This program 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 of the License, or (at your option) any later version. This program 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 this program. If not, see . */ /*! * \file tikzlexer.l * * The lexer for tikz input. */ #include "tikzparserdefs.h" #include "tikzparser.parser.hpp" #include #define YY_USER_ACTION \ yylloc->first_line = yylloc->last_line; \ yylloc->first_column = yylloc->last_column + 1; \ yylloc->last_column = yylloc->first_column + yyleng - 1; %} %option reentrant bison-bridge bison-locations 8bit %option bison-locations 8bit %option nounput %option yylineno %option noyywrap %option header-file="tikzlexer.h" %option extra-type="TikzAssembler *" %s props %s xcoord %s ycoord %s noderef FLOAT \-?[0-9]*(\.[0-9]+)? %% /* whitespace is ignored, except for position counting; we don't count formfeed and vtab as whitespace, because it's not obvious how they should be dealt with and no-one actually uses them */ /* lex will take the longest-matching string */ \r\n|\r|\n { yylloc->first_line += 1; yylloc->last_line = yylloc->first_line; yylloc->first_column = yylloc->last_column = 0; } [\t ]+ { } %.*$ { } \\begin\{tikzpicture\} { return BEGIN_TIKZPICTURE_CMD; } \\end\{tikzpicture\} { return END_TIKZPICTURE_CMD; } \\tikzstyle { return TIKZSTYLE_CMD; } \\begin\{pgfonlayer\} { return BEGIN_PGFONLAYER_CMD; } \\end\{pgfonlayer\} { return END_PGFONLAYER_CMD; } \\draw { return DRAW_CMD; } \\node { return NODE_CMD; } \\path { return PATH_CMD; } ; { return SEMICOLON; } = { return EQUALS; } rectangle { return RECTANGLE; } node { return NODE; } at { return AT; } to { return TO; } cycle { return CYCLE; } \([ ]*{FLOAT}[ ]*,[ ]*{FLOAT}[ ]*\) { yylloc->last_column = yylloc->first_column + 1; yyless(1); BEGIN(xcoord); } {FLOAT} { yylval->pt = new QPointF(); QString s(yytext); yylval->pt->setX(s.toDouble()); BEGIN(ycoord); } , { } {FLOAT} { QString s(yytext); yylval->pt->setY(s.toDouble()); } \) { BEGIN(INITIAL); return TCOORD; } /* when we see "[", change parsing mode */ \[ /*syntaxhlfix]*/ { BEGIN(props); return LEFTBRACKET; } = { return EQUALS; } , { return COMMA; } /* technically, it is possible to have newlines in the middle of property names or values, but in practice this is unlikely and screws up our line counting */ [^=,\{\] \t\n]([^=,\{\]\n]*[^=,\{\] \t\n])? { char *str = (char*)malloc(sizeof(char)*yyleng + 1); strncpy(str, yytext, yyleng + 1); yylval->str = str; return PROPSTRING; } \] { BEGIN(INITIAL); return RIGHTBRACKET; } \( { BEGIN(noderef); return LEFTPARENTHESIS; } \. { return FULLSTOP; } /* we assume node names (and anchor names) never contain newlines */ [^\.\{\)\n]+ { //qDebug() << "nodename: " << yytext << " size: " << strlen(yytext); char *str = (char*)malloc(sizeof(char)*yyleng + 1); strncpy(str, yytext, yyleng+1); yylval->str = str; return REFSTRING; } \) { BEGIN(INITIAL); return RIGHTPARENTHESIS; } \{ { std::stringstream buf; unsigned int brace_depth = 1; unsigned int escape = 0; while (1) { char c = yyinput(yyscanner); // eof reached before closing brace if (c == '\0' || c == EOF) { return UNCLOSED_DELIM_STR; } yylloc->last_column += 1; yyleng += 1; if (escape) { escape = 0; } else if (c == '\\') { escape = 1; } else if (c == '{') { brace_depth++; } else if (c == '}') { brace_depth--; if (brace_depth == 0) break; } else if (c == '\n') { yylloc->last_line += 1; yylloc->last_column = 0; } buf << c; } char *str = (char*)malloc(sizeof(char) * yyleng + 1); strncpy(str, buf.str().c_str(), yyleng + 1); //str[len] = 0; yylval->str = str; //qDebug() << "got delim string: " << str; return DELIMITEDSTRING; } \\begin { return UNKNOWN_BEGIN_CMD; } \\end { return UNKNOWN_END_CMD; } \\[a-zA-Z0-9]+ { return UNKNOWN_CMD; } [a-zA-Z0-9]+ { return UNKNOWN_STR; } . { return UNKNOWN_STR; } /* vi:ft=lex:noet:ts=4:sts=4:sw=4: */