1 // This scanner uses the recursive descent method.
3 // The char pointers token_str and scan_str are pointers to the input string as
4 // in the following example.
6 // | g | a | m | m | a | | a | l | p | h | a |
10 // The char pointer token_buf points to a malloc buffer.
12 // | g | a | m | m | a | \0 |
19 #define T_INTEGER 1001
22 #define T_FUNCTION 1004
23 #define T_NEWLINE 1006
29 static int token
, newline_flag
, meta_mode
;
30 static char *input_str
, *scan_str
, *token_str
, *token_buf
;
32 // Returns number of chars scanned and expr on stack.
34 // Returns zero when nothing left to scan.
51 return (int) (token_str
- input_str
);
69 return (int) (token_str
- input_str
);
131 scan_expression(void)
148 while (newline_flag
== 0 && (token
== '+' || token
== '-')) {
179 if (newline_flag
) { // implicit mul can't cross line
180 scan_str
= token_str
; // better error display
199 if (tos
> h
&& isrational(stack
[tos
- 1]) && equaln(stack
[tos
- 1], 1))
202 while (is_factor()) {
206 } else if (token
== '/') {
215 if (tos
> h
+ 1 && isnum(stack
[tos
- 2]) && isnum(stack
[tos
- 1]))
220 if (tos
> h
&& isrational(stack
[tos
- 1]) && equaln(stack
[tos
- 1], 1))
226 else if (tos
- h
> 1) {
228 push_symbol(MULTIPLY
);
256 else if (token
== T_SYMBOL
)
258 else if (token
== T_FUNCTION
)
259 scan_function_call();
260 else if (token
== T_INTEGER
) {
261 bignum_scan_integer(token_buf
);
263 } else if (token
== T_DOUBLE
) {
264 bignum_scan_float(token_buf
);
266 } else if (token
== T_STRING
)
269 error("syntax error");
278 while (token
== ',') {
288 while (token
== '!') {
290 push_symbol(FACTORIAL
);
299 if (token
!= T_SYMBOL
)
300 error("symbol expected");
301 if (meta_mode
&& strlen(token_buf
) == 1)
302 switch (token_buf
[0]) {
313 push(usr_symbol(token_buf
));
317 push(usr_symbol(token_buf
));
324 new_string(token_buf
);
329 scan_function_call(void)
333 p
= usr_symbol(token_buf
);
335 get_next_token(); // function name
336 get_next_token(); // left paren
340 while (token
== ',') {
352 // scan subexpression
364 while (token
== ',') {
381 // try not to put question mark on orphan line
383 while (input_str
!= scan_str
) {
384 if ((*input_str
== '\n' || *input_str
== '\r') && input_str
+ 1 == scan_str
)
386 printchar(*input_str
++);
391 while (*input_str
&& (*input_str
!= '\n' && *input_str
!= '\r'))
392 printchar(*input_str
++);
399 // There are n expressions on the stack, possibly tensors.
401 // This function assembles the stack expressions into a single tensor.
403 // For example, at the top level of the expression ((a,b),(c,d)), the vectors
404 // (a,b) and (c,d) would be on the stack.
409 // int i, j, k, ndim, nelem;
419 p2
= alloc_tensor(n
);
420 p2
->u
.tensor
->ndim
= 1;
421 p2
->u
.tensor
->dim
[0] = n
;
422 for (i
= 0; i
< n
; i
++)
423 p2
->u
.tensor
->elem
[i
] = s
[i
];
438 if (token
!= T_NEWLINE
)
449 while (isspace(*scan_str
)) {
450 if (*scan_str
== '\n' || *scan_str
== '\r') {
458 token_str
= scan_str
;
462 if (*scan_str
== 0) {
469 if (isdigit(*scan_str
) || *scan_str
== '.') {
470 while (isdigit(*scan_str
))
472 if (*scan_str
== '.') {
474 while (isdigit(*scan_str
))
476 if (*scan_str
== 'e' && (scan_str
[1] == '+' || scan_str
[1] == '-' || isdigit(scan_str
[1]))) {
478 while (isdigit(*scan_str
))
484 update_token_buf(token_str
, scan_str
);
490 if (isalpha(*scan_str
)) {
491 while (isalnum(*scan_str
))
493 if (*scan_str
== '(')
497 update_token_buf(token_str
, scan_str
);
503 if (*scan_str
== '"') {
505 while (*scan_str
!= '"') {
506 if (*scan_str
== 0 || *scan_str
== '\n' || *scan_str
== '\r')
507 error("runaway string");
512 update_token_buf(token_str
+ 1, scan_str
- 1);
518 if (*scan_str
== '#' || (*scan_str
== '-' && scan_str
[1] == '-')) {
519 while (*scan_str
&& *scan_str
!= '\n' && *scan_str
!= '\r')
527 // relational operator?
529 if (*scan_str
== '=' && scan_str
[1] == '=') {
535 if (*scan_str
== '<' && scan_str
[1] == '=') {
541 if (*scan_str
== '>' && scan_str
[1] == '=') {
553 update_token_buf(char *a
, char *b
)
562 token_buf
= (char *) malloc(n
+ 1);
565 stop("malloc failure");
567 strncpy(token_buf
, a
, n
);
574 // Formerly add() and multiply() were used to construct expressions but
575 // this preevaluation caused problems.
577 // For example, suppose A has the floating point value inf.
579 // Before, the expression A/A resulted in 1 because the scanner would
580 // divide the symbols.
582 // After removing add() and multiply(), A/A results in nan which is the
585 // The functions negate() and inverse() are used but they do not cause
586 // problems with preevaluation of symbols.