/* Scanner for config specs -*- C -*- */
%option 8bit never-interactive yylineno
%option bison-bridge bison-locations
%option reentrant noyywrap
%option warn nodefault
%option outfile="lex.yy.c" prefix="augl_"
%option noinput nounput
%top{
/* config.h must precede flex's inclusion of <stdio.h>
in order for its _GNU_SOURCE definition to take effect. */
#include <config.h>
}
%{
#include "syntax.h"
#include "errcode.h"
typedef struct info YYLTYPE;
#define YYLTYPE_IS_DECLARED 1
#include "parser.h"
/* Advance of NUM lines. */
# define LOCATION_LINES(Loc, Num) \
(Loc).last_column = 0; \
(Loc).last_line += Num;
/* Restart: move the first cursor to the last position. */
# define LOCATION_STEP(Loc) \
(Loc).first_column = (Loc).last_column; \
(Loc).first_line = (Loc).last_line;
/* The lack of reference counting for filename is intentional */
#define YY_USER_ACTION \
do { \
yylloc->last_column += yyleng; \
yylloc->filename = augl_get_info(yyscanner)->filename; \
yylloc->error = augl_get_info(yyscanner)->error; \
} while(0);
#define YY_USER_INIT LOCATION_STEP(*yylloc)
#define YY_EXTRA_TYPE struct state *
int augl_init_lexer(struct state *state, yyscan_t * scanner);
void augl_close_lexer(yyscan_t *scanner);
struct info *augl_get_info(yyscan_t yyscanner);
static void loc_update(YYLTYPE *yylloc, const char *s, int len) {
for (int i=0; i < len; i++) {
if (s[i] == '\n') {
LOCATION_LINES(*yylloc, 1);
}
}
}
static char *regexp_literal(const char *s, int len) {
char *u = unescape(s, len, RX_ESCAPES);
if (u == NULL)
return NULL;
size_t u_len = strlen(u);
regexp_c_locale(&u, &u_len);
return u;
}
%}
DIGIT [0-9]
UID [A-Z][A-Za-z0-9_]*
LID [a-z_][A-Za-z0-9_]*
LETREC let[ \t]+rec
WS [ \t\n]
QID {UID}\.{LID}
ARROW ->
%s COMMENT
%%
<*>
{
[ \t]* LOCATION_STEP(*yylloc);
\n+ LOCATION_LINES(*yylloc, yyleng); LOCATION_STEP(*yylloc);
(\r\n)+ LOCATION_LINES(*yylloc, yyleng/2); LOCATION_STEP(*yylloc);
}
<INITIAL>
{
\"([^\\\"]|\\(.|\n))*\" {
loc_update(yylloc, yytext, yyleng);
yylval->string = unescape(yytext+1, yyleng-2, STR_ESCAPES);
return DQUOTED;
}
\/([^\\\/]|\\(.|\n))*\/i {
loc_update(yylloc, yytext, yyleng);
yylval->regexp.nocase = 1;
yylval->regexp.pattern = regexp_literal(yytext+1, yyleng-3);
return REGEXP;
}
\/([^\\\/]|\\(.|\n))*\/ {
loc_update(yylloc, yytext, yyleng);
yylval->regexp.nocase = 0;
yylval->regexp.pattern = regexp_literal(yytext+1, yyleng-2);
return REGEXP;
}
[|*?+()=:;\.\[\]{}-] return yytext[0];
module return KW_MODULE;
{LETREC}/{WS} return KW_LET_REC;
let return KW_LET;
string return KW_STRING;
regexp return KW_REGEXP;
lens return KW_LENS;
in return KW_IN;
autoload return KW_AUTOLOAD;
/* tests */
test return KW_TEST;
get return KW_GET;
put return KW_PUT;
after return KW_AFTER;
{ARROW} return ARROW;
{QID} {
yylval->string = strndup(yytext, yyleng);
return QIDENT;
}
{LID} {
yylval->string = strndup(yytext, yyleng);
return LIDENT;
}
{UID} {
yylval->string = strndup(yytext, yyleng);
return UIDENT;
}
\(\* {
augl_get_extra(yyscanner)->comment_depth = 1;
BEGIN(COMMENT);
}
. {
report_error(augl_get_info(yyscanner)->error, AUG_ESYNTAX,
"%s:%d:%d: Unexpected character %c",
augl_get_info(yyscanner)->filename->str,
yylineno, yylloc->first_column, yytext[0]);
}
<<EOF>> {
augl_close_lexer(yyscanner);
yyterminate();
}
}
<COMMENT>
{
\(\* {
augl_get_extra(yyscanner)->comment_depth += 1;
}
\*\) {
augl_get_extra(yyscanner)->comment_depth -= 1;
if (augl_get_extra(yyscanner)->comment_depth == 0)
BEGIN(INITIAL);
}
. /* Skip */;
<<EOF>> {
report_error(augl_get_info(yyscanner)->error, AUG_ESYNTAX,
"%s:%d:%d: Missing *)",
augl_get_info(yyscanner)->filename->str,
yylineno, yylloc->first_column);
augl_close_lexer(yyscanner);
yyterminate();
}
}
%%
void augl_close_lexer(yyscan_t *scanner) {
FILE *fp = augl_get_in(scanner);
if (fp != NULL) {
fclose(fp);
augl_set_in(NULL, scanner);
}
}
int augl_init_lexer(struct state *state, yyscan_t *scanner) {
FILE *f;
struct string *name = state->info->filename;
f = fopen(name->str, "r");
if (f == NULL)
return -1;
if (augl_lex_init(scanner) != 0) {
fclose(f);
return -1;
}
augl_set_extra(state, *scanner);
augl_set_in(f, *scanner);
return 0;
}
struct info *augl_get_info(yyscan_t scanner) {
return augl_get_extra(scanner)->info;
}