Commit 25820b21715ce6cfbb2528f8eb487b17502489c6
1 parent
5564dda3
Exists in
master
added flatzinc parser from minizinc 1.6 distrib
Showing
4 changed files
with
387 additions
and
0 deletions
Show diff stats
@@ -0,0 +1 @@ | @@ -0,0 +1 @@ | ||
1 | +flatzinc.output flatzinc.tab.c lex.yy.c fzp |
@@ -0,0 +1,39 @@ | @@ -0,0 +1,39 @@ | ||
1 | +EXEEXT= | ||
2 | + | ||
3 | +EXE_FILE = fzp$(EXEEXT) | ||
4 | +SRC = | ||
5 | +OBJ = flatzinc.tab.o | ||
6 | +GENCFILES = flatzinc.tab.c lex.yy.c | ||
7 | +OTHER = flatzinc.output | ||
8 | + | ||
9 | +# NOTE: we need to pass the `-l' flag to ensure the scanner internal | ||
10 | +# variable `yylineno' is available. | ||
11 | +# | ||
12 | +LEX = flex | ||
13 | +LEXFLAGS = -l | ||
14 | +LEXLIB = | ||
15 | + | ||
16 | +YACC = bison | ||
17 | +YACCFLAGS = -v | ||
18 | + | ||
19 | +CC = gcc | ||
20 | +CFLAGS = -g -O | ||
21 | +RM = /bin/rm -f | ||
22 | + | ||
23 | +$(EXE_FILE): $(OBJ) | ||
24 | + $(CC) $(CFLAGS) -o $(EXE_FILE) $(OBJ) $(LEXLIB) | ||
25 | + | ||
26 | +flatzinc.tab.c: flatzinc.y lex.yy.c | ||
27 | + $(YACC) $(YACCFLAGS) flatzinc.y | ||
28 | + | ||
29 | +lex.yy.c: flatzinc.l | ||
30 | + $(LEX) $(LEXFLAGS) flatzinc.l | ||
31 | + | ||
32 | +clean: | ||
33 | + $(RM) $(OBJ) $(GENCFILES) $(OTHER) core | ||
34 | + | ||
35 | +clobber: clean | ||
36 | + $(RM) $(EXE_FILE) | ||
37 | + | ||
38 | +.PHONY: distclean | ||
39 | +distclean: clobber |
@@ -0,0 +1,109 @@ | @@ -0,0 +1,109 @@ | ||
1 | +/* Lexer for FlatZinc. | ||
2 | + * Nick Nethercote, started May 2007. | ||
3 | + * | ||
4 | + * This file is in the public domain, and can be used without copyright | ||
5 | + * restrictions. | ||
6 | + */ | ||
7 | + | ||
8 | +%{ | ||
9 | +#include <string.h> | ||
10 | +%} | ||
11 | + | ||
12 | + /* Regular expressions for attributed tokens. */ | ||
13 | +ident [A-Za-z][A-Za-z0-9_]* | ||
14 | +underscore_ident _*[A-Za-z][A-Za-z0-9_]* | ||
15 | +string_literal \"[^"\n]*\" | ||
16 | +int_literal -?[0-9]+|-?0x[0-9A-Fa-f]+|-?0o[0-7]+ | ||
17 | +float_literal -?[0-9]+\.[0-9]+|-?[0-9]+\.[0-9]+[Ee][-+]?[0-9]+|-?[0-9]+[Ee][-+]?[0-9]+ | ||
18 | + | ||
19 | +%% | ||
20 | + | ||
21 | + /* Reserved words */ | ||
22 | +"array" { return ARRAY; } | ||
23 | +"bool" { return BOOL; } | ||
24 | +"constraint" { return CONSTRAINT;} | ||
25 | +"false" { return FALSE; } | ||
26 | +"float" { return FLOAT; } | ||
27 | +"int" { return INT; } | ||
28 | +"minimize" { return MINIMIZE; } | ||
29 | +"maximize" { return MAXIMIZE; } | ||
30 | +"of" { return OF; } | ||
31 | +"predicate" { return PREDICATE; } | ||
32 | +"satisfy" { return SATISFY; } | ||
33 | +"set" { return SET; } | ||
34 | +"solve" { return SOLVE; } | ||
35 | +"true" { return TRUE; } | ||
36 | +"var" { return VAR; } | ||
37 | + | ||
38 | +\.\. { return DOTDOT; } | ||
39 | +:: { return COLONCOLON;} | ||
40 | + | ||
41 | + /* Attributed tokens */ | ||
42 | +{ident} { | ||
43 | + yylval.string_val = strdup(yytext); | ||
44 | + return IDENT; | ||
45 | + } | ||
46 | +{underscore_ident} { | ||
47 | + yylval.string_val = strdup(yytext); | ||
48 | + return UNDERSCORE_IDENT; | ||
49 | +} | ||
50 | +{string_literal} { | ||
51 | + yylval.string_val = strdup(yytext); | ||
52 | + return STRING_LITERAL; | ||
53 | + } | ||
54 | +{int_literal} { | ||
55 | + /* | ||
56 | + ** atoi() doesn't recognise our hex and octal numbers, so we must | ||
57 | + ** handle them ourselves. | ||
58 | + ** | ||
59 | + ** XXX: this code doesn't detect if the integer literals overflow an | ||
60 | + ** 'int'. (In particular, 'atoi' doesn't detect overflow errors, | ||
61 | + ** but 'strtol' does, so that could be used for the decimal integer | ||
62 | + ** case.) | ||
63 | + ** | ||
64 | + ** XXX: I think this code will incorrectly parse negative octal and | ||
65 | + ** hexadecimal numbers -- the two conditions will fail due to the | ||
66 | + ** leading '-', so 'atoi' will be invoked, which will fail, and | ||
67 | + ** yylval.int_val will be set to something bogus (probably zero). | ||
68 | + */ | ||
69 | + if ('0' == yytext[0] && 'x' == yytext[1]) { | ||
70 | + int i = 2, x = 0; | ||
71 | + while ('\0' != yytext[i]) { | ||
72 | + x *= 16; | ||
73 | + if ('0' <= yytext[i] && yytext[i] <= '9') { | ||
74 | + x += (yytext[i] - '0'); | ||
75 | + } else { | ||
76 | + x += (yytext[i] - 'a' + 10); | ||
77 | + } | ||
78 | + i++; | ||
79 | + } | ||
80 | + yylval.int_val = x; | ||
81 | + | ||
82 | + } else if ('0' == yytext[0] && 'o' == yytext[1]) { | ||
83 | + int i = 2, x = 0; | ||
84 | + while ('\0' != yytext[i]) { | ||
85 | + x *= 8; | ||
86 | + x += (yytext[i] - '0'); | ||
87 | + i++; | ||
88 | + } | ||
89 | + yylval.int_val = x; | ||
90 | + | ||
91 | + } else { | ||
92 | + yylval.int_val = atoi(yytext); | ||
93 | + } | ||
94 | + return INT_LITERAL; | ||
95 | + } | ||
96 | +{float_literal} { | ||
97 | + yylval.float_val = atof(yytext); | ||
98 | + return FLOAT_LITERAL; | ||
99 | + } | ||
100 | + | ||
101 | + /* Skip newlines, whitespace and comments, return any non-matched | ||
102 | + * character. */ | ||
103 | +\n ; | ||
104 | +[ \t] ; | ||
105 | +%.* ; | ||
106 | +. { return yytext[0]; } | ||
107 | + | ||
108 | +%% | ||
109 | + |
@@ -0,0 +1,238 @@ | @@ -0,0 +1,238 @@ | ||
1 | +// Parser for FlatZinc 1.1. | ||
2 | +// Authors: Nick Nethercote | ||
3 | +// Julien Fischer | ||
4 | +// | ||
5 | +// NOTE: the parser produced by the following grammar does not ensure | ||
6 | +// that expressions are type correct. Further type-checking after parsing | ||
7 | +// is required for this. | ||
8 | +// | ||
9 | +// This file is in the public domain, and can be used without copyright | ||
10 | +// restrictions. | ||
11 | + | ||
12 | +%{ | ||
13 | +#include <stdio.h> | ||
14 | +#include <stdlib.h> | ||
15 | +%} | ||
16 | + | ||
17 | + | ||
18 | +// Possible values for attributed tokens. | ||
19 | +%union { | ||
20 | + char* string_val; | ||
21 | + int int_val; | ||
22 | + double float_val; | ||
23 | +}; | ||
24 | + | ||
25 | +// Token kinds | ||
26 | +%token <int_val> INT_LITERAL | ||
27 | + <string_val> STRING_LITERAL IDENT UNDERSCORE_IDENT | ||
28 | + <float_val> FLOAT_LITERAL | ||
29 | + ARRAY BOOL CONSTRAINT FALSE FLOAT INT MAXIMIZE MINIMIZE OF | ||
30 | + PREDICATE SATISFY SET SOLVE TRUE VAR DOTDOT COLONCOLON | ||
31 | + | ||
32 | +%% | ||
33 | + | ||
34 | +//--------------------------------------------------------------------------- | ||
35 | +// Model top-level | ||
36 | +//--------------------------------------------------------------------------- | ||
37 | + | ||
38 | +// Nb: these rules are left-recursive, which is good for Yacc as they run in | ||
39 | +// constant stack space. Earlier versions were right-recursive, and this | ||
40 | +// caused stack overflows on large models. The error recovery isn't great, | ||
41 | +// but it's better than none. | ||
42 | + | ||
43 | +model : pred_decl_items var_decl_items constraint_items model_end | ||
44 | + | ||
45 | +pred_decl_items : pred_decl_items pred_decl_item ';' | ||
46 | + | pred_decl_items error ';' { yyerrok; } | ||
47 | + | /* empty */ | ||
48 | + | ||
49 | +var_decl_items : var_decl_items var_decl_item ';' | ||
50 | + | /* empty */ | ||
51 | + | ||
52 | +constraint_items: constraint_items constraint_item ';' | ||
53 | + | /* empty */ | ||
54 | + | ||
55 | +model_end : solve_item ';' | ||
56 | + | ||
57 | + | ||
58 | +//--------------------------------------------------------------------------- | ||
59 | +// Items | ||
60 | +//--------------------------------------------------------------------------- | ||
61 | + | ||
62 | +pred_decl_item: | ||
63 | + PREDICATE IDENT '(' pred_decl_args ')' | ||
64 | + | ||
65 | +var_decl_item: | ||
66 | + VAR non_array_ti_expr_tail ':' ident_anns var_decl_item2 | ||
67 | + | non_array_ti_expr_tail ':' ident_anns '=' expr | ||
68 | + | ARRAY '[' INT_LITERAL DOTDOT INT_LITERAL ']' OF array_decl_tail | ||
69 | + | ||
70 | +var_decl_item2: | ||
71 | + '=' expr | ||
72 | + | /*empty*/ | ||
73 | + | ||
74 | +array_decl_tail: | ||
75 | + non_array_ti_expr_tail ':' ident_anns '=' array_literal | ||
76 | + | VAR non_array_ti_expr_tail ':' ident_anns array_decl_tail2 | ||
77 | + | ||
78 | +array_decl_tail2: | ||
79 | + '=' array_literal | ||
80 | + | /*empty*/ | ||
81 | + | ||
82 | +ident_anns: | ||
83 | + IDENT annotations | ||
84 | + | UNDERSCORE_IDENT annotations | ||
85 | + | ||
86 | +constraint_item: | ||
87 | + CONSTRAINT constraint_elem annotations | ||
88 | + | ||
89 | +constraint_elem: | ||
90 | + IDENT '(' exprs ')' | ||
91 | + | ||
92 | +solve_item: | ||
93 | + SOLVE annotations solve_kind | ||
94 | + | ||
95 | +solve_kind: | ||
96 | + SATISFY | ||
97 | + | MINIMIZE expr | ||
98 | + | MAXIMIZE expr | ||
99 | + | ||
100 | +//--------------------------------------------------------------------------- | ||
101 | +// Predicate parameters | ||
102 | +//--------------------------------------------------------------------------- | ||
103 | + | ||
104 | +pred_decl_args: | ||
105 | + pred_decl_arg "," pred_decl_args | ||
106 | + | pred_decl_arg | ||
107 | + | ||
108 | +pred_decl_arg: | ||
109 | + non_array_ti_expr_tail ':' IDENT | ||
110 | + | VAR non_array_ti_expr_tail ':' IDENT | ||
111 | + | ARRAY '[' pred_arg_array_index ']' OF pred_arg_array_tail ':' IDENT | ||
112 | + | ||
113 | +pred_arg_array_index: | ||
114 | + INT | ||
115 | + | INT_LITERAL DOTDOT INT_LITERAL | ||
116 | + | ||
117 | +pred_arg_array_tail: | ||
118 | + non_array_ti_expr_tail | ||
119 | + | VAR non_array_ti_expr_tail | ||
120 | + | ||
121 | +//--------------------------------------------------------------------------- | ||
122 | +// Type-Inst Expression Tails | ||
123 | +//--------------------------------------------------------------------------- | ||
124 | + | ||
125 | +non_array_ti_expr_tail: | ||
126 | + scalar_ti_expr_tail | ||
127 | + | set_ti_expr_tail | ||
128 | + | ||
129 | +scalar_ti_expr_tail: | ||
130 | + bool_ti_expr_tail | ||
131 | + | int_ti_expr_tail | ||
132 | + | float_ti_expr_tail | ||
133 | + | ||
134 | +bool_ti_expr_tail: | ||
135 | + BOOL | ||
136 | + | ||
137 | +int_ti_expr_tail: | ||
138 | + INT | ||
139 | + | INT_LITERAL DOTDOT INT_LITERAL | ||
140 | + | '{' int_literals '}' | ||
141 | + | ||
142 | +int_literals: | ||
143 | + INT_LITERAL ',' int_literals | ||
144 | + | INT_LITERAL | ||
145 | + | ||
146 | +float_ti_expr_tail: | ||
147 | + FLOAT | ||
148 | + | FLOAT_LITERAL DOTDOT FLOAT_LITERAL | ||
149 | + | ||
150 | +set_ti_expr_tail: | ||
151 | + SET OF int_ti_expr_tail | ||
152 | + | ||
153 | +//--------------------------------------------------------------------------- | ||
154 | +// Expressions | ||
155 | +//--------------------------------------------------------------------------- | ||
156 | + | ||
157 | +exprs: | ||
158 | + expr ',' exprs | ||
159 | + | expr | ||
160 | + | ||
161 | +expr: | ||
162 | + bool_literal | ||
163 | + | INT_LITERAL | ||
164 | + | FLOAT_LITERAL | ||
165 | + | STRING_LITERAL | ||
166 | + | set_literal | ||
167 | + | array_literal | ||
168 | + | array_access_expr | ||
169 | + | IDENT | ||
170 | + | UNDERSCORE_IDENT | ||
171 | + | IDENT '(' exprs ')' /* An annotation value with > 0 arguments. */ | ||
172 | + | ||
173 | +bool_literal: FALSE | TRUE | ||
174 | + | ||
175 | +set_literal: | ||
176 | + '{' exprs '}' | ||
177 | + | '{' '}' | ||
178 | + | INT_LITERAL DOTDOT INT_LITERAL | ||
179 | + | ||
180 | +array_literal: | ||
181 | + '[' exprs ']' | ||
182 | + | '[' ']' | ||
183 | + | ||
184 | +array_access_expr: IDENT '[' INT_LITERAL ']' | ||
185 | + | UNDERSCORE_IDENT '[' INT_LITERAL ']' | ||
186 | + | ||
187 | +//--------------------------------------------------------------------------- | ||
188 | +// Annotations | ||
189 | +//--------------------------------------------------------------------------- | ||
190 | + | ||
191 | +annotations: | ||
192 | + COLONCOLON expr annotations | ||
193 | + | /* empty */ | ||
194 | + | ||
195 | +%% | ||
196 | + | ||
197 | +#include "lex.yy.c" | ||
198 | + | ||
199 | +char* filename; | ||
200 | + | ||
201 | +int main(int argc, char *argv[]) | ||
202 | +{ | ||
203 | + if (argc != 2) { | ||
204 | + fprintf(stderr, "Usage: %s <file.fzn>\n", argv[0]); | ||
205 | + exit(1); | ||
206 | + } | ||
207 | + | ||
208 | + filename = argv[1]; | ||
209 | + yyin = fopen(filename, "r"); | ||
210 | + if (yyin == NULL) { | ||
211 | + fprintf(stderr, "cannot open file: '%s'\n", filename); | ||
212 | + exit(1); | ||
213 | + } | ||
214 | + | ||
215 | + yyparse(); | ||
216 | + return 0; | ||
217 | +} | ||
218 | + | ||
219 | +int yyerror(char *s) | ||
220 | +{ | ||
221 | + if (0 == strcmp(yytext, "")) { | ||
222 | + fprintf(stderr, | ||
223 | + "%s:%d: %s before end of file\n", filename, yylineno, s); | ||
224 | + } else { | ||
225 | + fprintf(stderr, | ||
226 | + "%s:%d: %s before '%s'\n", filename, yylineno, s, yytext); | ||
227 | + } | ||
228 | + return 0; | ||
229 | +} | ||
230 | + | ||
231 | +/* | ||
232 | +** This is only defined so the Flex library isn't needed. | ||
233 | +*/ | ||
234 | +int yywrap() | ||
235 | +{ | ||
236 | + return 1; | ||
237 | +} | ||
238 | + |