/* MeTA1 configuration lexer for GNU Pies. -*- c -*- */
%option nounput
%option noinput
%top {
/* MeTA1 configuration lexer for GNU Pies.
Copyright (C) 2008, 2009, 2010, 2011, 2013 Sergey Poznyakoff
GNU Pies 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, or (at your option)
any later version.
GNU Pies 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 GNU Pies. If not, see . */
/* This file implements a lexical analyzer for MeTA1 main configuration file.
*/
#ifdef HAVE_CONFIG_H
# include
#endif
}
%{
#include "pies.h"
#include "grecs-locus.h"
#include "meta1gram.h"
#include "meta1lex.h"
static struct grecs_locus_point meta1_locus_point;
static struct grecs_txtacc *meta1_txtacc;
char *meta1_queue_dir;
#define yylval meta1lval
#define YY_USER_ACTION do \
{ \
if (YYSTATE == 0) \
{ \
meta1lloc.beg = meta1_locus_point; \
meta1lloc.beg.col++; \
} \
meta1_locus_point.col += yyleng; \
meta1lloc.end = meta1_locus_point; \
} \
while (0);
%}
%x COMMENT STR
X [0-9a-fA-F]
%%
/* C-style comments */
"/*" BEGIN (COMMENT);
[^*\n]* /* eat anything that's not a '*' */
"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
\n grecs_locus_point_advance_line(meta1_locus_point);
"*"+"/" BEGIN (INITIAL);
/* End-of-line comments */
#.*\n grecs_locus_point_advance_line(meta1_locus_point);
#.* /* end-of-file comment */;
/* Number */
0[xX]{X}+ |
0[0-7]+ |
[1-9][0-9]+ { meta1_line_begin ();
meta1_line_add (yytext, yyleng);
yylval.string = meta1_line_finish ();
return META1_NUMBER; }
/* Identifiers (unquoted strings) */
[a-zA-Z0-9_\./:\*-]+ { meta1_line_begin ();
meta1_line_add (yytext, yyleng);
yylval.string = meta1_line_finish ();
return META1_IDENT; }
/* Quoted strings */
\"[^\\"\n]*\" { meta1_line_begin ();
meta1_line_add (yytext + 1, yyleng - 2);
yylval.string = meta1_line_finish ();
return META1_STRING; }
\"[^\\"\n]*\\x{X}{1,2} { BEGIN(STR);
meta1_line_begin ();
meta1_line_add_unescape_hex (yytext + 1, yyleng - 1);
}
\"[^\\"\n]*\\. { BEGIN(STR);
meta1_line_begin ();
meta1_line_add_unescape_last (yytext + 1, yyleng - 1); }
[^\\"\n]*\\x{X}{1,2} { meta1_line_add_unescape_hex (yytext, yyleng); }
[^\\"\n]*\\. { meta1_line_add_unescape_last (yytext, yyleng); }
[^\\"\n]*\" { BEGIN (INITIAL);
if (yyleng > 1)
meta1_line_add (yytext, yyleng - 1);
yylval.string = meta1_line_finish ();
return META1_STRING; }
[^\\"\n]*\n { BEGIN (INITIAL);
grecs_error (&meta1lloc, 0, _("newline in a string"));
meta1_line_add (yytext, yyleng - 1);
yylval.string = meta1_line_finish ();
return META1_STRING; }
/* Other tokens */
[ \t\f][ \t\f]* ;
\n grecs_locus_point_advance_line(meta1_locus_point);
[,;{}=] return yytext[0];
. { if (isascii (yytext[0]) && isprint (yytext[0]))
grecs_error (&meta1lloc, 0, _("stray character %c"), yytext[0]);
else
grecs_error (&meta1lloc, 0, _("stray character \\%03o"),
(unsigned char) yytext[0]); }
%%
int
yywrap ()
{
return 1;
}
void
meta1_line_add (const char *text, size_t len)
{
grecs_txtacc_grow (meta1_txtacc, text, len);
}
static char quote_transtab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
static int
unescape_char (int c)
{
char *p;
for (p = quote_transtab; *p; p += 2)
{
if (*p == c)
return p[1];
}
return c;
}
static void
unescape_to_line (int c)
{
char t;
if (c == 'v')
t = '\v';
else
{
t = unescape_char (c);
if (t == c && t != '\\' && t != '\"')
grecs_error (&meta1lloc, 0, _("unknown escape sequence '\\%c'"), c);
}
grecs_txtacc_grow_char (meta1_txtacc, t);
}
void
meta1_line_add_unescape_last (const char *text, size_t len)
{
grecs_txtacc_grow (meta1_txtacc, text, len - 2);
unescape_to_line (text[len - 1]);
}
void
meta1_line_add_unescape_hex (const char *text, size_t len)
{
for (; text[len-1] != 'x' && len > 0; len--)
;
grecs_txtacc_grow (meta1_txtacc, text, len - 2);
grecs_txtacc_grow_char (meta1_txtacc, (char) strtoul (text + len, NULL, 16));
}
void
meta1_line_begin ()
{
if (!meta1_txtacc)
meta1_txtacc = grecs_txtacc_create();
}
char *
meta1_line_finish ()
{
grecs_txtacc_grow_char (meta1_txtacc, 0);
return grecs_txtacc_finish (meta1_txtacc, 0);
}
char *
meta1_string (const char *str, size_t len)
{
meta1_line_begin ();
meta1_line_add (str, len);
return meta1_line_finish ();
}
void
meta1_lexer_set_debug ()
{
char *p = getenv ("META1_DEBUG_LEX");
yy_flex_debug = p && (*p - '0') > 0;
}
/* Parse MeTA1 configuration file `name'. Populate `meta1_parse_tree' with
the parse tree. */
int
meta1_config_parse (const char *name)
{
int rc;
FILE *fp;
fp = fopen (name, "r");
if (!fp)
{
logmsg (LOG_ERR,
_("%s: cannot open file: %s"), name, strerror (errno));
return 1;
}
meta1_locus_point.file = meta1_string (name, strlen (name));
meta1_locus_point.line = 1;
meta1_locus_point.col = 0;
meta1_lexer_set_debug ();
meta1_parser_set_debug ();
yyrestart (fp);
grecs_error_count = 0;
rc = meta1parse ();
fclose (fp);
if (grecs_error_count)
rc = 1;
return rc;
}