diff options
Diffstat (limited to 'lib/scanner.l')
-rw-r--r-- | lib/scanner.l | 202 |
1 files changed, 202 insertions, 0 deletions
diff --git a/lib/scanner.l b/lib/scanner.l new file mode 100644 index 0000000..21c1271 --- /dev/null +++ b/lib/scanner.l @@ -0,0 +1,202 @@ +/* -*- mode: C -*- */ +/* -------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2020 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + <http://www.gnu.org/licenses/>. + ---------------------------------------------------------------------------- +*/ + +%option nounistd +%option never-interactive +%option reentrant +%option noyywrap +%option yylineno +%option nounput +%option bison-bridge +%option header-file="scanner.h" +%option outfile="lex.yy.c" +%option extra-type="struct scan_context *" + +%{ + +#ifdef _MSC_VER +#pragma warning (disable: 4996) +#endif + +#include <stdlib.h> +#include <errno.h> +#include <ctype.h> +#include <string.h> +#include <limits.h> + +#include "parsectx.h" +#include "scanctx.h" +#include "grammar.h" +#include "wincompat.h" +#include "util.h" + +#define YY_NO_INPUT // Suppress generation of useless input() function + +%} + +true [Tt][Rr][Uu][Ee] +false [Ff][Aa][Ll][Ss][Ee] +name [A-Za-z\*][-A-Za-z0-9_\*]* +integer [-+]?[0-9]+ +integer64 [-+]?[0-9]+L(L)? +hex 0[Xx][0-9A-Fa-f]+ +hex64 0[Xx][0-9A-Fa-f]+L(L)? +hexchar \\[Xx][0-9A-Fa-f]{2} +float ([-+]?([0-9]*)?\.[0-9]*([eE][-+]?[0-9]+)?)|([-+]?([0-9]+)(\.[0-9]*)?[eE][-+]?[0-9]+) +include_open ^[ \t]*@include[ \t]+\" + +%x SINGLE_LINE_COMMENT MULTI_LINE_COMMENT STRING INCLUDE + +%% + +(#|\/\/) { BEGIN SINGLE_LINE_COMMENT; } +<SINGLE_LINE_COMMENT>\n { BEGIN INITIAL; } +<SINGLE_LINE_COMMENT>. { /* ignore */ } + +\/\* { BEGIN MULTI_LINE_COMMENT; } +<MULTI_LINE_COMMENT>\*\/ { BEGIN INITIAL; } +<MULTI_LINE_COMMENT>. { /* ignore */ } +<MULTI_LINE_COMMENT>\n { /* ignore */ } + +\" { BEGIN STRING; } +<STRING>[^\"\\]+ { libconfig_scanctx_append_string(yyextra, yytext); } +<STRING>\\n { libconfig_scanctx_append_char(yyextra, '\n'); } +<STRING>\\r { libconfig_scanctx_append_char(yyextra, '\r'); } +<STRING>\\t { libconfig_scanctx_append_char(yyextra, '\t'); } +<STRING>\\f { libconfig_scanctx_append_char(yyextra, '\f'); } +<STRING>\\\\ { libconfig_scanctx_append_char(yyextra, '\\'); } +<STRING>\\\" { libconfig_scanctx_append_char(yyextra, '\"'); } +<STRING>{hexchar} { + char c = (char)(strtol(yytext + 2, NULL, 16) & 0xFF); + libconfig_scanctx_append_char(yyextra, c); + } +<STRING>\\ { libconfig_scanctx_append_char(yyextra, '\\'); } +<STRING>\" { + yylval->sval = libconfig_scanctx_take_string(yyextra); + BEGIN INITIAL; + return(TOK_STRING); + } + +{include_open} { BEGIN INCLUDE; } +<INCLUDE>[^\"\\]+ { libconfig_scanctx_append_string(yyextra, yytext); } +<INCLUDE>\\\\ { libconfig_scanctx_append_char(yyextra, '\\'); } +<INCLUDE>\\\" { libconfig_scanctx_append_char(yyextra, '\"'); } +<INCLUDE>\" { + const char *error = NULL; + const char *path = libconfig_scanctx_take_string(yyextra); + FILE *fp = libconfig_scanctx_push_include(yyextra, (void *)YY_CURRENT_BUFFER, + path, &error); + __delete(path); + + if(fp) + { + yyin = fp; + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner), + yyscanner); + } + else if(error) + { + yyextra->config->error_text = error; + yyextra->config->error_file = libconfig_scanctx_current_filename(yyextra); + yyextra->config->error_line = libconfig_yyget_lineno(yyscanner); + return TOK_ERROR; + } + BEGIN INITIAL; +} + +\n|\r|\f { /* ignore */ } +[ \t]+ { /* ignore */ } + +\=|\: { return(TOK_EQUALS); } +, { return(TOK_COMMA); } +\{ { return(TOK_GROUP_START); } +\} { return(TOK_GROUP_END); } +{true} { yylval->ival = 1; return(TOK_BOOLEAN); } +{false} { yylval->ival = 0; return(TOK_BOOLEAN); } +{name} { yylval->sval = yytext; return(TOK_NAME); } +{float} { yylval->fval = atof(yytext); return(TOK_FLOAT); } +{integer} { + int ok; + long long llval = libconfig_parse_integer(yytext, &ok); + if(!ok) + return(TOK_ERROR); + + if((llval < INT_MIN) || (llval > INT_MAX)) + { + yylval->llval = llval; + return(TOK_INTEGER64); + } + else + { + yylval->ival = (int)llval; + return(TOK_INTEGER); + } + } +{integer64} { yylval->llval = atoll(yytext); return(TOK_INTEGER64); } +{hex} { + yylval->ival = strtoul(yytext, NULL, 16); + return(TOK_HEX); + } +{hex64} { + yylval->llval = libconfig_parse_hex64(yytext); + return(TOK_HEX64); + } +\[ { return(TOK_ARRAY_START); } +\] { return(TOK_ARRAY_END); } +\( { return(TOK_LIST_START); } +\) { return(TOK_LIST_END); } +; { return(TOK_SEMICOLON); } +. { return(TOK_GARBAGE); } + +<<EOF>> { + const char *error = NULL; + FILE *fp; + + fp = libconfig_scanctx_next_include_file(yyextra, &error); + if(fp) + { + yyin = fp; + yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner); + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner), + yyscanner); + } + else if(error) + { + yyextra->config->error_text = error; + yyextra->config->error_file = libconfig_scanctx_current_filename(yyextra); + yyextra->config->error_line = libconfig_yyget_lineno(yyscanner); + return TOK_ERROR; + } + else + { + /* No more files in the current include list. */ + YY_BUFFER_STATE buf = (YY_BUFFER_STATE)libconfig_scanctx_pop_include(yyextra); + if(buf) + { + yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner); + yy_switch_to_buffer(buf, yyscanner); + } + else + yyterminate(); + } +} |