diff --git a/fzn-parser/README b/fzn-parser/README new file mode 100644 index 0000000..5a0170e --- /dev/null +++ b/fzn-parser/README @@ -0,0 +1,5 @@ +AST nodes for fzn parser + +lit(TYPE, VALUE) + +TYPE = bool diff --git a/fzn-parser/flatzinc.l b/fzn-parser/flatzinc.l index d7a1ab2..1e295dc 100644 --- a/fzn-parser/flatzinc.l +++ b/fzn-parser/flatzinc.l @@ -1,4 +1,9 @@ -/* Lexer for FlatZinc. +/* == 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 @@ -40,15 +45,15 @@ float_literal -?[0-9]+\.[0-9]+|-?[0-9]+\.[0-9]+[Ee][-+]?[0-9]+|-?[0-9]+[Ee][- /* Attributed tokens */ {ident} { - yylval.string_val = strdup(yytext); + yylval.id = strdup(yytext); return IDENT; } {underscore_ident} { - yylval.string_val = strdup(yytext); + yylval.id = strdup(yytext); return UNDERSCORE_IDENT; } {string_literal} { - yylval.string_val = strdup(yytext); + yylval.lit.sval = strdup(yytext); return STRING_LITERAL; } {int_literal} { @@ -77,7 +82,7 @@ float_literal -?[0-9]+\.[0-9]+|-?[0-9]+\.[0-9]+[Ee][-+]?[0-9]+|-?[0-9]+[Ee][- } i++; } - yylval.int_val = x; + yylval.lit.ival = x; } else if ('0' == yytext[0] && 'o' == yytext[1]) { int i = 2, x = 0; @@ -86,15 +91,15 @@ float_literal -?[0-9]+\.[0-9]+|-?[0-9]+\.[0-9]+[Ee][-+]?[0-9]+|-?[0-9]+[Ee][- x += (yytext[i] - '0'); i++; } - yylval.int_val = x; + yylval.lit.ival = x; } else { - yylval.int_val = atoi(yytext); + yylval.lit.ival = atoi(yytext); } return INT_LITERAL; } {float_literal} { - yylval.float_val = atof(yytext); + yylval.lit.rval = atof(yytext); return FLOAT_LITERAL; } diff --git a/fzn-parser/flatzinc.y b/fzn-parser/flatzinc.y index 566b6f2..755508c 100644 --- a/fzn-parser/flatzinc.y +++ b/fzn-parser/flatzinc.y @@ -21,28 +21,36 @@ #define AST(pop, push) \ { \ - if (pop) \ - printf ("[%s|_Tail] ==> [", pop); \ - else \ - printf ("_Tail ==> ["); \ + printf ("[%s|_T] -> [", pop); \ printf push; \ - printf ("|_Tail].\n"); \ + printf ("|_T].\n"); \ +} + +#define INIT(x) \ +{ \ + printf ("_ -> %s.\n", x); \ } #define PUSH(x) \ { \ - printf ("_Tail ==> ["); \ + printf ("_T -> ["); \ printf x; \ - printf ("|_Tail].\n"); \ + printf ("|_T].\n"); \ } -#define CONS() AST ("T,H", ("[H|T]")) -#define CONS_SWAPPED() AST ("H,T", ("[H|T]")) + // pop an item and a list, push new list (CONS) +#define CONS() AST ("H,T", ("[H|T]")) + // pop one thing, push it as a 1-element list #define TAIL() AST ("T", ("[T]")) + + // push the empty list #define NIL() PUSH (("[]")) + // pop one thing, push an open-ended list headed with that thing #define TAIL_OPEN() AST ("T", ("[T|_]")) + + // push an unbound variable #define NIL_OPEN() PUSH (("_")) #define BINARY(op) AST ("B,A", ("op(A,B)")) @@ -73,17 +81,21 @@ // caused stack overflows on large models. The error recovery isn't great, // but it's better than none. -model : pred_decl_items var_decl_items constraint_items model_end +model : { INIT ("[]"); } + pred_decl_items { AST ("X", ("preds(X)")); } + var_decl_items { AST ("X", ("vars(X)")); } + constraint_items { AST ("X", ("constrs(X)")); } + model_end -pred_decl_items : pred_decl_items pred_decl_item ';' - | pred_decl_items error ';' { yyerrok; } - | /* empty */ +pred_decl_items : pred_decl_items pred_decl_item ';' { CONS (); } + | pred_decl_items error ';' { yyerrok; } + | /* empty */ { NIL (); } -var_decl_items : var_decl_items var_decl_item ';' - | /* empty */ +var_decl_items : var_decl_items var_decl_item ';' { CONS (); } + | /* empty */ { NIL (); } -constraint_items: constraint_items constraint_item ';' - | /* empty */ +constraint_items: constraint_items constraint_item ';' { CONS (); } + | /* empty */ { NIL (); } model_end : solve_item ';' @@ -118,6 +130,7 @@ ident_anns: constraint_item: CONSTRAINT constraint_elem annotations + { AST ("A, C", ("constraint(C, A)")); } constraint_elem: IDENT '(' exprs ')' @@ -165,20 +178,20 @@ scalar_ti_expr_tail: | float_ti_expr_tail bool_ti_expr_tail: - BOOL + BOOL { PUSH (("bool")); } int_ti_expr_tail: - INT - | INT_LITERAL DOTDOT INT_LITERAL - | '{' int_literals '}' + INT { PUSH (("int")); } + | INT_LITERAL DOTDOT INT_LITERAL { PUSH (("int(%d,%d)", $1, $3)); } + | '{' int_literals '}' { AST ("Ls", ("int(Ls)")); } int_literals: - INT_LITERAL ',' int_literals - | INT_LITERAL + INT_LITERAL ',' int_literals { AST ("Ls, L", ("[L|Ls]")); } + | INT_LITERAL { PUSH (("[%d]", $1)); } float_ti_expr_tail: - FLOAT - | FLOAT_LITERAL DOTDOT FLOAT_LITERAL + FLOAT { PUSH (("float")); } + | FLOAT_LITERAL DOTDOT FLOAT_LITERAL { PUSH (("float(%g,%g)", $1, $3)); } set_ti_expr_tail: SET OF int_ti_expr_tail @@ -193,26 +206,28 @@ exprs: expr: bool_literal - | INT_LITERAL - | FLOAT_LITERAL - | STRING_LITERAL + | INT_LITERAL { PUSH (("lit(int, %d)", $1)); } + | FLOAT_LITERAL { PUSH (("lit(float, %g)", $1)); } + | STRING_LITERAL { PUSH (("lit(string, \"%s\")", $1)); } | set_literal | array_literal | array_access_expr - | IDENT + | IDENT { PUSH (("lit(float, %g)", $1)); } | UNDERSCORE_IDENT | IDENT '(' exprs ')' /* An annotation value with > 0 arguments. */ -bool_literal: FALSE | TRUE +bool_literal: + FALSE { PUSH (("lit(bool, false)")); } + | TRUE { PUSH (("lit(bool, true)")); } set_literal: - '{' exprs '}' - | '{' '}' - | INT_LITERAL DOTDOT INT_LITERAL + '{' exprs '}' { AST ("Es", ("lit(set(_), Es)")); } + | '{' '}' { PUSH (("lit(set(_), [])")); } + | INT_LITERAL DOTDOT INT_LITERAL { PUSH (("lit(set(%d, %d)", $1, $3)); } array_literal: - '[' exprs ']' - | '[' ']' + '[' exprs ']' { AST ("Es", ("alit(Es)")); } + | '[' ']' { PUSH (("alit([])")); } array_access_expr: IDENT '[' INT_LITERAL ']' | UNDERSCORE_IDENT '[' INT_LITERAL ']' @@ -222,8 +237,8 @@ array_access_expr: IDENT '[' INT_LITERAL ']' //--------------------------------------------------------------------------- annotations: - COLONCOLON expr annotations - | /* empty */ + COLONCOLON expr annotations { CONS (); } + | /* empty */ { NIL (); } %% -- libgit2 0.21.2