aboutsummaryrefslogtreecommitdiff
path: root/lib/scanner.l
diff options
context:
space:
mode:
Diffstat (limited to 'lib/scanner.l')
-rw-r--r--lib/scanner.l202
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();
+ }
+}