summaryrefslogtreecommitdiff
path: root/libs/cassowary/ClReader.y
blob: f9f0dca43ee7a9559972f5968630cff297d59922 (plain)
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
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 = &xi;
  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;
  }
}