diff options
author | Jonathan McCrohan <jmccrohan@gmail.com> | 2011-12-01 22:56:23 +0000 |
---|---|---|
committer | Jonathan McCrohan <jmccrohan@gmail.com> | 2011-12-01 22:56:23 +0000 |
commit | 429e46051dba814e7d6c74368eb1bba550222cbe (patch) | |
tree | ed1dd43cd23c69f156aae2165006a16a66262cef /lib/scanner.l | |
parent | 58bf1382be0cbcf3f9649286fd2719b789a1595f (diff) | |
download | libconfig-faaa576c7d4f56a6633683e3261ae99582bf887a.tar.gz |
Imported Upstream version 1.4.8upstream/1.4.8
Diffstat (limited to 'lib/scanner.l')
-rw-r--r-- | lib/scanner.l | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/lib/scanner.l b/lib/scanner.l new file mode 100644 index 0000000..2703eb6 --- /dev/null +++ b/lib/scanner.l @@ -0,0 +1,190 @@ +/* -*- mode: C -*- */ +/* -------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 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 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 <ctype.h> +#include <string.h> +#include "grammar.h" +#include "wincompat.h" +#include "parsectx.h" +#include "scanctx.h" + +#define YY_NO_INPUT // Suppress generation of useless input() function + +static unsigned long long fromhex(const char *s) +{ +#ifdef __MINGW32__ + + /* MinGW's strtoull() seems to be broken; it only returns the lower + * 32 bits... + */ + + const char *p = s; + unsigned long long val = 0; + + if(*p != '0') + return(0); + + ++p; + + if(*p != 'x' && *p != 'X') + return(0); + + for(++p; isxdigit(*p); ++p) + { + val <<= 4; + val |= ((*p < 'A') ? (*p & 0xF) : (9 + (*p & 0x7))); + } + + return(val); + +#else /* ! __MINGW32__ */ + + return(strtoull(s, NULL, 16)); + +#endif /* __MINGW32__ */ +} + +%} + +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]+) +comment (#|\/\/).*$ +include_open ^[ \t]*@include[ \t]+\" + +%x COMMENT STRING INCLUDE + +%% + +\/\* { BEGIN COMMENT; } +<COMMENT>\*\/ { BEGIN INITIAL; } +<COMMENT>. { /* ignore */ } +<COMMENT>\n { /* ignore */ } + +\" { BEGIN STRING; } +<STRING>[^\"\\]+ { scanctx_append_string(yyextra, yytext); } +<STRING>\\n { scanctx_append_string(yyextra, "\n"); } +<STRING>\\r { scanctx_append_string(yyextra, "\r"); } +<STRING>\\t { scanctx_append_string(yyextra, "\t"); } +<STRING>\\f { scanctx_append_string(yyextra, "\f"); } +<STRING>\\\\ { scanctx_append_string(yyextra, "\\"); } +<STRING>\\\" { scanctx_append_string(yyextra, "\""); } +<STRING>{hexchar} { + char c[2] = { (char)(strtol(yytext + 2, NULL, 16) & 0xFF), + 0 }; + scanctx_append_string(yyextra, c); + } +<STRING>\" { + yylval->sval = scanctx_take_string(yyextra); + BEGIN INITIAL; + return(TOK_STRING); + } + +{include_open} { BEGIN INCLUDE; } +<INCLUDE>[^\"\\]+ { scanctx_append_string(yyextra, yytext); } +<INCLUDE>\\\\ { scanctx_append_string(yyextra, "\\"); } +<INCLUDE>\\\" { scanctx_append_string(yyextra, "\""); } +<INCLUDE>\" { + const char *error; + FILE *fp = scanctx_push_include(yyextra, + (void *)YY_CURRENT_BUFFER, + &error); + if(fp) + { + yyin = fp; + yy_switch_to_buffer( + yy_create_buffer(yyin, YY_BUF_SIZE, yyscanner), + yyscanner); + } + else + { + yyextra->config->error_text = error; + yyextra->config->error_file = 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} { yylval->ival = atoi(yytext); return(TOK_INTEGER); } +{integer64} { yylval->llval = atoll(yytext); return(TOK_INTEGER64); } +{hex} { + yylval->ival = strtoul(yytext, NULL, 16); + return(TOK_HEX); + } +{hex64} { yylval->llval = fromhex(yytext); return(TOK_HEX64); } +\[ { return(TOK_ARRAY_START); } +\] { return(TOK_ARRAY_END); } +\( { return(TOK_LIST_START); } +\) { return(TOK_LIST_END); } +; { return(TOK_SEMICOLON); } +{comment} { /* ignore */ } +. { return(TOK_GARBAGE); } + +<<EOF>> { + YY_BUFFER_STATE buf = (YY_BUFFER_STATE)scanctx_pop_include( + yyextra); + if(buf) + { + yy_delete_buffer(YY_CURRENT_BUFFER, yyscanner); + yy_switch_to_buffer(buf, yyscanner); + } + else + yyterminate(); + } |