root/library/bdm/base/libconfig/scanner.l @ 652

Revision 248, 5.6 kB (checked in by smidl, 15 years ago)

doc

Line 
1/* -*- mode: C -*- */
2/* --------------------------------------------------------------------------
3   libconfig - A library for processing structured configuration files
4   Copyright (C) 2005-2008  Mark A Lindner
5 
6   This file is part of libconfig.
7   
8   This library is free software; you can redistribute it and/or
9   modify it under the terms of the GNU Lesser General Public License
10   as published by the Free Software Foundation; either version 2.1 of
11   the License, or (at your option) any later version.
12   
13   This library is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16   Lesser General Public License for more details.
17   
18   You should have received a copy of the GNU Library General Public
19   License along with this library; if not, see
20   <http://www.gnu.org/licenses/>.
21   ----------------------------------------------------------------------------
22*/
23
24%{
25#define YY_EXTRA_TYPE void*
26%}
27
28%option nounistd
29%option reentrant
30%option noyywrap
31%option yylineno
32%option nounput
33%option bison-bridge
34%option header-file="scanner.h"
35%option outfile="lex.yy.c"
36
37%{
38
39#ifdef _MSC_VER
40#pragma warning (disable: 4996)
41#endif
42
43#include <stdlib.h>
44#include <ctype.h>
45#include <string.h>
46#include "grammar.h"
47#include "wincompat.h"
48
49/* this is somewhat kludgy, but I wanted to avoid building strings
50  dynamically during scanning */
51
52static char *make_string(char *s)
53{
54  char *r = ++s;
55  char *p, *q = r;
56  size_t len = strlen(r);
57  int esc = 0;
58
59  *(r + --len) = 0;
60
61  for(p = r; *p; p++)
62  {
63    if(*p == '\\')
64    {
65      if(! esc)
66      {
67        esc = 1;
68        continue;
69      }
70    }
71     
72    if(esc)
73    {
74      if(*p == 'n')
75        *(q++) = '\n';
76      else if(*p == 'r')
77        *(q++) = '\r';
78      else if(*p == 'f')
79        *(q++) = '\f';
80      else if(*p == 't')
81        *(q++) = '\t';
82      else
83        *(q++) = *p;
84
85      esc = 0;
86    }
87   
88    else if(*p == '\"') /* if we reached the end of a string segment, ... */
89    {
90       /* This construction allows for C-style string concatenation.
91          We don't bother to check for end-of-string here, as we depend
92          on the {string} definition to ensure a new opening quote exists.
93          We do, however, check for and discard all forms of comments
94          [that is, (#...$|//...$|[/][*]...[*][/])] between string segments. */
95
96      while (*++p != '\"') /* ... look for the start of the next segment */
97      {
98        if(*p == '#') /* check for #...$ comment */
99        {
100          while(*++p != '\n') 
101          {
102            /* skip the rest of the line */
103          }
104        }
105        else if (*p == '/')
106        {
107          if(*++p == '/') /* check for //...$ comment */
108          {
109            while (*++p != '\n') 
110            {
111              /* skip the rest of the line */
112            }
113          }
114          else /* must be '*', lead-in to an old C-style comment */
115          {
116            while (*++p != '*' || *(p+1) != '/')
117            {
118              /* skip all comment content */
119            }
120            ++p; /* step to the trailing slash, to skip it as well */
121          }
122        }
123      }
124    }
125    else
126      *(q++) = *p;
127  }
128
129  *q = 0;
130
131  return(r);
132}
133
134static unsigned long long fromhex(const char *s)
135{
136#ifdef __MINGW32__
137
138  // MinGW's strtoull() seems to be broken; it only returns the lower
139  // 32 bits...
140
141  const char *p = s;
142  unsigned long long val = 0;
143
144  if(*p != '0')
145    return(0);
146
147  ++p;
148
149  if(*p != 'x' && *p != 'X')
150    return(0);
151
152  for(++p; isxdigit(*p); ++p)
153  {
154    val <<= 4;
155    val |= ((*p < 'A') ? (*p & 0xF) : (9 + (*p & 0x7)));
156  }
157 
158  return(val); 
159
160#else // ! __MINGW32__
161
162  return(strtoull(s, NULL, 16));
163 
164#endif // __MINGW32__
165}
166
167%}
168
169ws               [ \t\f\r\n]+
170equals           \=|\:
171comma            ,
172group_start      \{
173group_end        \}
174true             [Tt][Rr][Uu][Ee]
175false            [Ff][Aa][Ll][Ss][Ee]
176name             [A-Za-z\*][-A-Za-z0-9_\*]*
177quote            \"
178integer          [-+]?[0-9]+
179integer64        [-+]?[0-9]+L(L)?
180hex              0[Xx][0-9A-Fa-f]+
181hex64            0[Xx][0-9A-Fa-f]+L(L)?
182float            ([-+]?([0-9]*)?\.[0-9]*([eE][-+]?[0-9]+)?)|([-+]?([0-9]+)(\.[0-9]*)?[eE][-+]?[0-9]+)
183segment          {quote}([^\"\\]|\\.)*{quote}
184string           {segment}(([ \t\f\r\n]*((#|\/\/).*\n|\/\*(.|\n)*\*\/)*)*{segment})*
185end              ;
186array_start      \[
187array_end        \]
188list_start       \(
189list_end         \)
190comment          (#|\/\/).*$
191
192%x COMMENT
193
194%%
195
196\/\*          { BEGIN COMMENT; }
197<COMMENT>\*\/ { BEGIN INITIAL; }
198<COMMENT>.    { /* ignore */ }
199<COMMENT>\n   {  }
200
201{ws}          { /* skip */ }
202
203{equals}      { return(TOK_EQUALS); }
204{comma}       { return(TOK_COMMA); }
205{group_start} { return(TOK_GROUP_START); }
206{group_end}   { return(TOK_GROUP_END); }
207{true}        { yylval->ival = 1; return(TOK_BOOLEAN); }
208{false}       { yylval->ival = 0; return(TOK_BOOLEAN); }
209{name}        { yylval->sval = strdup(yytext); return(TOK_NAME); }
210{float}       { yylval->fval = atof(yytext); return(TOK_FLOAT); }
211{integer}     { yylval->ival = atoi(yytext); return(TOK_INTEGER); }
212{integer64}   { yylval->llval = atoll(yytext); return(TOK_INTEGER64); }
213{hex}         { yylval->ival = strtoul(yytext, NULL, 16); return(TOK_HEX); }
214{hex64}       { yylval->llval = fromhex(yytext); return(TOK_HEX64); }
215{string}      { yylval->sval = strdup(make_string(yytext)); return(TOK_STRING); }
216{array_start} { return(TOK_ARRAY_START); }
217{array_end}   { return(TOK_ARRAY_END); }
218{list_start}  { return(TOK_LIST_START); }
219{list_end}    { return(TOK_LIST_END); }
220{end}         { return(TOK_END); }
221{comment}     { /* ignore */ }
222.             { return(TOK_GARBAGE); }
Note: See TracBrowser for help on using the browser.