diff options
Diffstat (limited to 'libs/cassowary/ClReader.y')
-rw-r--r-- | libs/cassowary/ClReader.y | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/libs/cassowary/ClReader.y b/libs/cassowary/ClReader.y new file mode 100644 index 0000000000..f9f0dca43e --- /dev/null +++ b/libs/cassowary/ClReader.y @@ -0,0 +1,154 @@ +/* + $Id$ + + Cassowary Incremental Constraint Solver + Original Smalltalk Implementation by Alan Borning + This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu> + http://www.cs.washington.edu/homes/gjb + (C) 1998, 1999 Greg J. Badros and Alan Borning + See ../LICENSE for legal details regarding this software + + ClReader.y + Original implementation contributed by Steve Wolfman + Subsequently largely revised by Greg J. Badros + + Supports parsing of read-only variables in constraints via "?" suffix + annotations on variables. If a variable is followed by "?" in any of + its occurrences in the constraint, that variable is deemed read-only + and entered into the constraint object as such. E.g., + + x = 2*y? + + is a one-way constraint that sets x from y's value. + + x = y + y? + and + x = y? + y + + are identical one-way constraints with y read-only. One would prefer + to have it written like so: + + x = y? + y? + + but it need not be, and no warning or error is raised. +*/ + + +%{ + /* C Declarations */ + +#include <cassowary/Cl.h> +#include <string> +#include <map> + +#ifdef HAVE_CONFIG_H +#include <config.h> +#define CONFIG_H_INCLUDED +#endif + +#ifdef USE_CRUMMY_LEXER +string current; /* Global to help in debugging/error messages */ +#endif + +/* Get yyparse, yylex to have an extra argument (type void *) */ +#define YYPARSE_PARAM cl_parse_data +#define YYLEX_PARAM cl_parse_data +#ifndef YYERROR_VERBOSE +#define YYERROR_VERBOSE +#endif +#define YYDEBUG 1 + +%} + + +/* Bison Declarations */ + +%pure_parser + +%union { + double num; + const ClVariable *pclv; + ClLinearExpression *pcle; + ClConstraint *pcn; +} + +%{ +int yylex(YYSTYPE *lvalp, void *YYLEX_PARAM); +void yyerror(const char *sz); +%} + +%start constraint + +%token <num> NUM +%token <pclv> VAR +%token <pclv> RO_VAR + +%token GEQ +%token GT +%token LEQ +%token LT + +%type <pcle> expr +%type <pcn> constraint equation inequality + +%left '-' '+' +%left '*' '/' +%left NEG + +%% +/* Grammar Rules */ + +constraint: equation { $$ = $1; ((ClParseData*)YYPARSE_PARAM)->_pcn = $1; } + | inequality { $$ = $1; ((ClParseData*)YYPARSE_PARAM)->_pcn = $1; } +; + +equation: expr '=' expr { $$ = new ClLinearEquation(*$1, *$3); } +; + +inequality: expr GEQ expr { $$ = new ClLinearInequality(*$1, cnGEQ, *$3); } + | expr LEQ expr { $$ = new ClLinearInequality(*$1, cnLEQ, *$3); } + | expr LT expr { $$ = new ClLinearInequality(*$1, cnLT, *$3); } + | expr GT expr { $$ = new ClLinearInequality(*$1, cnGT, *$3); } +; + +expr: NUM { $$ = new ClLinearExpression($1); } + | VAR { $$ = new ClLinearExpression(*$1); } + | RO_VAR { $$ = new ClLinearExpression(*$1); + ((ClParseData*)YYPARSE_PARAM)->_readOnlyVarsSoFar.insert(*$1); } + | expr '+' expr { $$ = new ClLinearExpression(*$1 + *$3); } + | expr '-' expr { $$ = new ClLinearExpression(*$1 - *$3); } + | expr '*' expr { $$ = new ClLinearExpression(*$1 * *$3); } + | expr '/' expr { $$ = new ClLinearExpression(*$1 / *$3); } + | '-' expr %prec NEG { $$ = new ClLinearExpression(-1 * *$2); } + | '(' expr ')' { $$ = $2; } +; + +%% + +void clerror(const char *sz) +{ + throw ExCLParseErrorMisc(sz); +} + +extern istream *pxi_lexer; + +// xi is the stream from which to read the constraint. +// aVars is an array of variables large enough to account for +// each one that might be mentioned in a constraint +ClConstraint *PcnParseConstraint(istream &xi, const ClVarLookupFunction &lookup_func, + const ClStrength &strength) +{ + ClParseData cl_parse_data(xi, lookup_func); + pxi_lexer = ξ + if (yyparse(&cl_parse_data) == 0) { // success +#ifdef DEBUG_PARSER + cerr << *cl_parse_data.Pcn() << endl; +#endif + cl_parse_data.Pcn()->ChangeStrength(strength); + cl_parse_data.Pcn()->AddROVars(cl_parse_data._readOnlyVarsSoFar); + return cl_parse_data.Pcn(); + } + else { // failed + return 0; + } +} |