Merging from trunk
[ardour.git] / libs / cassowary / ClReader.yy
1 /*
2  $Id$
3
4  Cassowary Incremental Constraint Solver
5  Original Smalltalk Implementation by Alan Borning
6  This C++ Implementation by Greg J. Badros, <gjb@cs.washington.edu>
7  http://www.cs.washington.edu/homes/gjb
8  (C) 1998, 1999 Greg J. Badros and Alan Borning
9  See ../LICENSE for legal details regarding this software
10
11  ClReader.y
12  Original implementation contributed by Steve Wolfman
13  Subsequently largely revised by Greg J. Badros
14
15  Supports parsing of read-only variables in constraints via "?" suffix
16  annotations on variables.  If a variable is followed by "?" in any of
17  its occurrences in the constraint, that variable is deemed read-only
18  and entered into the constraint object as such.  E.g.,
19
20   x = 2*y?
21
22   is a one-way constraint that sets x from y's value.
23
24   x = y + y?
25     and
26   x = y? + y
27  
28   are identical one-way constraints with y read-only.  One would prefer
29   to have it written like so:
30
31   x = y? + y?
32
33   but it need not be, and no warning or error is raised.
34 */
35
36
37 %{
38   /* C Declarations */
39
40 #include <cassowary/Cl.h>
41 #include <string>
42 #include <map>
43
44 #ifdef HAVE_CONFIG_H
45 #include <config.h>
46 #define CONFIG_H_INCLUDED
47 #endif
48
49 #ifdef USE_CRUMMY_LEXER
50 string current;  /* Global to help in debugging/error messages */
51 #endif
52
53 /* Get yyparse, yylex to have an extra argument (type void *) */
54 #define YYPARSE_PARAM cl_parse_data
55 #define YYLEX_PARAM cl_parse_data
56 #ifndef YYERROR_VERBOSE
57 #define YYERROR_VERBOSE
58 #endif
59 #define YYDEBUG 1
60
61 %}
62
63
64 /* Bison Declarations */
65
66 %pure_parser
67
68 %union {
69   double num;
70   const ClVariable *pclv;
71   ClLinearExpression *pcle;
72   ClConstraint *pcn;
73 }
74
75 %{
76 int yylex(YYSTYPE *lvalp, void *YYLEX_PARAM);
77 void yyerror(const char *sz);
78 %}
79
80 %start constraint
81
82 %token <num> NUM
83 %token <pclv> VAR
84 %token <pclv> RO_VAR
85
86 %token GEQ
87 %token GT
88 %token LEQ
89 %token LT
90
91 %type <pcle> expr
92 %type <pcn> constraint equation inequality
93
94 %left '-' '+'
95 %left '*' '/'
96 %left NEG
97
98 %%
99 /* Grammar Rules */
100
101 constraint:     equation  { $$ = $1; ((ClParseData*)YYPARSE_PARAM)->_pcn = $1; }
102             | inequality  { $$ = $1; ((ClParseData*)YYPARSE_PARAM)->_pcn = $1; }
103 ;
104
105 equation:  expr '=' expr  { $$ = new ClLinearEquation(*$1, *$3);   }
106 ;
107
108 inequality: expr GEQ expr { $$ = new ClLinearInequality(*$1, cnGEQ, *$3); }
109           | expr LEQ expr { $$ = new ClLinearInequality(*$1, cnLEQ, *$3); }
110           | expr LT  expr { $$ = new ClLinearInequality(*$1, cnLT,  *$3); }
111           | expr GT  expr { $$ = new ClLinearInequality(*$1, cnGT,  *$3); }
112 ;
113
114 expr:     NUM                { $$ = new ClLinearExpression($1);        }
115         | VAR                { $$ = new ClLinearExpression(*$1);       }
116         | RO_VAR             { $$ = new ClLinearExpression(*$1);
117                                ((ClParseData*)YYPARSE_PARAM)->_readOnlyVarsSoFar.insert(*$1); }
118         | expr '+' expr      { $$ = new ClLinearExpression(*$1 + *$3); }
119         | expr '-' expr      { $$ = new ClLinearExpression(*$1 - *$3); }
120         | expr '*' expr      { $$ = new ClLinearExpression(*$1 * *$3); }
121         | expr '/' expr      { $$ = new ClLinearExpression(*$1 / *$3); }
122         | '-' expr %prec NEG { $$ = new ClLinearExpression(-1 * *$2);  }
123         | '(' expr ')'       { $$ = $2;                                }
124 ;
125
126 %%
127
128 void clerror(const char *sz)
129 {
130   throw ExCLParseErrorMisc(sz);
131 }
132
133 extern istream *pxi_lexer;
134
135 // xi is the stream from which to read the constraint.
136 // aVars is an array of variables large enough to account for
137 // each one that might be mentioned in a constraint
138 ClConstraint *PcnParseConstraint(istream &xi, const ClVarLookupFunction &lookup_func, 
139         const ClStrength &strength)
140 {
141   ClParseData cl_parse_data(xi, lookup_func);
142   pxi_lexer = &xi;
143   if (yyparse(&cl_parse_data) == 0) { // success
144 #ifdef DEBUG_PARSER
145     cerr << *cl_parse_data.Pcn() << endl;
146 #endif
147     cl_parse_data.Pcn()->ChangeStrength(strength);
148     cl_parse_data.Pcn()->AddROVars(cl_parse_data._readOnlyVarsSoFar);
149     return cl_parse_data.Pcn();
150   }
151   else { // failed
152     return 0;
153   }
154 }