flatzinc.l
3.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* == Prolog AST-stream term Scanner for FlatZinc =============================
*
* (C) 2015 Salvador Abreu
*
* ----------------------------------------------------------------------------
* Based on the Lexer for FlatZinc.
* Nick Nethercote, started May 2007.
*
* This file is in the public domain, and can be used without copyright
* restrictions.
*/
%{
#include <string.h>
%}
/* Regular expressions for attributed tokens. */
ident [A-Za-z][A-Za-z0-9_]*
underscore_ident _*[A-Za-z][A-Za-z0-9_]*
string_literal \"[^"\n]*\"
int_literal -?[0-9]+|-?0x[0-9A-Fa-f]+|-?0o[0-7]+
float_literal -?[0-9]+\.[0-9]+|-?[0-9]+\.[0-9]+[Ee][-+]?[0-9]+|-?[0-9]+[Ee][-+]?[0-9]+
%%
/* Reserved words */
"array" { return ARRAY; }
"bool" { return BOOL; }
"constraint" { return CONSTRAINT;}
"false" { return FALSE; }
"float" { return FLOAT; }
"int" { return INT; }
"minimize" { return MINIMIZE; }
"maximize" { return MAXIMIZE; }
"of" { return OF; }
"predicate" { return PREDICATE; }
"satisfy" { return SATISFY; }
"set" { return SET; }
"solve" { return SOLVE; }
"true" { return TRUE; }
"var" { return VAR; }
\.\. { return DOTDOT; }
:: { return COLONCOLON;}
/* Attributed tokens */
{ident} {
yylval.id = strdup(yytext);
return IDENT;
}
{underscore_ident} {
yylval.id = strdup(yytext);
return UNDERSCORE_IDENT;
}
{string_literal} {
yylval.lit.sval = strdup(yytext);
return STRING_LITERAL;
}
{int_literal} {
/*
** atoi() doesn't recognise our hex and octal numbers, so we must
** handle them ourselves.
**
** XXX: this code doesn't detect if the integer literals overflow an
** 'int'. (In particular, 'atoi' doesn't detect overflow errors,
** but 'strtol' does, so that could be used for the decimal integer
** case.)
**
** XXX: I think this code will incorrectly parse negative octal and
** hexadecimal numbers -- the two conditions will fail due to the
** leading '-', so 'atoi' will be invoked, which will fail, and
** yylval.int_val will be set to something bogus (probably zero).
*/
if ('0' == yytext[0] && 'x' == yytext[1]) {
int i = 2, x = 0;
while ('\0' != yytext[i]) {
x *= 16;
if ('0' <= yytext[i] && yytext[i] <= '9') {
x += (yytext[i] - '0');
} else {
x += (yytext[i] - 'a' + 10);
}
i++;
}
yylval.lit.ival = x;
} else if ('0' == yytext[0] && 'o' == yytext[1]) {
int i = 2, x = 0;
while ('\0' != yytext[i]) {
x *= 8;
x += (yytext[i] - '0');
i++;
}
yylval.lit.ival = x;
} else {
yylval.lit.ival = atoi(yytext);
}
return INT_LITERAL;
}
{float_literal} {
yylval.lit.rval = atof(yytext);
return FLOAT_LITERAL;
}
/* Skip newlines, whitespace and comments, return any non-matched
* character. */
\n ;
[ \t] ;
%.* ;
. { return yytext[0]; }
%%