5

While typing immediate-mode commands in Apple II Applesoft / floating point BASIC, I discovered an odd situation where I will get other programming error messages before a syntax error. Why does it do this?

]NEW
]sagdgg
?SYNTAX ERROR

]sagdgg P(10)
?BAD SUBSCRIPT ERROR

]P(10)
?BAD SUBSCRIPT ERROR

Immediate-mode dimensioning now changes this behavior.

]DIM P(10)
]P(10)
?SYNTAX ERROR

]P(11)
?BAD SUBSCRIPT ERROR

]sagdgg P(10)
?SYNTAX ERROR

]sagdgg P(11)
?BAD SUBSCRIPT ERROR

Then there's this weirdness

]NEW
]P(P(P(P(P(P(P(P(P(P(P(P
?SYNTAX ERROR

]P(P(P(P(P(P(P(P(P(P(P(P(P
?OUT OF MEMORY ERROR

...?

1
  • 1
    I suspect that the parsing isn't done neatly step-by-step like it is nowadays, but instead is done in a fashion that made sense to the person writing it at the time. For example, I suspect array subscripts in this case are checked before the syntax is fully evaluated. As for the out of memory error, could be more like "too many recursions", to handle code within brackets? These are both just guesses, hence a comment rather than an answer.
    – Muzer
    Dec 14, 2016 at 15:56

2 Answers 2

9

In Applesoft BASIC, the parser recognizes reserved words greedily, but spaces outside tokens or reserved words are ignored. Variable names may consist of any sequence of letters or numbers provided they start with a letter and do not contain any reserved words. Because the code for listing programs adds spaces before and after recognized tokens, typing a line into a program and then listing it can show how it was parsed.

For example, given:

10 FA=123:BUN=4:F=9:O=3
20 GR
30 ? FAMILY
40 H LINO,FATBURGER
50 ? FATALIST

The program would probably list as something like:

10 FA = 123 : BUN = 4: F = 9 : O = 3
20  GR
30  PRINT FAMILY
40  HLIN O,F AT BURGER
50  PRINT F AT A LIST

In line 30, FAMILY will be a reference to variable FA, which has a value of 123.

In line 40, O will have a value of 3, F will have a value of 9, and BURGER will be treated as a reference to variable BU whose value is 4. In line 50, I would expect that unexpected appearances of keywords AT and LIST will trigger a syntax error.

If memory serves, it's possible to create code which uses reserved words as variable names if one breaks up the words using spaces when typing them. Such spaces will not be preserved when the program is listed, however, so care must be taken when editing lines containing such names.

Typing in:

1 T OMA TO=23
2 PRINT T O

would generate a program that would be listed out as:

1 TOMATO = 23
2  PRINT TO

but typing in line 2 the way it appears in the listing would change it to

2  PRINT  TO

which would yield a syntax error when run [note that tokens are shown both preceded and followed by a space, and in the latter case "TO" is a token but in the former case it isn't].

6

This is the result of the way AppleSoft "parses" programs. From the behavior you described, I can infer that at a high level, AppleSoft executes commands in two steps:

  1. Evaluate arguments to the command (if any)
  2. Execute command

"sagdgg" has no arguments so step 1 is skipped, then in step 2 AppleSoft discovers that there is no such command as "sagdgg" and gives you a syntax error.

"sagdgg P(10)" does have an argument so AppleSoft tries to evaluate it. But while looking up the value in the P array, it finds that the array isn't that large and gives you a bad subscript error.

"P(P(P(P(P(P(P(P(P(P(P(P(P" is a deeply nested argument, and evaluating a nested argument requires use of a stack. The basic reason for this can better be explained with a simpler expression: "X(Y)". To evaluate this you must evaluate Y before you can determine the value of X(Y). Similarly: to evaluate "P(P(P(P(P(P(P(P(P(P(P(P(P", you must first evaluate "P(P(P(P(P(P(P(P(P(P(P(P".

To evaluate that, you must first evaluate "P(P(P(P(P(P(P(P(P(P(P";
To evaluate that, you must first evaluate "P(P(P(P(P(P(P(P(P(P";
To evaluate that, you must first evaluate "P(P(P(P(P(P(P(P(P";
And so on and so forth.

But while doing all that nested evaluation, AppleSoft runs out of stack space, because each time it needs to evaluate a sub-expression it needs to save some information about where it was in the process of evaluating the outer expressions. When the inner-most expression has finally been evaluated it will be able to 'backtrack' and resume evaluation of the next layer expression, and when that's done backtrack to the next layer, etc., until finally the entire expression has been evaluated.

In this case no backtracking happens because AppleSoft runs out of memory first, and gives an out of memory error.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .