comparison tests/agcl/parsifal/ss-sscx.syn @ 0:13d2b8934445

Import AnaGram (near-)release tree into Mercurial.
author David A. Holland
date Sat, 22 Dec 2007 17:52:45 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:13d2b8934445
1 {/*
2 Copyright 1992, Jerome T. Holland
3 See the file COPYING for license and usage terms.
4
5 An example syntax and supporting classes for implementing a spreadsheet
6
7 Class definitions are found in sscxdefs.h
8
9 This example is largely intended to serve as an illustration, and is
10 incomplete in a number of ways. In particular, the expression syntax
11 is that of C, except for identifiers, and only a few functions are
12 implemented. More may be implemented trivially by following the
13 patterns provided.
14
15 The supported operations are:
16 Conditional expressions: ? :
17 Logical operators: !, &, |
18 Comparison operators: ==, !=, <, <=, >, >=
19 Binary arithmetic operators: +, -, *, /
20 Exponentiation: **
21 Unary arithmetic operators: +, -
22 Parentheses
23 Function calls abs, sin, asin, atan
24
25 A note on the technique used for compilation:
26
27 The basic approach is to build a Reverse Polish Notation stack.
28 During parsing, the constants, cell locators, and operators are
29 stacked on separate temporary stacks. When parsing is complete,
30 these stacks are unloaded into arrays belonging to the cell
31 expression object. Note that there is a one to one correspondence
32 between items on the constant stack and fd (fetch double) operators
33 in the op stack. Since there are no branching instructions, there
34 there is one and ony one constant corresponding to a fd operation
35 so it is sufficient to simply increment an index into the constant
36 array as execution progresses, to know which constant to use. The
37 same logic holds for cell locators.
38 */
39
40 #include <math.h>
41 #include "agstk.h"
42 #include <string.h>
43 #include <errno.h>
44 #include "sscxdefs.h"
45
46 }
47
48 // -- CONFIGURATION SECTION ----------------------------
49 [
50 disregard white space
51 lexeme {real, cell name}
52 pointer input
53 parser name = parseKernel
54 parser file name = "#.cpp"
55 line numbers // For debugging
56 escape backslashes // Comment this line if using a Borland compiler
57 ]
58
59 input string $ // specify grammar token
60 -> expression, eof
61
62 expression
63 -> logical or expression
64 -> logical or expression, '?',
65 expression, ':', expression =opStack.push(CellExpression::cond);
66
67 logical or expression
68 -> logical and expression
69 -> logical or expression, '|', logical and expression =opStack.push(CellExpression::or);
70
71 logical and expression
72 -> equality expression
73 -> logical and expression, '&', equality expression =opStack.push(CellExpression::and);
74
75 equality expression
76 -> relational expression
77 -> equality expression:x, "==", relational expression:y =opStack.push(CellExpression::eq);
78 -> equality expression:x, "!=", relational expression:y =opStack.push(CellExpression::ne);
79
80 relational expression
81 -> additive expression
82 -> relational expression, '<', additive expression =opStack.push(CellExpression::lt);
83 -> relational expression, "<=", additive expression =opStack.push(CellExpression::le);
84 -> relational expression, '>', additive expression =opStack.push(CellExpression::gt);
85 -> relational expression, ">=", additive expression =opStack.push(CellExpression::ge);
86
87 additive expression
88 -> multiplicative expression
89 -> additive expression, '+', multiplicative expression =opStack.push(CellExpression::add);
90 -> additive expression, '-', multiplicative expression =opStack.push(CellExpression::sub);
91
92 multiplicative expression
93 -> factor
94 -> multiplicative expression:x, '*', factor:y =opStack.push(CellExpression::mpy);
95 -> multiplicative expression:x, '/', factor:y =opStack.push(CellExpression::div);
96
97 factor
98 -> primary
99 -> primary, "**", factor =opStack.push(CellExpression::pow);
100
101 primary
102 -> real:x =doubleStack.push(x), opStack.push(CellExpression::fd);
103 -> cell name:n =locatorStack.push(n), opStack.push(CellExpression::fc);
104 -> "abs", '(', expression, ')' =opStack.push(CellExpression::abs);
105 -> "sin", '(', expression, ')' =opStack.push(CellExpression::sin);
106 -> "asin", '(', expression, ')' =opStack.push(CellExpression::sin);
107 -> "atan", '(', expression, ')' =opStack.push(CellExpression::atan);
108 -> "atan", '(', expression, ',', expression, ')' =opStack.push(CellExpression::atan2);
109 -> '(', expression, ')'
110 -> '-', primary =opStack.push(CellExpression::minus);
111 -> '+', primary
112 -> '!', primary =opStack.push(CellExpression::not);
113
114 // -- LEXICAL UNITS ------------------------------------------------
115 digit = '0-9'
116 eof = 0
117
118 (void) white space
119 -> ' ' + '\t' + '\f' + '\v' + '\r' + '\n'
120 -> "/*", ~eof?..., "*/" // C style comment
121 -> "//", ~(eof+'\n')?..., '\n' // C++ style comment
122
123 (double) real
124 -> simple real
125 -> simple real:x, 'e'+'E', '+'?,exponent:e =x*pow(10,e);
126 -> simple real:x, 'e'+'E', '-',exponent:e =x*pow(10,-e);
127
128 (double) simple real
129 -> integer part:i, '.', fraction part:f = i+f;
130 -> integer part, '.'?
131 -> '.', fraction part:f = f;
132
133 (double) integer part
134 -> digit:d = d-'0';
135 -> integer part:x, digit:d = 10*x + d-'0';
136
137 (double) fraction part
138 -> digit:d =(d-'0')/10.;
139 -> digit:d, fraction part:f =(d-'0' + f)/10.;
140
141 (int) exponent
142 -> digit:d = d-'0';
143 -> exponent:x, digit:d = 10*x + d-'0';
144
145 (Locator) cell name //value of name token is length of name string
146 -> column:c, row:r =Locator(r-1,c);
147 -> '$',column:c, row:r =Locator(r-1,c).setAbsoluteCol();
148 -> column:c, '$', row:r =Locator(r-1,c).setAbsoluteRow();
149 -> '$', column:c, '$', row:r =Locator(r-1,c).setAbsoluteRow().setAbsoluteCol();
150
151 (int) letter
152 -> 'a-z':c =c - 'a';
153 -> 'A-Z':c =c = 'A';
154
155 (int) column
156 -> letter:n =n;
157 -> column:c, letter:n =26*c + n;
158
159 (int) row
160 -> digit:d =d - '0';
161 -> row:n, digit:d =10*n + d - '0';
162
163 {
164
165 // Stacks for use in parsing and compiling
166
167 AgStack<double> doubleStack;
168 AgStack<Locator> locatorStack;
169 AgStack<CellExpression::Op> opStack;
170
171 // Data for a simple minded test
172
173 CellExpression *Locator::expression[3][3];
174 int Locator::maxRow = 3;
175 int Locator::maxCol = 3;
176
177 char *expressionText[3][3] = {
178 {"17", "19", "-23"},
179 {"2*a1", "b1 - a2", "a2+b2"},
180 {"b2 + c2", "a3-a2", "a2/b2"}
181 };
182
183 /*
184 Constructor for CellExpression
185
186 Parses the input text and creates byte code for later execution by
187 the value() function.
188 */
189
190 CellExpression::CellExpression(char *text)
191 : constant(0), nConstants(0),
192 locator(0), nLocators(0),
193 op(0), nOps(0),
194 errorFlag(0), busy(0), cycle(0)
195 {
196 doubleStack.reset();
197 locatorStack.reset();
198 opStack.reset();
199 PCB.pointer = (unsigned char *) text;
200 parseKernel(); // Parse expression
201 if (PCB.exit_flag != AG_SUCCESS_CODE) {errorFlag = 1; return;}
202 // save parse results
203 nConstants = doubleStack.size();
204 nLocators = locatorStack.size();
205 nOps = opStack.size();
206 constant = new double[nConstants];
207 locator = new Locator[nLocators];
208 op = new Op[nOps];
209 int i;
210 for (i = nConstants; i--;) constant[i] = doubleStack.pop();
211 for (i = nLocators; i--;) locator[i] = locatorStack.pop();
212 for (i = nOps; i--;) op[i] = opStack.pop();
213 }
214
215 // Function to execute byte code
216
217 Number CellExpression::value() {
218 if (errorFlag) return Number();
219 if (busy) { // Check for cyclic definition
220 errorFlag = cycle = 1;
221 return Number();
222 }
223 busy = 1;
224 int constantIndex = 0;
225 int locatorIndex = 0;
226
227 AgStack<Number> stack; // Arithmetic stack for byte code interpreter
228
229 Number temp; // temporary variable
230 int pc = 0;
231 while (pc < nOps && errorFlag == 0) {
232 switch (op[pc]) {
233 case add: stack.pop(temp); stack.top() += temp; break;
234 case sub: stack.pop(temp); stack.top() -= temp; break;
235 case mpy: stack.pop(temp); stack.top() *= temp; break;
236 case div: stack.pop(temp); stack.top() /= temp; break;
237 case pow: stack.pop(temp); stack.top() = stack.top().pow(temp); break;
238 case lt: stack.pop(temp); stack.top() = stack.top() < temp; break;
239 case le: stack.pop(temp); stack.top() = stack.top() <= temp; break;
240 case gt: stack.pop(temp); stack.top() = stack.top() > temp; break;
241 case ge: stack.pop(temp); stack.top() = stack.top() >= temp; break;
242 case eq: stack.pop(temp); stack.top() = stack.top() == temp; break;
243 case ne: stack.pop(temp); stack.top() = stack.top() != temp; break;
244 case and: stack.pop(temp); stack.top() = stack.top() != Number(0) & temp != Number(0); break;
245 case or: stack.pop(temp); stack.top() = stack.top() != Number(0) | temp != Number(0); break;
246 case minus: stack.top() = -stack.top(); break;
247 case not: stack.top() = stack.top() == Number(0); break;
248 case cond: {
249 Number secondOption = stack.pop();
250 Number firstOption = stack.pop();
251 if (stack.top().bad) break;
252 stack.top() = (stack.top() != Number(0)) ? firstOption : secondOption;
253 break;
254 }
255 case abs: stack.top() = stack.top().abs(); break;
256 case sin: stack.top() = stack.top().sin(); break;
257 case asin: stack.top() = stack.top().asin(); break;
258 case atan: stack.top() = stack.top().atan(); break;
259 case atan2: temp = stack.pop(); stack.top() = stack.top().atan2(temp); break;
260 // Fetch double
261 case fd: stack.push(constant[constantIndex++]); break;
262 // Fetch cell value
263 case fc: {
264 CellExpression *x = locator[locatorIndex++].cellExpression();
265 Number temp;
266 if (x != 0) temp = x->value();
267 stack.push(temp);
268 break;
269 }
270 }
271 pc++;
272 }
273 busy = 0;
274 return stack.top();
275 }
276
277 // Rather trivial test
278
279 int main() {
280 int i, j;
281 // Initialize CellExpresions
282 for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) {
283 Locator::expression[i][j] = new CellExpression(expressionText[i][j]);
284 }
285 // Calculate and print out values
286 for (i = 0; i < 3; i++) for (j = 0; j < 3; j++) {
287 printf("cell[%d][%d] = %G\n", i, j, (double) (Locator::expression[i][j]->value()));
288 }
289 return 0;
290 }
291
292 }