{"id":131,"date":"2018-09-07T20:54:32","date_gmt":"2018-09-08T04:54:32","guid":{"rendered":"https:\/\/www.viscerallogic.com\/programming\/blog\/?p=131"},"modified":"2018-09-07T20:56:21","modified_gmt":"2018-09-08T04:56:21","slug":"basic-interpreter-part-vi","status":"publish","type":"post","link":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-vi\/","title":{"rendered":"BASIC Interpreter, Part VI"},"content":{"rendered":"<p>This is a continuation of <a href=\"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-v\/\">Part V<\/a>. In the previous section, we added support for the <code>GOTO<\/code> statement. Since we don&#8217;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: <code>IF-THEN<\/code>. We will also add the <code>READ<\/code> and <code>DATA<\/code> statements.<br \/>\n<!--more--><\/p>\n<p>Following the BASIC guide we are using, an <code>IF-THEN<\/code> statement takes the following form: <code>&lt;LINE&gt; IF &lt;EXPRESSION&gt; &lt;RELATION&gt; &lt;EXPRESSION&gt; THEN &lt;LINE&gt;<\/code>. I.e., compare two expressions using some test operator, and if the result is true, jump to the specified line number; otherwise continue to the next line. We have already defined a token for the <code>=<\/code> operator for use in the <code>LET<\/code> statement, but we will need to add tokens for the remaining comparisons: <code>&lt;<\/code>, <code>&gt;<\/code>, <code>&lt;=<\/code>, <code>&gt;=<\/code>, and <code>&lt;&gt;<\/code>.<\/p>\n<p>Let&#8217;s start by creating a class to handle the <code>IF-THEN<\/code> statement. <code>IfThen<\/code> will be a subclass of <code>Program<\/code>; it will store pointers to two <code>DoubleExpression<\/code>s to be evaluated at run time, which comparison is to be performed, and the line number to jump to if the comparison is successful. There are various ways of indicating which operation is to be performed; in this case, I have chosen to store it as a C-style string; using an <code>enum<\/code> would be another good option. Here is the header file, <em>ifthen.h:<\/em><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#ifndef _IFTHEN_H_\r\n#define _IFTHEN_H_\r\n\r\n#include \"program.h\"\r\n#include \"doubleexpression.h\"\r\n\r\n\/*\r\nThis class provides support for the IF-THEN statement.\r\n*\/\r\nclass IfThen : public Program {\r\npublic:\r\n\tIfThen(DoubleExpression *a, DoubleExpression *b, char *op, int line);\r\n\t~IfThen();\r\n\t\r\n\tvoid execute() const;\t\t\t\/\/ run this line of the program\r\n\tvoid list(std::ostream&amp; os) const;\t\/\/ list this line\r\n\r\nprivate:\r\n\tDoubleExpression *a, *b;\r\n\tchar *op;\r\n\tint line;\r\n};\r\n\r\n#endif<\/pre>\n<p>The implementation is pretty straightforward. The constructor stores all the member variables, the destructor deletes the <code>DoubleExpression<\/code>s, <code>execute()<\/code> performs the comparison operation and jumps to the appropriate line if it succeeds, and <code>list()<\/code> prints out the statement (which is simplified since we stored the operator as a c-string). So here is <em>ifthen.cpp:<\/em><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#include &lt;cstring&gt;\r\n\r\n#include \"ifthen.h\"\r\n#include \"basic.h\"\r\n\r\n\/\/ create a new statement instance\r\nIfThen::IfThen(DoubleExpression *a, DoubleExpression *b, char *op, int line){\r\n\tthis-&gt;a = a;\r\n\tthis-&gt;b = b;\r\n\tthis-&gt;op = op;\r\n\tthis-&gt;line = line;\r\n}\r\n\r\n\/\/ clean up the expression pointers\r\nIfThen::~IfThen(){\r\n\tdelete a;\r\n\tdelete b;\r\n}\r\n\r\n\/\/ run this line of the program\r\nvoid IfThen::execute() const{\r\n\tdouble aVal = a-&gt;value();\r\n\tdouble bVal = b-&gt;value();\r\n\tbool result = false;\r\n\t\r\n\tif( strcmp(op, \"=\") == 0 )\r\n\t\tresult = aVal == bVal;\r\n\telse if( strcmp(op, \"&lt;\") == 0 )\r\n\t\tresult = aVal &lt; bVal;\r\n\telse if( strcmp(op, \"&gt;\") == 0 )\r\n\t\tresult = aVal &gt; bVal;\r\n\telse if( strcmp(op, \"&lt;=\") == 0 )\r\n\t\tresult = aVal &lt;= bVal;\r\n\telse if( strcmp(op, \"&gt;=\") == 0 )\r\n\t\tresult = aVal &gt;= bVal;\r\n\telse if( strcmp(op, \"&lt;&gt;\") == 0 )\r\n\t\tresult = aVal != bVal;\r\n\t\r\n\tif( result )\r\n\t\tBasic::instance()-&gt;gotoLine(line);\r\n\telse\r\n\t\tProgram::execute();\r\n}\r\n\r\n\/\/ list this line\r\nvoid IfThen::list(std::ostream&amp; os) const{\r\n\tos &lt;&lt; \"IF \" &lt;&lt; a-&gt;list() &lt;&lt; ' ' &lt;&lt; op &lt;&lt; ' ';\r\n\tos &lt;&lt; b-&gt;list() &lt;&lt; \" THEN \" &lt;&lt; line;\r\n}<\/pre>\n<p>Next, we need to add support in our Bison input file. First, make sure to include the new <code>IfThen<\/code> header file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">#include \"ifthen.h\"<\/pre>\n<p>We already have a <code>EQUAL<\/code> token defined for the <code>LET<\/code> assignment statement, and we will re-use it here since it is the same character. We need to add tokens for <code>IF<\/code>, <code>THEN<\/code>, and the remaining comparison operators:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">%token IF\r\n%token THEN\r\n%token LESS\r\n%token GREATER\r\n%token LESSEQUAL\r\n%token GREATEREQUAL\r\n%token NOTEQUAL<\/pre>\n<p>We somehow need to convert these tokens into C-strings to pass to the <code>IfThen<\/code> class, so we will create a new non-terminal token <code>comp<\/code> that will be an <code>sVal<\/code> type to store the operator:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">%type &lt;sVal&gt; comp<\/pre>\n<p>Create the rule for our new <code>comp<\/code> symbol:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\" data-enlighter-language=\"cpp\">comp:\r\n\tEQUAL\t\t\t{ $$ = \"=\"; }\r\n\t| LESS\t\t\t{ $$ = \"&lt;\"; }\r\n\t| GREATER\t\t{ $$ = \"&gt;\"; }\r\n\t| LESSEQUAL\t\t{ $$ = \"&lt;=\"; }\r\n\t| GREATEREQUAL\t\t{ $$ = \"&gt;=\"; }\r\n\t| NOTEQUAL\t\t{ $$ = \"&lt;&gt;\"; }\r\n;<\/pre>\n<p>And now update the <code>program<\/code> rule to recognize <code>IF-THEN<\/code> statements:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-highlight=\"9-10\" 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;<\/pre>\n<p>Now, on to the flex input file. Add scanners for the new tokens defined in the Bison input file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">IF\t\t\t{ return IF; }\r\nTHEN\t\t\t{ return THEN; }\r\n\\&lt;\t\t\t{ return LESS; }\r\n\\&gt;\t\t\t{ return GREATER; }\r\n\\&lt;\\=\t\t\t{ return LESSEQUAL; }\r\n\\&gt;\\=\t\t\t{ return GREATEREQUAL; }\r\n\\&lt;\\&gt;\t\t\t{ return NOTEQUAL; }<\/pre>\n<p>Finally, add the new files in your Makefile. You can now run programs like this:<\/p>\n<pre>Welcome to BASIC!\r\nEnter a program name: test\r\n&gt;10 if 1 &lt; 2 then 30\r\n&gt;20 print \"1 &gt; 2\"\r\n&gt;30 if 1 = 1 then 50\r\n&gt;40 print \"1 &lt;&gt; 1\"\r\n&gt;50 if 2 &gt; 1 then 70\r\n&gt;60 print \"2 &lt; 1\"\r\n&gt;70 if 1 &lt;= 2 then 90\r\n&gt;80 print \"1 &gt; 2\"\r\n&gt;90 if 2 &gt;= 1 then 110\r\n&gt;100 print \"2 &lt; 1\"\r\n&gt;110 if 1 &lt;&gt; 2 then 130\r\n&gt;120 print \"1 = 2\"\r\n&gt;130 end\r\n&gt;run\r\n&gt;<\/pre>\n<p>Adding support for <code>READ<\/code> and <code>DATA<\/code> will require some reworking of how we do things. Prior to the program running, all the <code>DATA<\/code> statements must already be evaluated so their values can be stored and ready for any <code>READ<\/code> statement. We will accomplish this by adding a <em>pre-evaluation<\/em> loop before the main execution loop. But first, we will add storage for the <code>DATA<\/code> values and functions to read\/write them. We will store the values in a <code>std::deque<\/code>, which implements a <em>first-in-first-out<\/em> queue.<\/p>\n<p>Start by including the header files for <code>std::vector<\/code> and <code>std::deque<\/code> in <em>basic.h<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\" data-enlighter-highlight=\"4-5\">#include &lt;map&gt;\r\n#include &lt;string&gt;\r\n#include &lt;iostream&gt;\r\n#include &lt;vector&gt;\r\n#include &lt;deque&gt;\r\n\r\n#include \"program.h\"\r\n#include \"doubleexpression.h\"\r\n<\/pre>\n<p>Next, declare functions for the <code>READ<\/code> and <code>DATA<\/code> statements. <code>read()<\/code> will take as input a variable name, and assign to it the next value taken from a <code>DATA<\/code> statement. <code>pushData()<\/code> will take a vector of doubles, and put them into the data value deque:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\" data-enlighter-highlight=\"5,6\">public:\r\n\r\n...\r\n\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<\/pre>\n<p>Finally, add a private member variable to store the <code>DATA<\/code> values:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\" data-enlighter-highlight=\"5\">private:\r\n\r\n...\r\n\r\n\tstd::deque&lt;double&gt; data;\t\t\t\t\t\t\t\/\/ stored data block for READ<\/pre>\n<p>Moving on to the implementation in <em>basic.cpp<\/em>, add the two new functions. <code>read()<\/code> will take advantage of our existing <code>assign()<\/code> function. <code>pushData()<\/code> will iterate through the values in its input vector and push them onto the <code>data<\/code> variable:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\/\/ assign next data value to var\r\nvoid Basic::read(std::string var){\r\n\tassign(var, data.front());\r\n\tdata.pop_front();\r\n}\r\n\r\n\/\/ push more values onto data vector\r\nvoid Basic::pushData(std::vector&lt;double&gt; vals){\r\n\tfor( std::vector&lt;double&gt;::iterator it = vals.begin(); it != vals.end(); ++it ){\r\n\t\tdata.push_back(*it);\r\n\t}\r\n}<\/pre>\n<p>We also need to modify the <code>execute()<\/code> function to add our pre-evaluation loop. This will run through all the <code>Program<\/code> instances stored in our <code>lines<\/code> map and call <code>preExecute()<\/code>, a function which we will add to the <code>Program<\/code> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\" data-enlighter-highlight=\"3-6\">\/\/ run the program\r\nvoid Basic::execute(){\r\n\tdata.clear(); \/\/ clear any existing stored data\r\n\tfor( map&lt;int, const Program *&gt;::iterator it = lines.begin(); it!= lines.end(); ++it ){\r\n\t\tit-&gt;second-&gt;preExecute();\r\n\t}\r\n \r\n\tcounter = lines.begin();\r\n\twhile( counter != lines.end() )\r\n\t\tcounter-&gt;second-&gt;execute();\r\n}<\/pre>\n<p>Next, we&#8217;ll add the <code><code>preExecute()<code> function to our <code>Program<\/code> class. Here is the new signature in the header file, <\/code><\/code><\/code><em>program.h<\/em><code><code>:<\/code><\/code><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\" data-enlighter-highlight=\"5\">class Program{\r\npublic:\r\n\tvirtual void execute() const;\t\t\t\/\/ run this line of the program\r\n\tvirtual void list(std::ostream&amp; os) const;\t\/\/ list this line\r\n\tvirtual void preExecute() const;\t\t\/\/ run before main program execution\r\n};<\/pre>\n<p>Since this function is only used by one specialized subclass, the implementation in <em>program.cpp<\/em> doesn&#8217;t do anything:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\/\/ nothing to do here...\r\nvoid Program::preExecute() const{\r\n}<\/pre>\n<p>Now we will add the <code>Data<\/code> class to handle the <code>DATA<\/code> statement. Like usual, it will be a subclass of <code>Program<\/code>. Unlike usual, it will not override the <code>execute()<\/code> function, since it only has activity in the <code>preExecute()<\/code> phase. Here is the header file, <em>data.h<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#ifndef _DATA_H_\r\n#define _DATA_H_\r\n\r\n#include &lt;vector&gt;\r\n\r\n#include \"program.h\"\r\n\r\n\/*\r\nThis class implements the DATA statement, storing numbers\r\nfor later use by READ.\r\n*\/\r\nclass Data : public Program {\r\npublic:\r\n\tData(std::vector&lt;double&gt; vals);\r\n\t\r\n\t\/\/ use parent 'execute' implementation\r\n\tvoid list(std::ostream&amp; os) const;\t\/\/ list this line\r\n\tvoid preExecute() const;\t\t\/\/ run before main program execution\r\n\r\nprivate:\r\n\tstd::vector&lt;double&gt; vals;\t\t\/\/ doubles to be stored\r\n};\r\n\r\n#endif<\/pre>\n<p>In the implementation, the constructor will take a vector of doubles, and store it in <code>val<\/code>. The <code>list()<\/code> function will do the normal listing of the statement, and <code>preExecute()<\/code> will load the numerical values into the <code>Basic<\/code> data storage variable. Note that because <code>list()<\/code> is declared <code>const<\/code>, we must use a <code>const_iterator<\/code> access to the member variable <code>vals<\/code>, along with the corresponding <code>cbegin()<\/code> and <code>cend()<\/code> iterator functions. Here is <em>data.cpp<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#include \"data.h\"\r\n#include \"basic.h\"\r\n\r\nData::Data(std::vector&lt;double&gt; vals){\r\n\tthis-&gt;vals = vals;\r\n}\r\n\r\n\/\/ list this line\r\nvoid Data::list(std::ostream&amp; os) const{\r\n\tos &lt;&lt; \"DATA \";\r\n\tstd::vector&lt;double&gt;::const_iterator it = vals.cbegin();\r\n\tos &lt;&lt; *it;\t\t\/\/ print out first value\r\n\tfor(  ++it; it != vals.cend(); ++it ){\r\n\t\tos &lt;&lt; \", \" &lt;&lt; *it; \/\/ print out remaining values\r\n\t}\r\n}\r\n\r\n\/\/ run before main program execution\r\nvoid Data::preExecute() const{\r\n\tBasic::instance()-&gt;pushData(vals);\r\n}<\/pre>\n<p>The <code>Read<\/code> class also subclasses <code>Program<\/code>. It stores a vector of strings representing variables names to be assigned values from a <code>DATA<\/code> statement. Here is the header file, <em>read.h:<\/em><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#ifndef _READ_H_\r\n#define _READ_H_\r\n\r\n#include &lt;vector&gt;\r\n#include &lt;string&gt;\r\n\r\n#include \"program.h\"\r\n\r\n\/*\r\nThis class supports the READ statement, putting pre-stored DATA\r\ninto specified variables.\r\n*\/\r\nclass Read : public Program {\r\npublic:\r\n\tRead(std::vector&lt;std::string&gt; vars);\r\n\t\r\n\tvoid execute() const;\t\t\t\/\/ run this line of the program\r\n\tvoid list(std::ostream&amp; os) const;\t\/\/ list this line\r\n\r\nprivate:\r\n\tstd::vector&lt;std::string&gt; vars;\t\t\/\/ variables names to receive values\r\n};\r\n\r\n#endif<\/pre>\n<p>Here is the implementation, <em>read.cpp<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#include \"read.h\"\r\n#include \"basic.h\"\r\n\r\nRead::Read(std::vector&lt;std::string&gt; vars){\r\n\tthis-&gt;vars = vars;\r\n}\r\n\r\n\/\/ run this line of the program\r\nvoid Read::execute() const{\r\n\tfor( std::vector&lt;std::string&gt;::const_iterator it = vars.cbegin(); it != vars.cend(); ++it ){\r\n\t\tBasic::instance()-&gt;read(*it);\r\n\t}\r\n\tProgram::execute();\r\n}\r\n\r\n\/\/ list this line\r\nvoid Read::list(std::ostream&amp; os) const{\r\n\tos &lt;&lt; \"READ \";\r\n\tstd::vector::const_iterator it = vars.cbegin();\r\n\tos &lt;&lt; *it;\t\t\/\/ print out first value\r\n\tfor(  ++it; it != vars.cend(); ++it ){\r\n\t\tos &lt;&lt; \", \" &lt;&lt; *it;\t\/\/ print out remaining values\r\n\t}\r\n\r\n}\r\n<\/pre>\n<p>That is all for the C++ classes, so we will now move on to the flex and Bison files. The flex change for this is very simple, we just need to read and return two new tokens that will be defined in the Bison input file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">DATA\t\t\t{ return DATA; }\r\nREAD\t\t\t{ return READ; }<\/pre>\n<p>In the Bison input file, first include our two new header files:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\" data-enlighter-language=\"cpp\">#include \"read.h\"\r\n#include \"data.h\"<\/pre>\n<p>Next, we need to add a couple new types to the token union definition, one for string lists, and one for double lists:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\" data-enlighter-language=\"cpp\" data-enlighter-highlight=\"10,11\">\/\/ token type definition\r\n%union {\r\n\tint iVal;\r\n\tdouble dVal;\r\n\tchar *sVal;\r\n\tProgram *progVal;\r\n\tExpression *eVal;\r\n\tDoubleExpression *dxVal;\r\n\tstd::vector&lt;Expression*&gt; *eList;\r\n\tstd::vector&lt;std::string&gt; *sList;\r\n\tstd::vector&lt;double&gt; *dList;\r\n}<\/pre>\n<p>Create two new constant tokens for the new statements:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">%token DATA\r\n%token READ<\/pre>\n<p>Add two new non-terminal symbols for new rules we will create to handle string lists and double lists:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\">%type &lt;sList&gt; stringList\r\n%type &lt;dList&gt; doubleList<\/pre>\n<p>Extend the <code>program<\/code> rule to handle our new statements, making use of our new constant tokens and non-terminal symbols:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\" data-enlighter-language=\"cpp\" data-enlighter-highlight=\"5,6\">program:\r\n\r\n...\r\n\r\n\t| READ stringList\t\t{ $$ = new Read(*$2); }\r\n\t| DATA doubleList\t\t{ $$ = new Data(*$2); }\r\n;<\/pre>\n<p>Finally, we need to add the rules for our new <code>stringList<\/code> and <code>doubleList<\/code> non-terminal symbols. Similarly to the <code>exprList<\/code> rule we already have, the <code>stringList<\/code> will consist of one <code>VAR<\/code> symbol, optionally followed by any number of <code>COMMA VAR<\/code> pairs. The <code>doubleList<\/code> actually needs to be able to handle integers as well as floating point numbers, so it will consist of either an <code>INT<\/code> or a <code>DOUBLE<\/code> token to start with, optionally followed by more <code>INT<\/code> and\/or <code>DOUBLE<\/code> tokens, separated again by commas:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-linenumbers=\"false\" data-enlighter-language=\"cpp\">stringList:\r\n\tVAR\t\t\t\t{ $$ = new std::vector(1, $1); }\r\n\t| stringList COMMA VAR\t\t{\r\n\t\t\t\t\t\t$1-&gt;push_back($3);\r\n\t\t\t\t\t\t$$ = $1;\r\n\t\t\t\t\t}\r\n;\r\n\r\ndoubleList:\r\n\tDOUBLE\t\t\t\t{ $$ = new std::vector(1, $1); }\r\n\t| INT\t\t\t\t{ $$ = new std::vector(1, $1); }\r\n\t| doubleList COMMA DOUBLE\t{\r\n\t\t\t\t\t\t$1-&gt;push_back($3);\r\n\t\t\t\t\t\t$$ = $1;\r\n\t\t\t\t\t}\r\n\t| doubleList COMMA INT\t\t{\r\n\t\t\t\t\t\t$1-&gt;push_back($3);\r\n\t\t\t\t\t\t$$ = $1;\r\n\t\t\t\t\t}\r\n;<\/pre>\n<p>That&#8217;s all the code. Now add the new <code>Read<\/code> and <code>Data<\/code> class files to your <em>Makefile, and build and run. Here is a sample session:<\/em><\/p>\n<pre>Welcome to BASIC!\r\nEnter a program name: readdata\r\n&gt;10 data 1\r\n&gt;20 read x, y\r\n&gt;40 print x, y\r\n&gt;50 data 2\r\n&gt;run\r\n1.000000 2.000000<\/pre>\n<p>As always, the complete source files are available here: <a href=\"https:\/\/github.com\/VisceralLogic\/basic\/tree\/part-6\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/VisceralLogic\/basic\/tree\/part-6<\/a><\/p>\n<p>Continue to\u00a0<a href=\"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-vii\/\">Part VII<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a continuation of Part V. In the previous section, we added support for the GOTO statement. Since we don&#8217;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 also add the READ and [&hellip;]<\/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-27","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":149,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-vii\/","url_meta":{"origin":131,"position":0},"title":"Basic Interpreter, Part VII","date":"September 7, 2018","format":false,"excerpt":"This is a continuation of Part VI. This time, we will be adding the FOR-NEXT loop and unary negation. The FOR-NEXT loop takes a couple forms: FOR <VAR> = <START> TO <STOP> ... NEXT <VAR> or FOR <VAR> = <START> TO <STOP> STEP <STEP> ... NEXT <VAR> In the former\u2026","rel":"","context":"In &quot;BASIC&quot;","img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":46,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-ii\/","url_meta":{"origin":131,"position":1},"title":"BASIC Interpreter, Part II","date":"September 7, 2018","format":false,"excerpt":"This is a continuation of Part I. In Part II, we will add functionality to store and run BASIC programs, although still limited to the PRINT statement. We will also be adding a LIST statement to print out the currently stored program. We will be adding a number of new\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":131,"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":111,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-v\/","url_meta":{"origin":131,"position":3},"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":72,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpeter-part-iii\/","url_meta":{"origin":131,"position":4},"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":3,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/numerical-expression-solver-in-java\/","url_meta":{"origin":131,"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\/131"}],"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=131"}],"version-history":[{"count":10,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/posts\/131\/revisions"}],"predecessor-version":[{"id":171,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/posts\/131\/revisions\/171"}],"wp:attachment":[{"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/media?parent=131"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/categories?post=131"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/tags?post=131"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}