spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[ParserConstants] naming constants
author
Ben Vogt <[email protected]>
date
2017-12-22 01:41:17
stats
2 file(s) changed, 68 insertions(+), 66 deletions(-)
files
src/Parser/ParserConstants.ts
tests/SheetBasicTests.ts
  1diff --git a/src/Parser/ParserConstants.ts b/src/Parser/ParserConstants.ts
  2index 2c6f3c8..41c5123 100644
  3--- a/src/Parser/ParserConstants.ts
  4+++ b/src/Parser/ParserConstants.ts
  5@@ -146,9 +146,9 @@ const enum ReduceActions {
  6   TO_NUMBER_NAN_AS_ZERO = 22,
  7   CALL_FUNCTION_LAST_BLANK = 23,
  8   CALL_FUNCTION_LAST_TWO_IN_STACK = 24,
  9-  I25 = 25,
 10-  I26 = 26,
 11-  I27 = 27,
 12+  CELL_VALUE_AS_EXPRESSION = 25,
 13+  ERROR_AND_CONTINUE = 26,
 14+  ERROR_AND_CONTINUE_WITH_OTHER_ERRORS = 27,
 15   FIXED_CELL_VAL = 28,
 16   FIXED_CELL_RANGE_VAL = 29,
 17   CELL_VALUE = 30,
 18@@ -263,9 +263,9 @@ productions[ReduceActions.INVERT_NUM] = new ReductionPair(Symbol.EXPRESSION, 2);
 19 productions[ReduceActions.TO_NUMBER_NAN_AS_ZERO] = new ReductionPair(Symbol.EXPRESSION, 2);
 20 productions[ReduceActions.CALL_FUNCTION_LAST_BLANK] = new ReductionPair(Symbol.EXPRESSION, 3);
 21 productions[ReduceActions.CALL_FUNCTION_LAST_TWO_IN_STACK] = new ReductionPair(Symbol.EXPRESSION, 4);
 22-productions[ReduceActions.I25] = new ReductionPair(Symbol.EXPRESSION, 1);
 23-productions[ReduceActions.I26] = new ReductionPair(Symbol.EXPRESSION, 1);
 24-productions[ReduceActions.I27] = new ReductionPair(Symbol.EXPRESSION, 2);
 25+productions[ReduceActions.CELL_VALUE_AS_EXPRESSION] = new ReductionPair(Symbol.EXPRESSION, 1);
 26+productions[ReduceActions.ERROR_AND_CONTINUE] = new ReductionPair(Symbol.EXPRESSION, 1);
 27+productions[ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS] = new ReductionPair(Symbol.EXPRESSION, 2);
 28 productions[ReduceActions.FIXED_CELL_VAL] = new ReductionPair(Symbol.CELL, 1);
 29 productions[ReduceActions.FIXED_CELL_RANGE_VAL] = new ReductionPair(Symbol.CELL, 3);
 30 productions[ReduceActions.CELL_VALUE] = new ReductionPair(Symbol.CELL, 1);
 31@@ -397,6 +397,7 @@ const enum State {
 32   DIVIDE_TWO_NUMBERS = 54,
 33   NUMBER_TO_POWER_OF_OTHER = 55,
 34   CLOSE_PAREN_ON_EXPRESSION = 57,
 35+  FUNCTION_LEFTPAREN_EXPRESSION = 60,
 36   COMPARE_TWO_EXPRESSIONS_WITH_GTE = 69,
 37   CLOSE_PAREN_ON_FUNCTION = 70,
 38   VARIABLE_FOLLOWED_BY_SEMI_COLON = 71,
 39@@ -546,35 +547,35 @@ table[State.FUNCTION] = ObjectBuilder
 40   .add(Symbol.LEFT_PAREN, [SHIFT, State.FOLLOW_FUNCTION_THEN_LEFT_PAREN])
 41   .build();
 42 table[State.FOLLOWS_CELL] = ObjectBuilder
 43-  .add(Symbol.EOF, [REDUCE, ReduceActions.I25])
 44-  .add(Symbol.AMPERSAND, [REDUCE, ReduceActions.I25])
 45-  .add(Symbol.EQUALS, [REDUCE, ReduceActions.I25])
 46-  .add(Symbol.PLUS, [REDUCE, ReduceActions.I25])
 47-  .add(Symbol.RIGHT_PAREN, [REDUCE, ReduceActions.I25])
 48-  .add(Symbol.LESS_THAN, [REDUCE, ReduceActions.I25])
 49-  .add(Symbol.GREATER_THAN, [REDUCE, ReduceActions.I25])
 50-  .add(Symbol.MINUS, [REDUCE, ReduceActions.I25])
 51-  .add(Symbol.ASTERISK, [REDUCE, ReduceActions.I25])
 52-  .add(Symbol.DIVIDE, [REDUCE, ReduceActions.I25])
 53-  .add(Symbol.CARROT, [REDUCE, ReduceActions.I25])
 54-  .add(Symbol.SEMI_COLON, [REDUCE, ReduceActions.I25])
 55-  .add(Symbol.COMMA, [REDUCE, ReduceActions.I25])
 56+  .add(Symbol.EOF, [REDUCE, ReduceActions.CELL_VALUE_AS_EXPRESSION])
 57+  .add(Symbol.AMPERSAND, [REDUCE, ReduceActions.CELL_VALUE_AS_EXPRESSION])
 58+  .add(Symbol.EQUALS, [REDUCE, ReduceActions.CELL_VALUE_AS_EXPRESSION])
 59+  .add(Symbol.PLUS, [REDUCE, ReduceActions.CELL_VALUE_AS_EXPRESSION])
 60+  .add(Symbol.RIGHT_PAREN, [REDUCE, ReduceActions.CELL_VALUE_AS_EXPRESSION])
 61+  .add(Symbol.LESS_THAN, [REDUCE, ReduceActions.CELL_VALUE_AS_EXPRESSION])
 62+  .add(Symbol.GREATER_THAN, [REDUCE, ReduceActions.CELL_VALUE_AS_EXPRESSION])
 63+  .add(Symbol.MINUS, [REDUCE, ReduceActions.CELL_VALUE_AS_EXPRESSION])
 64+  .add(Symbol.ASTERISK, [REDUCE, ReduceActions.CELL_VALUE_AS_EXPRESSION])
 65+  .add(Symbol.DIVIDE, [REDUCE, ReduceActions.CELL_VALUE_AS_EXPRESSION])
 66+  .add(Symbol.CARROT, [REDUCE, ReduceActions.CELL_VALUE_AS_EXPRESSION])
 67+  .add(Symbol.SEMI_COLON, [REDUCE, ReduceActions.CELL_VALUE_AS_EXPRESSION])
 68+  .add(Symbol.COMMA, [REDUCE, ReduceActions.CELL_VALUE_AS_EXPRESSION])
 69   .build();
 70 table[State.ERROR] = ObjectBuilder
 71   .add(Symbol.ERROR, State.FOLLOW_ERROR_ERROR)
 72-  .add(Symbol.EOF, [REDUCE, ReduceActions.I26])
 73-  .add(Symbol.AMPERSAND, [REDUCE, ReduceActions.I26])
 74-  .add(Symbol.EQUALS, [REDUCE, ReduceActions.I26])
 75-  .add(Symbol.PLUS, [REDUCE, ReduceActions.I26])
 76-  .add(Symbol.RIGHT_PAREN, [REDUCE, ReduceActions.I26])
 77-  .add(Symbol.LESS_THAN, [REDUCE, ReduceActions.I26])
 78-  .add(Symbol.GREATER_THAN, [REDUCE, ReduceActions.I26])
 79-  .add(Symbol.MINUS, [REDUCE, ReduceActions.I26])
 80-  .add(Symbol.ASTERISK, [REDUCE, ReduceActions.I26])
 81-  .add(Symbol.DIVIDE, [REDUCE, ReduceActions.I26])
 82-  .add(Symbol.CARROT, [REDUCE, ReduceActions.I26])
 83-  .add(Symbol.SEMI_COLON, [REDUCE, ReduceActions.I26])
 84-  .add(Symbol.COMMA, [REDUCE, ReduceActions.I26])
 85+  .add(Symbol.EOF, [REDUCE, ReduceActions.ERROR_AND_CONTINUE])
 86+  .add(Symbol.AMPERSAND, [REDUCE, ReduceActions.ERROR_AND_CONTINUE])
 87+  .add(Symbol.EQUALS, [REDUCE, ReduceActions.ERROR_AND_CONTINUE])
 88+  .add(Symbol.PLUS, [REDUCE, ReduceActions.ERROR_AND_CONTINUE])
 89+  .add(Symbol.RIGHT_PAREN, [REDUCE, ReduceActions.ERROR_AND_CONTINUE])
 90+  .add(Symbol.LESS_THAN, [REDUCE, ReduceActions.ERROR_AND_CONTINUE])
 91+  .add(Symbol.GREATER_THAN, [REDUCE, ReduceActions.ERROR_AND_CONTINUE])
 92+  .add(Symbol.MINUS, [REDUCE, ReduceActions.ERROR_AND_CONTINUE])
 93+  .add(Symbol.ASTERISK, [REDUCE, ReduceActions.ERROR_AND_CONTINUE])
 94+  .add(Symbol.DIVIDE, [REDUCE, ReduceActions.ERROR_AND_CONTINUE])
 95+  .add(Symbol.CARROT, [REDUCE, ReduceActions.ERROR_AND_CONTINUE])
 96+  .add(Symbol.SEMI_COLON, [REDUCE, ReduceActions.ERROR_AND_CONTINUE])
 97+  .add(Symbol.COMMA, [REDUCE, ReduceActions.ERROR_AND_CONTINUE])
 98   .add(Symbol.VARIABLE, [SHIFT, ReduceActions.ENSURE_LAST_TWO_IN_ARRAY_AND_PUSH])
 99   .add(Symbol.POUND, [SHIFT, ReduceActions.MULTIPLY])
100   .build();
101@@ -827,7 +828,7 @@ table[State.NUMBER_FOLLOWED_BY_CARROT] = ObjectBuilder
102   .add(Symbol.NUMBER_UPPER, [SHIFT, State.FOLLOW_NUMBER_UPPER])
103   .add(Symbol.POUND, [SHIFT, State.FOLLOW_POUND])
104   .build();
105-table[ReduceActions.CELL_VALUE] = ObjectBuilder
106+table[30] = ObjectBuilder
107   .add(Symbol.VARIABLE, [SHIFT, 56])
108   .build();
109 table[31] = ObjectBuilder
110@@ -868,7 +869,7 @@ table[State.EXPRESSION_FOLLOWING_PREFIX_UNARY_MINUS] = ObjectBuilder
111   .add(Symbol.LESS_THAN, [REDUCE, ReduceActions.INVERT_NUM])
112   .add(Symbol.GREATER_THAN, [REDUCE, ReduceActions.INVERT_NUM])
113   .add(Symbol.MINUS, [REDUCE, ReduceActions.INVERT_NUM])
114-  .add(Symbol.ASTERISK, [SHIFT, ReduceActions.I27])
115+  .add(Symbol.ASTERISK, [SHIFT, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
116   .add(Symbol.DIVIDE, [SHIFT, ReduceActions.FIXED_CELL_VAL])
117   .add(Symbol.CARROT, [SHIFT, ReduceActions.FIXED_CELL_RANGE_VAL])
118   .add(Symbol.SEMI_COLON, [REDUCE, ReduceActions.INVERT_NUM])
119@@ -891,7 +892,7 @@ table[State.EXPRESSION_FOLLOWING_PREFIX_UNARY_PLUS] = ObjectBuilder
120   .build();
121 table[State.FOLLOW_FUNCTION_THEN_LEFT_PAREN] = ObjectBuilder
122   .add(Symbol.ERROR, State.ERROR)
123-  .add(Symbol.EXPRESSION, 60)
124+  .add(Symbol.EXPRESSION, State.FUNCTION_LEFTPAREN_EXPRESSION)
125   .add(Symbol.VARIABLE_SEQUENCE, State.FOLLOW_VARIABLE_SEQUENCE)
126   .add(Symbol.NUMBER, State.START_NUMBER)
127   .add(Symbol.STRING, [SHIFT, State.START_STRING])
128@@ -910,19 +911,19 @@ table[State.FOLLOW_FUNCTION_THEN_LEFT_PAREN] = ObjectBuilder
129   .add(Symbol.POUND, [SHIFT, State.FOLLOW_POUND])
130   .build();
131 table[State.FOLLOW_ERROR_ERROR] = ObjectBuilder
132-  .add(Symbol.EOF, [REDUCE, ReduceActions.I27])
133-  .add(Symbol.AMPERSAND, [REDUCE, ReduceActions.I27])
134-  .add(Symbol.EQUALS, [REDUCE, ReduceActions.I27])
135-  .add(Symbol.PLUS, [REDUCE, ReduceActions.I27])
136-  .add(Symbol.RIGHT_PAREN, [REDUCE, ReduceActions.I27])
137-  .add(Symbol.LESS_THAN, [REDUCE, ReduceActions.I27])
138-  .add(Symbol.GREATER_THAN, [REDUCE, ReduceActions.I27])
139-  .add(Symbol.MINUS, [REDUCE, ReduceActions.I27])
140-  .add(Symbol.ASTERISK, [REDUCE, ReduceActions.I27])
141-  .add(Symbol.DIVIDE, [REDUCE, ReduceActions.I27])
142-  .add(Symbol.CARROT, [REDUCE, ReduceActions.I27])
143-  .add(Symbol.SEMI_COLON, [REDUCE, ReduceActions.I27])
144-  .add(Symbol.COMMA, [REDUCE, ReduceActions.I27])
145+  .add(Symbol.EOF, [REDUCE, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
146+  .add(Symbol.AMPERSAND, [REDUCE, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
147+  .add(Symbol.EQUALS, [REDUCE, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
148+  .add(Symbol.PLUS, [REDUCE, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
149+  .add(Symbol.RIGHT_PAREN, [REDUCE, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
150+  .add(Symbol.LESS_THAN, [REDUCE, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
151+  .add(Symbol.GREATER_THAN, [REDUCE, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
152+  .add(Symbol.MINUS, [REDUCE, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
153+  .add(Symbol.ASTERISK, [REDUCE, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
154+  .add(Symbol.DIVIDE, [REDUCE, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
155+  .add(Symbol.CARROT, [REDUCE, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
156+  .add(Symbol.SEMI_COLON, [REDUCE, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
157+  .add(Symbol.COMMA, [REDUCE, ReduceActions.ERROR_AND_CONTINUE_WITH_OTHER_ERRORS])
158   .build();
159 table[37] = ObjectBuilder
160   .add(Symbol.POUND, [REDUCE, ReduceActions.AS_ERROR])
161@@ -1069,25 +1070,25 @@ table[State.GREATERTHAN_EXPRESSION] = ObjectBuilder
162   .add(Symbol.COMMA, [REDUCE, ReduceActions.GT])
163   .build();
164 table[51] = ObjectBuilder
165-  .add(Symbol.AMPERSAND, [SHIFT, 20])
166+  .add(Symbol.AMPERSAND, [SHIFT, State.NUMBER_FOLLOWED_BY_AMPERSAND])
167   .add(Symbol.PLUS, [SHIFT, 22])
168   .add(Symbol.LESS_THAN, [SHIFT, 23])
169   .add(Symbol.GREATER_THAN, [SHIFT, 24])
170-  .add(Symbol.MINUS, [SHIFT, 26])
171-  .add(Symbol.ASTERISK, [SHIFT, 27])
172+  .add(Symbol.MINUS, [SHIFT, State.NUMBER_FOLLOWED_BY_MINUS])
173+  .add(Symbol.ASTERISK, [SHIFT, State.NUMBER_FOLLOWED_BY_ASTERISK])
174   .add(Symbol.DIVIDE, [SHIFT, 28])
175   .add(Symbol.CARROT, [SHIFT, 29])
176   .build();
177 table[State.SUBTRACT_TWO_NUMBERS] = ObjectBuilder
178   .add(Symbol.EOF, [REDUCE, ReduceActions.MINUS])
179-  .add(Symbol.AMPERSAND, [SHIFT, 20])
180+  .add(Symbol.AMPERSAND, [SHIFT, State.NUMBER_FOLLOWED_BY_AMPERSAND])
181   .add(Symbol.EQUALS, [REDUCE, ReduceActions.MINUS])
182   .add(Symbol.PLUS, [REDUCE, ReduceActions.MINUS])
183   .add(Symbol.RIGHT_PAREN, [REDUCE, ReduceActions.MINUS])
184   .add(Symbol.LESS_THAN, [REDUCE, ReduceActions.MINUS])
185   .add(Symbol.GREATER_THAN, [REDUCE, ReduceActions.MINUS])
186   .add(Symbol.MINUS, [REDUCE, ReduceActions.MINUS])
187-  .add(Symbol.ASTERISK, [SHIFT, 27])
188+  .add(Symbol.ASTERISK, [SHIFT, State.NUMBER_FOLLOWED_BY_ASTERISK])
189   .add(Symbol.DIVIDE, [SHIFT, 28])
190   .add(Symbol.CARROT, [SHIFT, 29])
191   .add(Symbol.SEMI_COLON, [REDUCE, ReduceActions.MINUS])
192@@ -1189,7 +1190,7 @@ table[59] = ObjectBuilder
193   .add(Symbol.SEMI_COLON, [SHIFT, State.VARIABLE_FOLLOWED_BY_SEMI_COLON])
194   .add(Symbol.COMMA, [SHIFT, State.VARIABLE_FOLLOWED_BY_COMMA])
195   .build();
196-table[60] = ObjectBuilder
197+table[State.FUNCTION_LEFTPAREN_EXPRESSION] = ObjectBuilder
198   .add(Symbol.AMPERSAND, [SHIFT, State.NUMBER_FOLLOWED_BY_AMPERSAND])
199   .add(Symbol.EQUALS, [SHIFT, State.START_EQUALS])
200   .add(Symbol.PLUS, [SHIFT, State.NUMBER_FOLLOWED_BY_PLUS])
201diff --git a/tests/SheetBasicTests.ts b/tests/SheetBasicTests.ts
202index c8dd211..df39965 100644
203--- a/tests/SheetBasicTests.ts
204+++ b/tests/SheetBasicTests.ts
205@@ -25,8 +25,8 @@ test("Sheet, number multiplication", function () {
206 });
207 
208 test("Sheet, parse but throw parse error", function(){
209-  // assertEquals(parser.parse('=10e'), PARSE_ERROR);
210-  // assertEquals(parser.parse('= SUM('), PARSE_ERROR);
211+  assertFormulaEqualsError('=10e', PARSE_ERROR);
212+  assertFormulaEqualsError('= SUM(', PARSE_ERROR);
213 });
214 
215 test("Sheet, parse & operator", function(){
216@@ -50,7 +50,7 @@ test("Sheet, parse / operator", function(){
217   assertFormulaEquals('="500" / 1', 500);
218   assertFormulaEqualsError('=10 / 0', DIV_ZERO_ERROR);
219   assertFormulaEqualsError('=0 / 0', DIV_ZERO_ERROR);
220-  // assertEquals(parser.parse('P9 / 1'), 0);
221+  assertFormulaEquals('=P9 / 1', 0);
222 });
223 
224 test("Sheet, parse ^ operator", function(){
225@@ -138,14 +138,14 @@ test("Sheet, parse and throw error literal", function () {
226 
227 test("Sheet, parse plain numbers", function() {
228   assertFormulaEquals('=10', 10);
229-  // assertEquals(parser.parse('.1'), 0.1); // TODO: Fails because our parser doesn't expect a decimal right away.
230+  // assertFormulaEquals('=.1', 0.1); // TODO: Fails because our parser doesn't expect a decimal right away.
231   assertFormulaEquals('=+1', 1);
232   assertFormulaEquals('=-1', -1);
233   assertFormulaEquals('=++1', 1);
234   assertFormulaEquals('=--1', 1);
235   assertFormulaEquals('=10e1', 100);
236   assertFormulaEquals('=0e1', 0);
237-  // assertEquals(parser.parse('0.e1'), 0); // TODO: Fails. After decimal, finds 'e' and thinks it's a variable.
238+  // assertFormulaEquals('=0.e1', 0); // TODO: Fails. After decimal, finds 'e' and thinks it's a variable.
239   assertFormulaEquals('=-10e1', -100);
240   assertFormulaEquals('=+10e1', 100);
241   assertFormulaEquals('=++10e1', 100);
242@@ -192,7 +192,7 @@ test("Sheet, parse strings", function(){
243   assertFormulaEquals('="str"', "str");
244   assertFormulaEquals('="str"&"str"', "strstr");
245   assertFormulaEqualsError('="str"+"str"', VALUE_ERROR);
246-  // assertEquals("='str'", PARSE_ERROR); // TODO: Parses, but we should not allow single-quote strings.
247+  // assertFormulaEqualsError("='str'", PARSE_ERROR); // TODO: Parses, but we should not allow single-quote strings.
248 });
249 
250 test("Sheet, parse boolean literals", function(){
251@@ -208,7 +208,6 @@ test("Sheet, parse comparison logic inside parentheses", function(){
252   assertFormulaEquals('=(1=1)+2', 3);
253 });
254 
255-
256 test("Sheet, parse range literal", function(){
257   // assertEqualsArray('=[1, 2, 3]', [1, 2, 3]); // TODO: Fails because we've not implemented array-level parsing.
258   // assertEqualsArray('=[]', []);
259@@ -216,5 +215,9 @@ test("Sheet, parse range literal", function(){
260   // assertEqualsArray('=["str", [1, 2, 3], [1]]', ["str", [1, 2, 3], [1]]);
261 });
262 
263+test("Sheet state sequence: (number, ampersand, expression)", function(){
264+  assertFormulaEquals('=10&10', "1010");
265+  assertFormulaEquals('=10&"str"', "10str");
266+  assertFormulaEquals('=10 & TRUE', "10TRUE");
267+});
268 
269-assertFormulaEqualsDependsOnReference('M1', 10, '=10 + 10', 20);