13:- module(smtlib, [
14 15 smtlib_read_expression/2,
16 smtlib_read_expressions/2,
17 smtlib_read_theory/2,
18 smtlib_read_logic/2,
19 smtlib_read_script/2,
20 21 smtlib_parse_expression/2,
22 smtlib_parse_expressions/2,
23 smtlib_parse_theory/2,
24 smtlib_parse_logic/2,
25 smtlib_parse_script/2,
26 27 smtlib_write_to_stream/2,
28 smtlib_write_to_file/2
29]).
47
54smtlib_read_expression(Path, Expression) :-
55 open(Path, read, Stream),
56 stream_to_list(Stream, Chars),
57 close(Stream),
58 smtlib_parse_expression(Chars, Expression).
59
66smtlib_read_expressions(Path, Expression) :-
67 open(Path, read, Stream),
68 stream_to_list(Stream, Chars),
69 close(Stream),
70 smtlib_parse_expressions(Chars, Expression).
71
78smtlib_read_theory(Path, Theory) :-
79 open(Path, read, Stream),
80 stream_to_list(Stream, Chars),
81 close(Stream),
82 smtlib_parse_theory(Chars, Theory).
83
90smtlib_read_logic(Path, Logic) :-
91 open(Path, read, Stream),
92 stream_to_list(Stream, Chars),
93 close(Stream),
94 smtlib_parse_logic(Chars, Logic).
95
101smtlib_read_script(Path, Script) :-
102 open(Path, read, Stream),
103 stream_to_list(Stream, Chars),
104 close(Stream),
105 smtlib_parse_script(Chars, Script).
106
113smtlib_parse_expression(Chars, Expression) :- s_expr(Expression, Chars, []).
114
121smtlib_parse_expressions(Chars, Expression) :- s_exprs(Expression, Chars, []).
122
129smtlib_parse_theory(Chars, Theory) :- theory_decl(Theory, Chars, []).
130
137smtlib_parse_logic(Chars, Logic) :- logic(Logic, Chars, []).
138
144smtlib_parse_script(Chars, Script) :- script(Script, Chars, []).
145
151smtlib_write_to_stream(Stream, numeral(N)) :- !, write(Stream, N), write(Stream, ' ').
152smtlib_write_to_stream(Stream, decimal(D)) :- !, write(Stream, D), write(Stream, ' ').
153smtlib_write_to_stream(Stream, hexadecimal(H)) :- !, write(Stream, H), write(Stream, ' ').
154smtlib_write_to_stream(Stream, binary(B)) :- !, write(Stream, B), write(Stream, ' ').
155smtlib_write_to_stream(Stream, symbol(S)) :- !, write(Stream, S), write(Stream, ' ').
156smtlib_write_to_stream(Stream, reserved(R)) :- !, write(Stream, R), write(Stream, ' ').
157smtlib_write_to_stream(Stream, keyword(K)) :- !, write(Stream, ':'), write(Stream, K), write(Stream, ' ').
158smtlib_write_to_stream(Stream, string(S)) :- !,
159 write(Stream, '"'),
160 write(Stream, S),
161 write(Stream, '"'),
162 write(Stream, ' ').
163smtlib_write_to_stream(Stream, list(Expr)) :- !,
164 maplist(smtlib_write_to_stream(Stream), Expr).
165smtlib_write_to_stream(Stream, Expr) :-
166 is_list(Expr), !,
167 write(Stream, '('),
168 maplist(smtlib_write_to_stream(Stream), Expr),
169 writeln(Stream, ')').
170
176smtlib_write_to_file(Path, SMTLIB) :-
177 open(Path, write, Stream),
178 smtlib_write_to_stream(Stream, SMTLIB),
179 close(Stream).
180
181
182
184
190stream_to_list(Stream, []) :-
191 at_end_of_stream(Stream), !.
192stream_to_list(Stream, [Char|Input]) :-
193 get_code(Stream, Code),
194 char_code(Char, Code),
195stream_to_list(Stream, Input).
196
197
198
201
--> [X], {X \= '\n'}, !, comment.
206comment --> [].
207
210whitespace --> [' '].
211whitespace --> ['\t'].
212whitespace --> ['\n'].
213whitespace --> ['\r'].
214whitespace --> [';'], comment, ['\n'], !.
215whitespace([';'|Xs],[]) :- comment(Xs,[]).
216
217whitespaces --> whitespace, !, whitespaces.
218whitespaces --> [].
219
220lpar --> ['('], whitespaces.
221rpar --> [')'], whitespaces.
222
224numeral(numeral(Y)) --> digits([X|Xs]), {(Xs = [] ; X \= '0'), number_chars(Y, [X|Xs])}, whitespaces.
225
226numerals([X|Xs]) --> numeral(X), !, numerals(Xs).
227numerals([]) --> [].
228
229digits([X|Xs]) --> [X], {char_code(X, C), C >= 48, C =< 57}, !, digits(Xs).
230digits([]) --> [].
231
233decimal(decimal(D)) -->
234 digits([X|Xs]),
235 {(Xs = [] ; X \= '0')},
236 ['.'], digits(Y),
237 {append([X|Xs], ['.'|Y], Z),
238 number_chars(D, Z)},
239 whitespaces.
240
243hexadecimal(hexadecimal(Y)) --> ['#','x'], hexadecimal_digits(X), {X \= [], atom_chars(Y, X)}, whitespaces.
244
245hexadecimal_digits([X|Xs]) --> [X],
246 {member(X, ['0','1','2','3','4','5','6','7','8','9',a,b,c,d,e,f,'A','B','C','D','E','F'])}, !,
247 hexadecimal_digits(Xs).
248hexadecimal_digits([]) --> [].
249
251binary(binary(Y)) --> ['#','b'], binary_digits(X), {X \= [], atom_chars(Y, X)}, whitespaces.
252
253binary_digits([X|Xs]) --> [X], {member(X, ['0','1'])}, !, binary_digits(Xs).
254binary_digits([]) --> [].
255
261string(string(Y)) --> ['"'], quoted(X), ['"'], {atom_chars(Y, X)}, whitespaces.
262
263quoted([X|Xs]) --> printable_character(X), {X \= '"'}, !, quoted(Xs).
264quoted([X|Xs]) --> [X], {member(X, [' ','\n','\r','\t'])}, !, quoted(Xs).
265quoted(['"'|Xs]) --> ['"','"'], !, quoted(Xs).
266quoted([]) --> [].
267
268printable_character(X) --> [X], {char_code(X, C), (C >= 32, C =< 126 ; C >= 128)}.
269
273reserved_word(X) :- member(X, [
274 par, 'BINARY', 'HEXADECIMAL', 'NUMERAL', 'DECIMAL', 'STRING', '_', '!', as,
275 let, forall, exists, match, 'set-logic', 'set-option', 'set-info', 'declare-sort',
276 'define-sort', 'declare-fun', push, pop, assert, 'check-sat', 'get-assertions',
277 'get-proof', 'get-unsat-core', 'get-value', 'get-assignment', 'get-info', exit,
278 'check-sat-assuming', 'declare-const', 'declare-datatype', 'declare-datatypes',
279 'define-fun', 'define-fun-rec', 'define-funs-rec', echo, 'get-model', 'get-option',
280 'get-unsat-assumptions', reset, 'reset-assertions', 'set-option'
281]).
282
283reserved_word(reserved(Y)) -->
284 symbol_chars([X|Xs]),
285 {atom_chars(Y, [X|Xs]),
286 reserved_word(Y)},
287 whitespaces.
288
294symbol(X) --> simple_symbol(X).
295symbol(X) --> quoted_symbol(X).
296
297symbols([X|Xs]) --> symbol(X), !, symbols(Xs).
298symbols([]) --> [].
299
300simple_symbol(symbol(Y)) -->
301 symbol_chars([X|Xs]),
302 {\+member(X, ['0','1','2','3','4','5','6','7','8','9']),
303 atom_chars(Y, [X|Xs]),
304 \+reserved_word(Y)},
305 whitespaces.
306
307symbol_chars([X|Xs]) --> [X],
308 {member(X, ['~','!','@','$','%','^','&','*','_','-','+','=','<','>','.','?','/']) ;
309 (char_code(X, C), C >= 48, C =< 57) ;
310 (char_code(X, C), C >= 97, C =< 122) ;
311 (char_code(X, C), C >= 65, C =< 90)}, !,
312 symbol_chars(Xs).
313symbol_chars([]) --> [].
314
315quoted_symbol(symbol(Y)) --> ['|'], quoted_symbol_chars(X), ['|'], {atom_chars(Y, X)}, whitespaces.
316
317quoted_symbol_chars([X|Xs]) --> printable_character(X), {X \= '|', X \= '\\'}, !, quoted_symbol_chars(Xs).
318quoted_symbol_chars([X|Xs]) --> [X], {member(X, [' ','\n','\r','\t'])}, !, quoted_symbol_chars(Xs).
319quoted_symbol_chars([]) --> [].
320
323keyword(keyword(Y)) --> [':'], symbol_chars(X), {X \= [], atom_chars(Y, X)}, whitespaces.
324
325
326
328
332spec_constant(X) --> decimal(X), !.
333spec_constant(X) --> numeral(X), !.
334spec_constant(X) --> hexadecimal(X), !.
335spec_constant(X) --> binary(X), !.
336spec_constant(X) --> string(X), !.
337
338s_expr(X) --> whitespaces, s_expr2(X).
339s_expr2(X) --> spec_constant(X), !.
340s_expr2(X) --> symbol(X), !.
341s_expr2(X) --> reserved_word(X), !.
342s_expr2(X) --> keyword(X), !.
343s_expr2(X) --> lpar, s_exprs(X), whitespaces, rpar.
344
345s_exprs([X|Xs]) --> s_expr(X), !, s_exprs(Xs).
346s_exprs([]) --> [].
347
348
349
351
354identifier([reserved('_'),X|Xs]) --> lpar, ['_'], whitespaces, symbol(X), indices(Xs), {Xs \= []}, rpar.
355identifier(X) --> symbol(X).
356
357index(X) --> numeral(X).
358index(X) --> symbol(X).
359
360indices([X|Xs]) --> index(X), !, indices(Xs).
361indices([]) --> [].
362
363
365
368attribute_value(X) --> spec_constant(X), !.
369attribute_value(X) --> symbol(X), !.
370attribute_value(Xs) --> lpar, s_exprs(Xs), rpar.
371
372attribute([X,Xs]) --> keyword(X), attribute_value(Xs), !.
373attribute(X) --> keyword(X).
374
375attributes([X|Xs]) --> attribute(X), !, attributes(Xs).
376attributes([]) --> [].
377
378
380
383sort([X|Xs]) --> lpar, identifier(X), sorts(Xs), {Xs \= []}, rpar.
384sort(X) --> identifier(X).
385
386sorts([X|Xs]) --> sort(X), sorts(Xs).
387sorts([]) --> [].
388
389
390
392
397qual_identifier(X) --> identifier(X).
398qual_identifier([reserved(as),X,Y]) --> lpar, [a,s], whitespaces, identifier(X), sort(Y), rpar.
399
400var_binding([X,Y]) --> lpar, symbol(X), term(Y), rpar.
401var_bindings([X|Xs]) --> var_binding(X), !, var_bindings(Xs).
402var_bindings([]) --> [].
403
404sorted_var([X,Y]) --> lpar, symbol(X), sort(Y), rpar.
405sorted_vars([X|Xs]) --> sorted_var(X), !, sorted_vars(Xs).
406sorted_vars([]) --> [].
407
408pattern([X|Xs]) --> lpar, !, symbol(X), symbols(Xs), {Xs \= []}, rpar.
409pattern(X) --> symbol(X).
410
411match_case([X,Y]) --> lpar, pattern(X), term(Y), rpar.
412match_cases([X|Xs]) --> match_case(X), !, match_cases(Xs).
413match_cases([]) --> [].
414
415term(X) --> spec_constant(X).
416term(X) --> qual_identifier(X).
417term([X|Xs]) --> lpar, qual_identifier(X), terms(Xs), {Xs \= []}, rpar.
418term([reserved(let), Xs, X]) --> lpar, reserved_word(reserved(let)), lpar, var_bindings(Xs), {Xs \= []}, rpar, term(X), rpar.
419term([reserved(Y), Xs, X]) --> lpar, reserved_word(reserved(Y)), {member(Y, [forall, exists])}, lpar, sorted_vars(Xs), {Xs \= []}, rpar, term(X), rpar.
420term([reserved(match), Xs]) --> lpar, reserved_word(reserved(match)), lpar, match_cases(Xs), {Xs \= []}, rpar, rpar.
421term([reserved('!'),X|Xs]) --> lpar, reserved_word(reserved('!')), term(X), attributes(Xs), {Xs \= []}, rpar.
422
423terms([X|Xs]) --> term(X), !, terms(Xs).
424terms([]) --> [].
425
426
427
429
435sort_symbol_decl([X,Y|Z]) --> lpar, identifier(X), numeral(Y), attributes(Z), rpar.
436sort_symbol_decls([X|Xs]) --> sort_symbol_decl(X), !, sort_symbol_decls(Xs).
437sort_symbol_decls([]) --> [].
438
439meta_spec_constant(reserved(X)) --> reserved_word(reserved(X)), {member(X, ['NUMERAL','DECIMAL','STRING'])}.
440
441fun_symbol_decl([X,Y|Z]) --> lpar, spec_constant(X), sort(Y), attributes(Z), rpar.
442fun_symbol_decl([X,Y|Z]) --> lpar, meta_spec_constant(X), sort(Y), attributes(Z), rpar.
443fun_symbol_decl([X|YZ]) --> lpar, identifier(X), sorts(Y), {Y \= []}, attributes(Z), rpar, {append(Y, Z, YZ)}.
444
445par_fun_symbol_decl(X) --> fun_symbol_decl(X).
446par_fun_symbol_decl([reserved(par), X, [Y|ZW]]) -->
447 lpar, reserved_word(reserved(par)),
448 lpar, symbols(X), {X \= []}, rpar,
449 lpar, identifier(Y), sorts(Z), {Z \= []},
450 attributes(W), rpar,
451 rpar, {append(Z, W, ZW)}.
452
453par_fun_symbol_decls([X|Xs]) --> par_fun_symbol_decl(X), !, par_fun_symbol_decls(Xs).
454par_fun_symbol_decls([]) --> [].
455
456theory_attribute([keyword(sorts),Xs]) --> keyword(keyword(sorts)), lpar, sort_symbol_decls(Xs), {Xs \= []}, rpar, !.
457theory_attribute([keyword(funs),Xs]) --> keyword(keyword(funs)), lpar, par_fun_symbol_decls(Xs), {Xs \= []}, rpar, !.
458theory_attribute([keyword(X),Y]) --> keyword(keyword(X)), {member(X,['sorts-description','funs-description',definition,values,notes])}, string(Y), !.
459theory_attribute(X) --> attribute(X), !.
460
461theory_attributes([X|Xs]) --> theory_attribute(X), !, theory_attributes(Xs).
462theory_attributes([]) --> [].
463
464theory_decl(list([symbol(theory),X|Y])) --> whitespaces, lpar, symbol(symbol(theory)), symbol(X), theory_attributes(Y), {Y \= []}, rpar.
465
466
467
469
473logic_attribute([keyword(theories),Xs]) --> keyword(keyword(theories)), lpar, symbols(Xs), {Xs \= []}, rpar, !.
474logic_attribute([keyword(X),Y]) --> keyword(keyword(X)), {member(X,[language,extensions,values,notes])}, string(Y), !.
475logic_attribute(X) --> attribute(X).
476
477logic_attributes([X|Xs]) --> logic_attribute(X), !, logic_attributes(Xs).
478logic_attributes([]) --> [].
479
480logic(list([symbol(logic),X|Xs])) --> whitespaces, lpar, symbol(symbol(logic)), symbol(X), logic_attributes(Xs), {Xs \= []}, rpar.
481
482
483
485
488
489sort_dec([X,Y]) --> lpar, symbol(X), numeral(Y), rpar.
490sort_decs([X|Xs]) --> sort_dec(X), !, sort_decs(Xs).
491sort_decs([]) --> [].
492
493selector_dec([X,Y]) --> lpar, symbol(X), sort(Y), rpar.
494selector_decs([X|Xs]) --> selector_dec(X), !, selector_decs(Xs).
495selector_decs([]) --> [].
496
497constructor_dec([X|Xs]) --> lpar, symbol(X), selector_decs(Xs), rpar.
498constructor_decs([X|Xs]) --> constructor_dec(X), !, constructor_decs(Xs).
499constructor_decs([]) --> [].
500
501datatype_dec(Xs) --> lpar, constructor_decs(Xs), {Xs \= []}, rpar.
502datatype_dec([reserved(par),X,Y]) --> lpar, reserved_word(reserved(par)),
503 lpar, symbols(X), {X \= []}, rpar,
504 lpar, constructor_decs(Y), {Y \= []}, rpar, rpar.
505datatype_decs([X|Xs]) --> datatype_dec(X), !, datatype_decs(Xs).
506datatype_decs([]) --> [].
507
508function_dec([X,Y,Z]) --> lpar, symbol(X), lpar, sorted_vars(Y), rpar, sort(Z), rpar.
509function_decs([X|Xs]) --> function_dec(X), !, function_decs(Xs).
510function_decs([]) --> [].
511
512function_def([X,Y,Z,W]) --> symbol(X), lpar, sorted_vars(Y), rpar, sort(Z), term(W).
513
514prop_literal([symbol(not),X]) --> lpar, symbol(symbol(not)), symbol(X), rpar.
515prop_literal(X) --> symbol(X).
516prop_literals([X|Xs]) --> prop_literal(X), !, prop_literals(Xs).
517prop_literals([]) --> [].
518
519command([reserved('check-sat-assuming'),X]) --> lpar, reserved_word(reserved('check-sat-assuming')), lpar, prop_literals(X), rpar, rpar.
520command([reserved('declare-const'),X,Y]) --> lpar, reserved_word(reserved('declare-const')), symbol(X), sort(Y), rpar.
521command([reserved('declare-datatype'),X,Y]) --> lpar, reserved_word(reserved('declare-datatype')), symbol(X), datatype_dec(Y), rpar.
522command([reserved('declare-datatypes'),X,Y]) --> lpar, reserved_word(reserved('declare-datatypes')),
523 lpar, sort_decs(X), rpar, lpar, datatype_decs(Y), {length(X,Length), length(Y,Length), Length > 0}, rpar, rpar.
524command([reserved('set-logic'),X]) --> lpar, reserved_word(reserved('set-logic')), symbol(X), rpar.
525command([reserved('set-option')|X]) --> lpar, reserved_word(reserved('set-option')), option(X), rpar.
526command([reserved('set-info'),X]) --> lpar, reserved_word(reserved('set-info')), attribute(X), rpar.
527command([reserved('declare-sort'),X,Y]) --> lpar, reserved_word(reserved('declare-sort')), symbol(X), numeral(Y), rpar.
528command([reserved('define-sort'),X,Y,Z]) --> lpar, reserved_word(reserved('define-sort')), symbol(X), lpar, symbols(Y), rpar, sort(Z), rpar.
529command([reserved('declare-fun'),X,Y,Z]) --> lpar, reserved_word(reserved('declare-fun')), symbol(X), lpar, sorts(Y), rpar, sort(Z), rpar.
530command([reserved('define-fun'),X,Y,Z,W]) --> lpar, reserved_word(reserved('define-fun')), function_def([X,Y,Z,W]), rpar.
531command([reserved('define-fun-rec'),X,Y,Z,W]) --> lpar, reserved_word(reserved('define-fun-rec')), function_def([X,Y,Z,W]), rpar.
532command([reserved('define-funs-rec'),X,Y]) --> lpar, reserved_word(reserved('define-funs-rec')),
533 lpar, function_decs(X), rpar, lpar, terms(Y), {length(X,Length), length(Y,Length), Length > 0}, rpar, rpar.
534command([reserved(push),X]) --> lpar, reserved_word(reserved(push)), numeral(X), rpar.
535command([reserved(pop),X]) --> lpar, reserved_word(reserved(pop)), numeral(X), rpar.
536command([reserved(assert),X]) --> lpar, reserved_word(reserved(assert)), term(X), rpar.
537command([reserved(X)]) --> lpar, reserved_word(reserved(X)), {member(X,['check-sat','get-model','get-assertions','get-proof','get-unsat-core','get-assignment','get-unsat-assumptions',exit,reset,'reset-assertions'])}, rpar.
538command([reserved('get-value'),Xs]) --> lpar, reserved_word(reserved('get-value')), lpar, terms(Xs), {Xs \= []}, rpar, rpar.
539command([reserved('get-option'),X]) --> lpar, reserved_word(reserved('get-option')), keyword(X), rpar.
540command([reserved('get-info'),X]) --> lpar, reserved_word(reserved('get-info')), info_flag(X), rpar.
541command([reserved(echo),X]) --> lpar, reserved_word(reserved(echo)), string(X), rpar.
542
543script(list(X)) --> whitespaces, script2(X).
544script2([X|Xs]) --> command(X), !, script2(Xs).
545script2([]) --> [].
546
550b_value(symbol(X)) --> symbol(symbol(X)), {member(X, [true,false])}.
551
552option([keyword(X),Y]) --> keyword(keyword(X)), {member(X,['global-declarations','print-success','interactive-mode','produce-proofs','produce-unsat-cores','produce-models','produce-assignments','produce-assertions','produce-unsat-assumptions'])}, b_value(Y).
553option([keyword('diagnostic-output-channel'),X]) --> keyword(keyword('diagnostic-output-channel')), string(X).
554option([keyword('random-seed'),X]) --> keyword(keyword('random-seed')), numeral(X).
555option([keyword('verbosity'),X]) --> keyword(keyword('verbosity')), numeral(X).
556option([keyword('reproducible-resource-limit'),X]) --> keyword(keyword('reproducible-resource-limit')), numeral(X).
557option([keyword('regular-output-channel'),X]) --> keyword(keyword('regular-output-channel')), string(X).
558option([X]) --> attribute(X).
559
563info_flag(keyword(X)) --> keyword(keyword(X)), {member(X,['error-behavior',name,authors,version,'reason-unknown','all-statistics','assertion-stack-lavels'])}, !.
564info_flag(X) --> keyword(X)