{"id":149,"date":"2018-09-07T20:55:40","date_gmt":"2018-09-08T04:55:40","guid":{"rendered":"https:\/\/www.viscerallogic.com\/programming\/blog\/?p=149"},"modified":"2018-09-07T20:55:40","modified_gmt":"2018-09-08T04:55:40","slug":"basic-interpreter-part-vii","status":"publish","type":"post","link":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-vii\/","title":{"rendered":"Basic Interpreter, Part VII"},"content":{"rendered":"<p>This is a continuation of <a href=\"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-vi\/\">Part VI<\/a>. This time, we will be adding the <code>FOR-NEXT<\/code> loop and unary negation.<br \/>\n<!--more--><br \/>\nThe <code>FOR-NEXT<\/code> loop takes a couple forms:<\/p>\n<pre>FOR &lt;VAR&gt; = &lt;START&gt; TO &lt;STOP&gt;\r\n...\r\nNEXT &lt;VAR&gt;\r\n<\/pre>\n<p>or<\/p>\n<pre>FOR &lt;VAR&gt; = &lt;START&gt; TO &lt;STOP&gt; STEP &lt;STEP&gt;\r\n...\r\nNEXT &lt;VAR&gt;\r\n<\/pre>\n<p>In the former case, the step size is set to be 1. In the latter case, it can be any numerical expression, although 0 is generally not a good idea (however, the loop could be exited using <code>IF-THEN<\/code> statements, so we shouldn&#8217;t disallow 0). The variable is a regular global variable, and will be accessible both inside and after the loop. The start\/stop\/step inputs are all arbitrary numerical expressions which do not have to be constant, since they will be evaluated each time through the loop.<\/p>\n<p>Although this could be replaced by the <code>IF-THEN<\/code> and <code>GOTO<\/code> statements we have already implemented, the <code>FOR-NEXT<\/code> construct simplifies things for the BASIC programmer. For the BASIC <em>interpreter<\/em> writer, however, it makes things a little more complicated. Since neither <code>FOR<\/code> nor <code>NEXT<\/code> statements take a line number as input, we have to associate them in our pre-processing. We also have to have a way of determining whether we are on the initial loop, in which case we have to set the loop variable to its start value, or whether we have returned from a <code>NEXT<\/code> statement, in which case we need to increment the variable.<\/p>\n<p>Let&#8217;s start with the <code>For<\/code> class. We will need to implement the usual <code>Program<\/code> functions, as well as a couple new ones for handling <code>NEXT<\/code> statements. We will need to store three <code>DoubleExpression<\/code> pointers: one for the start condition, one for the stop condition, and one for the step size. We also need to store the loop variable name.<\/p>\n<p>Storing the related <code>Next<\/code> instance and a boolean for whether this is the first time through the loop is a little trickier. Logically, it would make sense to have these and instance variables. But since all our instances of <code>Program<\/code> subclasses are <code>const<\/code>, we can&#8217;t modify them after they are created, which we would need to do to update these variables. So instead we will use a couple class variables storing maps between <code>For<\/code> instances and their corresponding <code>Next<\/code> and loop status booleans. Here is the header file, <em>for.h<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#ifndef _FOR_H_\r\n#define _FOR_H_\r\n\r\n#include &lt;string&gt;\r\n#include &lt;map&gt;\r\n\r\n#include \"program.h\"\r\n#include \"doubleexpression.h\"\r\n\r\nclass Next;\r\n\r\n\/*\r\nThis class provides the functionality to handle the FOR\r\nloop statement.\r\n*\/\r\nclass For : public Program {\r\npublic:\r\n\tFor(DoubleExpression *start, DoubleExpression *stop, DoubleExpression *step, std::string var);\r\n\t~For();\r\n\t\r\n\tvoid execute() const;\t\t\t\t\/\/ run this line of the program\r\n\tvoid list(std::ostream&amp; os) const;\t\t\/\/ list this line\r\n\tvoid preExecute() const;\t\t\t\/\/ run before main program execution\r\n\tvoid registerNext(const Next *next) const;\t\/\/ register NEXT statement\r\n\tvoid doNext() const;\t\t\t\t\/\/ called from NEXT statement\r\n\r\nprivate:\r\n\tDoubleExpression *start;\t\t\t\/\/ expression to evaluate to start the loop\r\n\tDoubleExpression *stop;\t\t\t\t\/\/ end condition expression\r\n\tDoubleExpression *step;\t\t\t\t\/\/ step size expression\r\n\tstd::string var;\t\t\t\t\/\/ loop variable name\r\n\tstatic std::map&lt;const For*, const Next*&gt; nextLine;\t\/\/ NEXT statement to jump past when loop terminates\r\n\tstatic std::map&lt;const For*, bool&gt; initial;\t\/\/ is this the first time executing\r\n};\r\n\r\n#endif<\/pre>\n<p>Now let&#8217;s look at the implementation, in <em>for.cpp<\/em>. We start with our necessary <code>include<\/code>s, and define the static variables. The constructor is like most we&#8217;ve done so far, with one addition: we add our new instance to the static <code>initial<\/code> map, setting it to <code>true<\/code>. Likewise in the destructor, we remove the instance from the two static variables (the instance is inserted into <code>nextLine<\/code> elsewhere):<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#include \"for.h\"\r\n#include \"basic.h\"\r\n#include \"next.h\"\r\n\r\nstd::map&lt;const For*, const Next*&gt; For::nextLine;\r\nstd::map&lt;const For*, bool&gt; For::initial;\r\n\r\n\/\/ initialize with all necessary information\r\nFor::For(DoubleExpression *start, DoubleExpression *stop, DoubleExpression *step, std::string var){\r\n\tthis-&gt;start = start;\r\n\tthis-&gt;stop = stop;\r\n\tthis-&gt;step = step;\r\n\tthis-&gt;var = var;\r\n\tinitial[this] = true;\r\n}\r\n\r\n\/\/ clean up pointers\r\nFor::~For(){\r\n\tdelete start;\r\n\tdelete stop;\r\n\tdelete step;\r\n\tinitial.erase(this);\r\n\tnextLine.erase(this);\r\n}<\/pre>\n<p>Next, let&#8217;s look at the <code>execute()<\/code> function implementation:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-lineoffset=\"26\">\/\/ run this line of the program\r\nvoid For::execute() const{\r\n\tdouble s = 1.0;\t\t\t\t\/\/ default step size\r\n\tdouble val;\r\n\t\r\n\tif( step != NULL )\r\n\t\ts = step-&gt;value();\t\t\/\/ evaluate the step every time\r\n\t\r\n\tif( initial[this] ){\t\t\t\/\/ start the loop\r\n\t\tval = start-&gt;value();\r\n\t} else {\t\t\t\/\/ increment the loop\r\n\t\tval = Basic::instance()-&gt;resolve(var) + s;\r\n\t}\r\n\t\r\n\tinitial[this] = true;\t\t\t\/\/ reset\r\n\t\r\n\tBasic::instance()-&gt;assign(var, val);\t\/\/ store the value\r\n\t\r\n\t\/\/ check for loop termination\r\n\tif( (s &gt; 0 &amp;&amp; val &gt; stop-&gt;value()) || (s &lt; 0 &amp;&amp; val &lt; stop-&gt;value()) ){\r\n\t\tBasic::instance()-&gt;gotoProgram(nextLine[this]);\r\n\t}\r\n\t\r\n\tProgram::execute();\t\t\t\/\/ continue to next line\r\n}<\/pre>\n<p>First, we create our local variables for storing the step size and the loop variable value. The <code>FOR<\/code> statement allows the user to omit the <code>STEP<\/code> part, in which case we will pass <code>NULL<\/code> for the <code>DoubleExpression<\/code> pointer, and use <code>1.0<\/code> as the step size.<\/p>\n<p>Then we determine the loop variable value. If it is the first time through the loop (<code>initial[this]<\/code> is true), we evaluate the <code>start<\/code> <code>DoubleExpression<\/code>. Otherwise, we get the stored value of the BASIC variable with the loop variable name, and add the step size value to it. In either case, we then store this value into the BASIC variable with our loop variable name, so it will be available both inside and after the loop. We also set the <code>initial<\/code> value to <code>true<\/code> here. This value is only set to <code>false<\/code> when the corresponding <code>NEXT<\/code> statement is executed, so that if this <code>FOR<\/code> loop is entered just by the program&#8217;s going to the next line or executing a <code>GOTO<\/code>, the loop will start over.<\/p>\n<p>Next we check to see if the loop is done. If the step size is greater than 0, the loop terminates if its value is <em>greater<\/em> than the stop value; if the step size is less than 0, the loop terminates if its value is <em>less<\/em> than the stop value. If the step size is equal to 0, the loop will not terminate on this iteration. If the loop should terminate, we make a call to <code>gotoProgram()<\/code> (which we will implement shortly) on the <code>Basic<\/code> singleton instance, passing it a pointer to the <code>NEXT<\/code> statement instance associated with this <code>FOR<\/code> statement. Otherwise, we continue to the next line (i.e., enter the loop).<\/p>\n<p>Here is the final portion of the <em>for.cpp<\/em> file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-lineoffset=\"52\">\/\/ list this line\r\nvoid For::list(std::ostream&amp; os) const{\r\n\tos &lt;&lt; \"FOR \" &lt;&lt; var &lt;&lt; \" = \" &lt;&lt; start-&gt;list() &lt;&lt; \" TO \" &lt;&lt; stop-&gt;list();\r\n\tif( step != NULL )\r\n\t\tos &lt;&lt; \" STEP \" &lt;&lt; step-&gt;list();\r\n}\r\n\r\n\/\/ run before main program execution\r\nvoid For::preExecute() const{\r\n\tBasic::instance()-&gt;pushFor(this);\r\n}\r\n\r\n\/\/ register NEXT statement\r\nvoid For::registerNext(const Next *next) const{\r\n\tnextLine[this] = next;\r\n}\r\n\r\n\/\/ called from NEXT statement\r\nvoid For::doNext() const{\r\n\tinitial[this] = false;\r\n}\r\n<\/pre>\n<p><code>list()<\/code> prints out a representation of this statement, choosing the appropriate form based on whether a step size expression was supplied. <code>preExecute()<\/code> registers this <code>For<\/code> instance with the <code>Basic<\/code> singleton, where it will be matched with its corresponding <code>Next<\/code> instance when its <code>preExecute()<\/code> function is called. <code>registerNext()<\/code> associates a <code>Next<\/code> instance with this <code>For<\/code> instance in the <code>nextLine<\/code> class variable, which is used by the <code>execute()<\/code> function. And <code>doNext()<\/code> is called by the corresponding <code>NEXT<\/code> statement to set the <code>initial<\/code> boolean mapped to this instance to false, so that the loop variable will be incremented when its <code>execute()<\/code> function is called.<\/p>\n<p>Now, on to the <code>NEXT<\/code> statement! Here is the header file, <em>next.h<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#ifndef _NEXT_H_\r\n#define _NEXT_H_\r\n\r\n#include &lt;string&gt;\r\n#include &lt;map&gt;\r\n\r\n#include \"program.h\"\r\n\r\nclass For;\r\n\r\n\/*\r\nThis class implements the NEXT part of a FOR\/NEXT loop.\r\n*\/\r\nclass Next : public Program {\r\npublic:\r\n\tNext(std::string var);\r\n\t~Next();\r\n\t\r\n\tvoid execute() const;\t\t\t\t\/\/ run this line of the program\r\n\tvoid list(std::ostream&amp; os) const;\t\t\/\/ list this line\r\n\tvoid preExecute() const;\t\t\t\/\/ run before main program execution\r\n\t\r\nprivate:\r\n\tstatic std::map&lt;const Next*, const For*&gt; loop;\t\/\/ FOR loop to jump back to\r\n\tstd::string var;\t\t\t\t\/\/ loop variable name\r\n};\r\n\r\n#endif<\/pre>\n<p>We declare the <code>For<\/code> class so that we can reference it in the class variable <code>loop<\/code>, but we don&#8217;t need to know any of its implementation details at this point. Like in the <code>For<\/code> class, we encounter the limitation of needing to make an association between <code>const<\/code> instances, so we again resort to a class variable. The only instance variable we need is to store the loop variable name.<\/p>\n<p>Here is the implementation, <em>next.cpp<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#include \"next.h\"\r\n#include \"basic.h\"\r\n#include \"for.h\"\r\n\r\nstd::map&lt;const Next*, const For*&gt; Next::loop;\r\n\r\n\/\/ initialize\r\nNext::Next(std::string var){\r\n\tthis-&gt;var = var;\r\n}\r\n\r\n\/\/ clean up\r\nNext::~Next(){\r\n\tloop.erase(this);\r\n}\r\n\r\n\/\/ run this line of the program\r\nvoid Next::execute() const{\r\n\tloop.at(this)-&gt;doNext();\r\n\tBasic::instance()-&gt;gotoProgram(loop[this]);\r\n}\r\n\r\n\/\/ list this line\r\nvoid Next::list(std::ostream&amp; os) const{\r\n\tos &lt;&lt; \"NEXT \" &lt;&lt; var;\r\n}\r\n\r\n\/\/ run before main program execution\r\nvoid Next::preExecute() const{\r\n\tloop[this] = Basic::instance()-&gt;popFor();\r\n\tloop.at(this)-&gt;registerNext(this);\r\n}<\/pre>\n<p>Since we have a <code>static<\/code> variable <code>loop<\/code> declared in the header file, we must define it here. The constructor receives and stores the loop variable name. The destructor removes this instance from the <code>loop<\/code> map. <code>execute()<\/code> tells the associated <code>For<\/code> instance that it is being called from a <code>Next<\/code> instance, so that its loop variable will be incremented, and then moves program execution to that statement. <code>list()<\/code> does the expected printing of the BASIC statement. <code>preExecute()<\/code> requests the associated <code>For<\/code> pointer from the <code>Basic<\/code> singleton instance, and then registers itself with it.<\/p>\n<p>Now we will look at the changes in the <code>Basic<\/code> class. In the header file, include the <code>stack<\/code> STL header, and declare the <code>For<\/code> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-lineoffset=\"6\" data-enlighter-highlight=\"9,14\">...\r\n#include &lt;vector&gt;\r\n#include &lt;deque&gt;\r\n#include &lt;stack&gt;\r\n\r\n#include \"program.h\"\r\n#include \"doubleexpression.h\"\r\n\r\nclass For;\r\n\r\n...<\/pre>\n<p>Add three new function declarations needed by the <code>FOR-NEXT<\/code> statements:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-highlight=\"34,38,39\" data-enlighter-lineoffset=\"31\" data-enlighter-language=\"cpp\">\t...\r\n\tvoid gotoLine(int line);\t\t\t\/\/ jump to program line\r\n\tvoid nextLine();\t\t\t\t\/\/ go to next program line\r\n\tvoid gotoProgram(const Program *program);\t\/\/ go to program line\r\n\tvoid endProgram();\t\t\t\t\/\/ end execution\r\n\tvoid read(std::string var);\t\t\t\/\/ assign next data value to var\r\n\tvoid pushData(std::vector&lt;double&gt; vals);\t\/\/ push more values onto data vector\r\n\tvoid pushFor(const For *forLoop);\t\t\/\/ push a FOR loop onto the stack\r\n\tconst For *popFor();\t\t\t\t\/\/ pop last FOR off the stack\r\n\t...<\/pre>\n<p>And define the <code>forLoops<\/code> variable, which uses a <code>stack<\/code> to keep track of which <code>FOR<\/code> statement is associated with which <code>NEXT<\/code> statement:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-highlight=\"52\" data-enlighter-lineoffset=\"49\">\t...\r\n\tstd::map&lt;int, const Program*&gt;::iterator counter;\t\/\/ program line to run next\r\n\tstd::deque&lt;double&gt; data;\t\t\t\t\/\/ stored data block for READ\r\n\tstd::stack&lt;const For*&gt; forLoops;\t\t\t\/\/ stack for registering FOR\/NEXT statements\r\n\t...<\/pre>\n<p>Now let&#8217;s write the implementations for these functions. The first, <code>gotoProgram()<\/code>, takes a pointer to a <code>Program<\/code> instance, and jumps to that location in the <code>lines<\/code> map. This is function is needed so that statements can reference each other without knowing line numbers. The logic is pretty simple: iterate through the entries until the specified pointer is found, and then set the <code>counter<\/code> iterator:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\/\/ go to program line\r\nvoid Basic::gotoProgram(const Program *program){\r\n\tfor( map&lt;int, const Program *&gt;::iterator it = lines.begin(); it!= lines.end(); ++it ){\r\n\t\tif( it-&gt;second == program )\r\n\t\t\tcounter = it;\r\n\t}\r\n}<\/pre>\n<p>For keeping track of <code>FOR-NEXT<\/code> associations, we have the <code>forLoops<\/code> stack. Each time a <code>FOR<\/code> statement is encountered, the <code>For<\/code> instance that is created will push itself onto the stack. When a <code>NEXT<\/code> statement is encountered, its <code>Next<\/code> instance will take the top <code>For<\/code> instance from the stack and associate itself. This allows for nested loops to be correctly linked. Technically, the variable name passed to the <code>NEXT<\/code> statement is not needed, since it will link to the most recent <code>FOR<\/code> statement regardless, but it makes a handy visual reference for the BASIC code writer. Here are the two functions for pushing and popping instances on the <code>forLoops<\/code> stack:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\/\/ push a FOR loop onto the stack\r\nvoid Basic::pushFor(const For *forLoop){\r\n\tforLoops.push(forLoop);\r\n}\r\n\r\n\/\/ pop last FOR off the stack\r\nconst For* Basic::popFor(){\r\n\tconst For *loop = forLoops.top();\r\n\tforLoops.pop();\r\n\treturn loop;\r\n}<\/pre>\n<p>Now that we have our logic implemented, we need to update our parsing and grammar. In the flex input file, add four new token parsers:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">...\r\nFOR\t\t\t{ return FOR; }\r\nTO\t\t\t{ return TO; }\r\nSTEP\t\t\t{ return STEP; }\r\nNEXT\t\t\t{ return NEXT; }\r\n...<\/pre>\n<p>In the Bison input file, start by including the two new header files:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">...\r\n#include \"for.h\"\r\n#include \"next.h\"\r\n...<\/pre>\n<p>Define the four new constant tokens:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">...\r\n%token FOR\r\n%token TO\r\n%token STEP\r\n%token NEXT\r\n...<\/pre>\n<p>And update the <code>program<\/code> rule to recognize the two forms of <code>FOR<\/code> statement and the <code>NEXT<\/code> statement:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-highlight=\"13-19\" data-enlighter-linenumbers=\"false\">program:\r\n\tPRINT exprList\t\t\t{ $$ = new Print($2); }\r\n\t| LET VAR EQUAL doubleExpr\t{\r\n\t\t\t\t\t\t$$ = new Let($2, $4);\r\n\t\t\t\t\t\tfree($2);\t\/\/ malloced in basic.l\r\n\t\t\t\t\t}\r\n\t| GOTO INT\t\t\t{ $$ = new Goto($2); }\r\n\t| END\t\t\t\t{ $$ = new End(); }\r\n\t| IF doubleExpr comp doubleExpr THEN INT\r\n\t\t\t\t\t{ $$ = new IfThen($2, $4, $3, $6); }\r\n\t| READ stringList\t\t{ $$ = new Read(*$2); }\r\n\t| DATA doubleList\t\t{ $$ = new Data(*$2); }\r\n\t| FOR VAR EQUAL doubleExpr TO doubleExpr {\r\n\t\t\t\t\t\t$$ = new For($4, $6, NULL, $2);\r\n\t\t\t\t\t}\r\n\t| FOR VAR EQUAL doubleExpr TO doubleExpr STEP doubleExpr {\r\n\t\t\t\t\t\t$$ = new For($4, $6, $8, $2);\r\n\t\t\t\t\t}\r\n\t| NEXT VAR\t\t\t{ $$ = new Next($2); }\r\n;<\/pre>\n<p>Add the new header and implementation files to your Makefile, and you can now create and run for loops:<\/p>\n<pre>Welcome to BASIC!\r\nEnter a program name: loop\r\n&gt;10 for a = 1 to 3\r\n&gt;20 for b = 2 to 6 step 2\r\n&gt;30 print a*b\r\n&gt;40 next b\r\n&gt;50 next a\r\n&gt;run\r\n2.000000\r\n4.000000\r\n6.000000\r\n4.000000\r\n8.000000\r\n12.000000\r\n6.000000\r\n12.000000\r\n18.000000<\/pre>\n<p>However, if you enter a negative value for the step size, you get a syntax error:<\/p>\n<pre>&gt;10 loop for a = 3 to 1 step -1\r\nError: syntax error<\/pre>\n<p>We never implement the unary negation operator! You could sidestep this by using <em>(0-1)<\/em> as an expression instead, but we should really support unary negation.<\/p>\n<p>First, update the <code>OperatorExpression<\/code> implementation. We will now allow <code>'n'<\/code> to be passed as the operator character, and <code>NULL<\/code> to be passed as the second <code>DoubleExpression<\/code>, so we need to make sure we don&#8217;t try to delete it in our destructor if it doesn&#8217;t exist:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-highlight=\"3,4\" data-enlighter-linenumbers=\"false\">OperatorExpression::~OperatorExpression(){\r\n\tdelete a;\r\n\tif( b != NULL )\r\n\t\tdelete b;\r\n}<\/pre>\n<p>The <code>list()<\/code> function now needs to check whether it&#8217;s printing out a unary or binary operator:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-highlight=\"2-5\" data-enlighter-linenumbers=\"false\">const std::string OperatorExpression::list() const{\r\n\tif( op != 'n' )\r\n\t\treturn a-&gt;list() + op + b-&gt;list();\r\n\telse\r\n\t\treturn \"-\" + a-&gt;list();\r\n}<\/pre>\n<p>Lastly, we need to update the <code>value()<\/code> function:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-highlight=\"13,14\" data-enlighter-linenumbers=\"false\">double OperatorExpression::value() const{\r\n\tswitch( op ){\r\n\t\tcase '+':\r\n\t\t\treturn a-&gt;value() + b-&gt;value();\r\n\t\tcase '-':\r\n\t\t\treturn a-&gt;value() - b-&gt;value();\r\n\t\tcase '*':\r\n\t\t\treturn a-&gt;value() * b-&gt;value();\r\n\t\tcase '\/':\r\n\t\t\treturn a-&gt;value() \/ b-&gt;value();\r\n\t\tcase '^':\r\n\t\t\treturn exp(log(a-&gt;value()) * b-&gt;value());\r\n\t\tcase 'n':\r\n\t\t\treturn -a-&gt;value();\r\n\t}\r\n}<\/pre>\n<p>That takes care of the logic, and since we already have a token for the minus sign, we now update <em>basic.y<\/em> to recognize it as a unary operation. Due to mathematical precedence rules, the new rule gets put into the <code>mulExpr<\/code> rule:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-highlight=\"5\" data-enlighter-linenumbers=\"false\">mulExpr:\r\n\texpExpr\r\n\t| expExpr MULT expExpr\t{ $$ = new OperatorExpression($1, $3, '*'); }\r\n\t| expExpr DIV expExpr\t{ $$ = new OperatorExpression($1, $3, '\/'); }\r\n\t| MINUS expExpr\t\t{ $$ = new OperatorExpression($2, NULL, 'n'); }\r\n;<\/pre>\n<p>Recompile, and you can now run loops with negative step sizes:<\/p>\n<pre>&gt;10 for a = 3 to 1 step -1\r\n&gt;20 print a\r\n&gt;30 next a\r\n&gt;run\r\n3.000000\r\n2.000000\r\n1.000000<\/pre>\n<p>As always, the full source is available here: <a href=\"https:\/\/github.com\/VisceralLogic\/basic\/tree\/part-7\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/VisceralLogic\/basic\/tree\/part-7<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a continuation of Part VI. This time, we will be adding the FOR-NEXT loop and unary negation.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false},"categories":[12,16,13,15],"tags":[],"jetpack_featured_media_url":"","jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p9npkn-2p","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":111,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-v\/","url_meta":{"origin":149,"position":0},"title":"BASIC Interpreter, Part V","date":"September 7, 2018","format":false,"excerpt":"This is a continuation of Part IV. In Part V we will add support for parentheses in mathematical expressions, add the GOTO and END statements, and implement the remaining program storage statements: CATALOG, SCRATCH, and RENAME. Now that we have a framework for supporting numerical operations, adding parentheses is not\u2026","rel":"","context":"In &quot;BASIC&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":131,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-vi\/","url_meta":{"origin":149,"position":1},"title":"BASIC Interpreter, Part VI","date":"September 7, 2018","format":false,"excerpt":"This is a continuation of Part V. In the previous section, we added support for the GOTO statement. Since we don't yet have any control logic, that is not very useful, but it does lay the infrastructure for one of the features we will add this time: IF-THEN. We will\u2026","rel":"","context":"In &quot;BASIC&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":90,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-iv\/","url_meta":{"origin":149,"position":2},"title":"BASIC Interpreter, Part IV","date":"September 7, 2018","format":false,"excerpt":"This is a continuation of Part III. This time we will add some mathematical operators, the ability to save and load programs, and support numerical variables. To enable mathematical operations, we will create a subclass of DoubleExpression that takes two DoubleExpressions as inputs, as well as a character code signifying\u2026","rel":"","context":"In &quot;BASIC&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":72,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpeter-part-iii\/","url_meta":{"origin":149,"position":3},"title":"BASIC Interpeter, Part III","date":"September 7, 2018","format":false,"excerpt":"This is a continuation of Part II. In this part, we will add support for numerical as well as string expressions, support multiple expression in a PRINT statement, and add functionality for deleting program lines. Let's start with the Basic class header file, basic.h. All we need to do here\u2026","rel":"","context":"In &quot;BASIC&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":5,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/guitar-chords-to-midi-in-objective-c\/","url_meta":{"origin":149,"position":4},"title":"Guitar Chords to MIDI in Objective-C","date":"December 3, 2005","format":false,"excerpt":"This tutorial will show you how to write a program that creates MIDI files of guitar chords by processing text files. Although I wrote this in Objective-C and the GUI is built using Cocoa, the MIDI algorithms could easily be applied to another language or platform. Essentially, this program scans\u2026","rel":"","context":"In &quot;Languages&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/numerical-expression-solver-in-java\/","url_meta":{"origin":149,"position":5},"title":"Numerical Expression Solver in Java","date":"November 12, 2005","format":false,"excerpt":"This tutorial will show you how to write a Java program that takes a string input such as \"3 + 4^2*7.5E-1*sin(22)\" and convert it into a numerical answer, 2.893784 in this case, which you can use for whatever purpose you like. This Java Applet utilizes the Expression class that you\u2026","rel":"","context":"In &quot;Java&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/posts\/149"}],"collection":[{"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/comments?post=149"}],"version-history":[{"count":7,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/posts\/149\/revisions"}],"predecessor-version":[{"id":170,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/posts\/149\/revisions\/170"}],"wp:attachment":[{"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/media?parent=149"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/categories?post=149"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/tags?post=149"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}