{"id":90,"date":"2018-09-07T20:52:24","date_gmt":"2018-09-08T04:52:24","guid":{"rendered":"https:\/\/www.viscerallogic.com\/programming\/blog\/?p=90"},"modified":"2018-09-07T20:54:07","modified_gmt":"2018-09-08T04:54:07","slug":"basic-interpreter-part-iv","status":"publish","type":"post","link":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-iv\/","title":{"rendered":"BASIC Interpreter, Part IV"},"content":{"rendered":"<p>This is a continuation of <a href=\"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpeter-part-iii\/\">Part III<\/a>. This time we will add some mathematical operators, the ability to save and load programs, and support numerical variables.<br \/>\n<!--more--><\/p>\n<p>To enable mathematical operations, we will create a subclass of <code>DoubleExpression<\/code> that takes two <code>DoubleExpression<\/code>s as inputs, as well as a character code signifying which operation is to be performed. Because we want to be able to support variable expressions a little later, we can&#8217;t evaluate the operation when it is entered. Instead, we will keep pointers to the child expressions, and evaluate them when the operation&#8217;s value is required. To do this, we will need the ability to get the numerical value of the child expressions. We already have a member function called <code>value<\/code> on the <code>Expression<\/code> class and its inheritors, but that returns a <code>string<\/code>, not a <code>double<\/code>. In retrospect, perhaps our naming convention was not the best, so let&#8217;s go back and change it. We will rename the <code>print<\/code> function to <code>list<\/code>, since it is to support the <code>LIST<\/code> statement, and rename the <code>value<\/code> function to <code>print<\/code>, since its purpose is to support the <code>PRINT<\/code> statement. Here is the new <em>expression.h<\/em> header file:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#ifndef _EXPRESSION_H_\r\n#define _EXPRESSION_H_\r\n\r\n#include &lt;string&gt;\r\n\r\n\/*\r\nBase class used for storing and evaluating data items\r\n*\/\r\nclass Expression {\r\npublic:\r\n\tvirtual const std::string print() const;\t\t\/\/ return a string version for PRINT\r\n\tvirtual const std::string list() const;\t\t\t\/\/ printable version suitable for LIST\r\n};\r\n\r\n#endif<\/pre>\n<p>Change the function names in the source file, <em>expression.cpp<\/em>, also:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#include \"expression.h\"\r\n\r\n\/\/ return the text value\r\nconst std::string Expression::print() const{\r\n\treturn std::string(\"BASE EXPRESSION\");\r\n}\r\n\r\n\/\/ return a string for printing\r\nconst std::string Expression::list() const{\r\n\treturn std::string(\"BASE EXPRESSION\");\r\n}<\/pre>\n<p>Make the same substitutions in the <code>StringExpression<\/code> header and source files, and in the <code>Print::execute<\/code> and <code>Print::list<\/code> functions.<\/p>\n<p>For <code>DoubleExpression<\/code>, make the same substitutions, add a new <code>value<\/code> function, and make them all virtual. Here are the new function declarations in the header file, <em>doubleexpression.h<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-lineoffset=\"13\">\tvirtual const std::string print() const;\t\/\/ return the stored value\r\n\tvirtual const std::string list() const;\t\t\/\/ printable version\r\n\tvirtual double value() const;\t\t\t\/\/ numerical evaluation<\/pre>\n<p>Here are the updated member functions in <em>doubleexpression.cpp<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-lineoffset=\"8\">\/\/ return the text value\r\nconst std::string DoubleExpression::print() const{\r\n\treturn std::to_string(d);\r\n}\r\n\r\n\/\/ return a string for printing\r\nconst std::string DoubleExpression::list() const{\r\n\treturn print();\r\n}\r\n\r\n\/\/ return the value\r\ndouble DoubleExpression::value() const{\r\n\treturn d;\r\n}\r\n<\/pre>\n<p>Now we&#8217;re ready to add our new class, <code>OperatorExpression<\/code>. As described earlier, here is the header file, <em>operatorexpression.h<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#ifndef _OPERATOREXPRESSION_H_\r\n#define _OPERATOREXPRESSION_H_\r\n\r\n#include \"doubleexpression.h\"\r\n\r\n\/*\r\nClass for performing mathematical operations on DoubleExpressions.\r\n*\/\r\nclass OperatorExpression : public DoubleExpression {\r\npublic:\r\n\tOperatorExpression(DoubleExpression *a, DoubleExpression *b, char op);\r\n\t~OperatorExpression();\t\t\t\t\/\/ delete the sub-expressions\r\n\t\r\n\tconst std::string print() const;\t\t\/\/ return the stored value\r\n\tconst std::string list() const;\t\t\t\/\/ printable version\r\n\tdouble value() const;\t\t\t\t\/\/ value of performed operation\r\n\r\nprivate:\r\n\tDoubleExpression *a, *b;\t\t\t\/\/ expressions on which to operate\r\n\tchar op;\t\t\t\t\t\/\/ operation to perform\r\n};\r\n\r\n#endif<\/pre>\n<p>The implementation is actually quite simple. We have a <code>delete<\/code> operator function to clean up child expressions. The <code>print<\/code> function will return a <code>string<\/code> version of the numerical evaluation. The <code>list<\/code> function will print out the sub-expressions, separated by the operator character. The bulk of the logic is in the <code>value<\/code> function, where we switch on the <code>op<\/code> member variable and perform the appropriate mathematical operation. Here is the source code, <em>operatorexpression.cpp<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#include &lt;cmath&gt;\r\n\r\n#include \"operatorexpression.h\"\r\n\r\nOperatorExpression::OperatorExpression(DoubleExpression *a, DoubleExpression *b, char op) : DoubleExpression(0) {\r\n\tthis-&gt;a = a;\r\n\tthis-&gt;b = b;\r\n\tthis-&gt;op = op;\r\n}\r\n\r\nOperatorExpression::~OperatorExpression(){\r\n\tdelete a;\r\n\tdelete b;\r\n}\r\n\r\nconst std::string OperatorExpression::print() const{\r\n\treturn std::to_string(value());\r\n}\r\n\r\nconst std::string OperatorExpression::list() const{\r\n\treturn a-&gt;list() + op + b-&gt;list();\r\n}\r\n\r\ndouble 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}\r\n}<\/pre>\n<p>Now that we have added support in our C++ code, we need to add it in our Bison and flex files. Starting with the Bison input file, <em>basic.y<\/em>, add the new header file to the includes part of the C declarations:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">#include \"operatorexpression.h\"<\/pre>\n<p>Add a new token type for <code>DoubleExpression<\/code>s:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\" data-enlighter-highlight=\"8\">\/\/ 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}<\/pre>\n<p>Add some new token types to support our operators:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">%token PLUS\r\n%token MINUS\r\n%token MULT\r\n%token DIV\r\n%token EXP<\/pre>\n<p>And add token types for the new non-terminal symbols we&#8217;ll be creating. We&#8217;ll create a hierarchy of expression types to enforce operator precedence (note: Bison also supports defining operator precedence directly):<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">%type &lt;dxVal&gt; doubleExpr\r\n%type &lt;dxVal&gt; addExpr\r\n%type &lt;dxVal&gt; mulExpr\r\n%type &lt;dxVal&gt; expExpr\r\n%type &lt;dxVal&gt; term<\/pre>\n<p>The philosophy for creating the operator precedence by rule hierarchy is to start with the lowest precedence operator, and let it be either an instance of the next-higher rule, or two instance of the next-higher rule separated by the current level operator. E.g., an <em>add<\/em> is a <em>mul<\/em>, or a <em>mul + mul<\/em>, or a <em>mul &#8211; mul<\/em>. This ensures that higher-precedence operators will be evaluated first.<\/p>\n<p>Our old definition for the <code>expr<\/code> rule had it as either a <code>STRING<\/code> or a <code>DOUBLE<\/code> terminal symbol. We are going to replace the <code>DOUBLE<\/code> symbol with a non-terminal symbol, the <code>doubleExpr<\/code> rule, which will expand into the operations we need to support. Here are the updated rules:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-highlight=\"104-128\" data-enlighter-lineoffset=\"99\">expr:\r\n\tSTRING\t\t\t{\r\n\t\t\t\t\t$$ = new StringExpression($1);\r\n\t\t\t\t\tfree($1);\t\/\/ malloced in basic.l\r\n\t\t\t\t}\r\n\t| doubleExpr\r\n\t\r\ndoubleExpr:\r\n\taddExpr\r\n;\r\n\r\naddExpr:\r\n\tmulExpr\r\n\t| mulExpr PLUS mulExpr\t{ $$ = new OperatorExpression($1, $3, '+'); }\r\n\t| mulExpr MINUS mulExpr\t{ $$ = new OperatorExpression($1, $3, '-'); }\r\n;\r\n\r\nmulExpr:\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;\r\n\r\nexpExpr:\r\n\tterm\r\n\t| term EXP term\t\t{ $$ = new OperatorExpression($1, $3, '^'); }\r\n;\r\n\r\nterm:\r\n\tDOUBLE\t\t\t{ $$ = new DoubleExpression($1); }<\/pre>\n<p>With our new tokens defined in the Bison input file, we need to update the flex input file. Add a declaration for the new <code>DoubleExpression<\/code> in the C declarations section:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">class DoubleExpression;<\/pre>\n<p>And add rules for the new tokens. These are escaped because some of these characters have special meaning in the regular expression pattern matching, but we just want the literal character:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\\+\t\t\t\t{ return PLUS; }\r\n-\t\t\t\t{ return MINUS; }\r\n\\*\t\t\t\t{ return MULT; }\r\n\\\/\t\t\t\t{ return DIV; }\r\n\\^\t\t\t\t{ return EXP; }\r\n<\/pre>\n<p>Lastly, update the makefile with the new <code>OperatorExpression<\/code> source files:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-highlight=\"9,10,12\" data-enlighter-lineoffset=\"3\">all:\tbasic.tab.c lex.yy.c \\\r\n\t\tbasic.h basic.cpp \\\r\n\t\tprogram.h program.cpp \\\r\n\t\tprint.h print.cpp \\\r\n\t\texpression.h expression.cpp \\\r\n\t\tstringexpression.h stringexpression.cpp \\\r\n\t\tdoubleexpression.h doubleexpression.cpp \\\r\n\t\toperatorexpression.h operatorexpression.cpp\r\n\tg++ basic.tab.c lex.yy.c program.cpp basic.cpp print.cpp expression.cpp \\\r\n\tstringexpression.cpp doubleexpression.cpp operatorexpression.cpp \\\r\n\t-o basic<\/pre>\n<p>Now you can print out mathematical expressions using operators! Here is a sample session:<\/p>\n<pre>Welcome to BASIC!\r\n&gt;10 print 2+2*3^7\r\n&gt;20 print \"whoa!\"\r\n&gt;list\r\n10 PRINT 2.000000+2.000000*3.000000^7.000000\r\n20 PRINT \"whoa!\"\r\n&gt;run\r\n4376.000000\r\nwhoa!<\/pre>\n<p>The next step is to add support for variables. Support in the parser is pretty simple; it is added into the <code>term<\/code> rule, as an alternative to a literal double; and a new statement: <code>LET<\/code>. In the lexical analyzer, the rule is also pretty simple: a variable is an alpha character optionally followed by a single digit.<\/p>\n<p>To perform variable storage and access operations, we will add a <code>map<\/code> to our <code>Basic<\/code> singleton instance that maps a <code>string<\/code> to a <code>double<\/code>, as well as function to assign and resolve variables.<\/p>\n<p>In the header file, <em>basic.h<\/em>, include the standard header for the <code>string<\/code> class:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">#include &lt;string&gt;<\/pre>\n<p>Add two new public member variables:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\tvoid assign(std::string var, double value);\t\/\/ assign a value to a variable\r\n\tdouble resolve(std::string var);\t\t\/\/ return variable value<\/pre>\n<p>And add a private member variable to store the variables:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\tstd::map&lt;std::string, double&gt; vars;\t\/\/ store variables<\/pre>\n<p>Here are the two new function implementations in <em>basic.cpp<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\/\/ assign a value to a variable\r\nvoid Basic::assign(string var, double value){\r\n\t\/\/ delete value if var already exists\r\n\tmap&lt;string, double&gt;::iterator it = vars.find(var);\r\n\tif( it != vars.end() ){\r\n\t\tvars.erase(it);\r\n\t}\r\n\t\r\n\tvars.insert(pair&lt;string, double&gt;(var, value));\r\n}\r\n\r\n\/\/ return variable value\r\ndouble Basic::resolve(string var){\r\n\tmap&lt;string, double&gt;::iterator it = vars.find(var);\r\n\tif( it != vars.end() ){\r\n\t\treturn it-&gt;second;\r\n\t}\r\n}<\/pre>\n<p>I also made a tweak to the <code>Basic::remove<\/code> function: instead of calling <code>lines.erase(index);<\/code>, I changed it to <code>lines.erase(it);<\/code>, since the former version requires searching through the map again, whereas the latter version makes use of the iterator we already found, making it slightly faster.<\/p>\n<p>Now we need to add a new class to represent our variables, a subclass of <code>DoubleExpression<\/code> called, naturally, <code>VariableExpression<\/code>. This class will implement the virtual functions defined in its parent class, using a <code>string<\/code> member variable to look up the value in the <code>Basic<\/code> singleton instance. Here is the header file, <em>variableexpression.h<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#ifndef _VARIABLEXPRESSION_H_\r\n#define _VARIABLEXPRESSION_H_\r\n\r\n#include &lt;string&gt;\r\n\r\n#include \"doubleexpression.h\"\r\n#include \"basic.h\"\r\n\r\n\/*\r\nThis class is used to access variable inside an expression\r\n*\/\r\nclass VariableExpression : public DoubleExpression {\r\npublic:\r\n\tVariableExpression(char *name);\r\n\r\n\tconst std::string print() const;\t\t\/\/ return the stored value\r\n\tconst std::string list() const;\t\t\t\/\/ printable version\r\n\tdouble value() const;\t\t\t\t\t\/\/ numerical evaluation\r\n\r\nprivate:\r\n\tstd::string var;\r\n};\r\n\r\n#endif<\/pre>\n<p>The implementation is pretty simple. The constructor takes a <code>string<\/code> to use as a lookup index, <code>print()<\/code> returns a string-version of the stored value, <code>list()<\/code> returns the variable name, and <code>value()<\/code> looks up and returns the stored value from the <code>Basic<\/code> singleton instance. Here is <em>variableexpression.cpp<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#include \"variableexpression.h\"\r\n\r\nVariableExpression::VariableExpression(char *name) : DoubleExpression(0) {\r\n\tvar = name;\r\n}\r\n\r\n\/\/ return the stored value\r\nconst std::string VariableExpression::print() const{\r\n\treturn std::to_string(value());\r\n}\r\n\r\n\/\/ printable version\r\nconst std::string VariableExpression::list() const{\r\n\treturn var;\r\n}\r\n\r\n\/\/ numerical evaluation\r\ndouble VariableExpression::value() const{\r\n\treturn Basic::instance()-&gt;resolve(var);\r\n}<\/pre>\n<p>In order to assign a value to a variable, we will use the <code>LET<\/code> statement, which looks like this:<\/p>\n<pre>LET X = 1\r\nLET Y1 = 2\r\nLET Z = X+Y1<\/pre>\n<p>To do this, we need to create a new subclass of <code>Program<\/code>. This class will implement the virtual functions <code>list()<\/code> and <code>execute()<\/code>, and provide storage for the variable name and expression whose value will be assigned. We need to keep a pointer to the expression and not just evaluate it immediately because it could contain references to other variables whose value we will not know until we run the program. Here is the header file, <em>let.h<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#ifndef _LET_H_\r\n#define _LET_H_\r\n\r\n#include &lt;string&gt;\r\n\r\n#include \"program.h\"\r\n#include \"doubleexpression.h\"\r\n#include \"basic.h\"\r\n\r\n\/*\r\nThe Let class provides variable assignment capability.\r\n*\/\r\nclass Let : public Program {\r\npublic:\r\n\tLet(char *var, const DoubleExpression *expression);\t\/\/ create a new LET assignment\r\n\t~Let();\t\t\t\t\t\t\t\t\t\t\t\t\/\/ clean up\r\n\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\/\/ list this line\r\n\t\r\nprivate:\r\n\tstd::string var;\r\n\tconst DoubleExpression *expression;\r\n};\r\n\r\n#endif<\/pre>\n<p>The implementation of this class is also pretty simple. The constructor stores the variable name and expression; the destructor deletes the expression (since the variable name is not stored in a pointer, we don&#8217;t need to delete it); the function <code>execute()<\/code>, which is called at program runtime, evaluates the expression and calls the <code>Basic<\/code> singleton instance to store it, and <code>list()<\/code> prints out the statement line. Here is the source of <em>let.cpp<\/em>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\">#include \"let.h\"\r\n\r\nLet::Let(char *var, const DoubleExpression *expression){\r\n\tthis-&gt;var = var;\r\n\tthis-&gt;expression = expression;\r\n}\r\n\r\n\/\/ clean up the pointer\r\nLet::~Let(){\r\n\tdelete expression;\r\n}\r\n\r\n\/\/ store the value of the Expression in the Basic vars map\r\nvoid Let::execute() const{\r\n\tBasic::instance()-&gt;assign(var, expression-&gt;value());\r\n}\r\n\r\n\/\/ list this LET statement\r\nvoid Let::list(std::ostream&amp; os) const{\r\n\tos &lt;&lt; \"LET \" &lt;&lt; var &lt;&lt; \" = \" &lt;&lt; expression-&gt;list();\r\n}<\/pre>\n<p>OK, time to update Bison and flex. In your Bison input file, include the header files for the new <code>VariableExpression<\/code> and <code>Let<\/code> classes:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">#include \"variablexpression.h\"\r\n#include \"let.h\"<\/pre>\n<p>Add new constant tokens to support the <code>LET<\/code> statement:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">%token LET\r\n%token EQUAL<\/pre>\n<p>and a new terminal symbol to represent variables:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">%token &lt;sVal&gt; VAR<\/pre>\n<p>Since we have added a new subclass of <code>Program<\/code>, we need to update its rule:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\" data-enlighter-highlight=\"3-6\">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;<\/pre>\n<p>We also need to update the <code>term<\/code> rule, which can now be either a literal double, or a variable name:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-highlight=\"3-6\" data-enlighter-linenumbers=\"false\">term:\r\n\tDOUBLE\t\t\t{ $$ = new DoubleExpression($1); }\r\n\t| VAR\t\t\t{\r\n\t\t\t\t\t$$ = new VariableExpression($1);\r\n\t\t\t\t\tfree($1);\r\n\t\t\t\t}\r\n;<\/pre>\n<p>In the flex input file, we need to add scanners for the new terminal token types we have defined. Per the BASIC documentation we are following, a variable name consists of an alphabetic character optionally followed by a single digit. Let&#8217;s add an <code>ALPHA<\/code> rule by our existing <code>DIGIT<\/code> rule:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-highlight=\"1\" data-enlighter-linenumbers=\"false\">ALPHA    [A-Z]\t\r\nDIGIT    [0-9]<\/pre>\n<p>Here are the new scanners:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">{ALPHA}{DIGIT}?\t{ yylval.sVal = strdup(yytext); return VAR; }\r\nLET\t\t{ return LET; }\r\n\\=\t\t{ return EQUAL; }<\/pre>\n<p>The <code>VAR<\/code> scanner needs to return the actual text value it read, as well as the token type; the other two just need to return the token type.<\/p>\n<p>Now, add the <em>let.*<\/em> and <em>variableexpression.*<\/em> dependencies to the make file, and run it:<\/p>\n<pre>Welcome to BASIC!\r\n&gt;10 let a = 1\r\n&gt;20 let b = a*2\r\n&gt;30 print a, b\r\n&gt;list\r\n10 LET a = 1.000000\r\n20 LET b = a*2.000000\r\n30 PRINT a, b\r\n&gt;run\r\n1.000000 2.000000\r\n<\/pre>\n<p>The last thing we want to add right now is the ability to save and load programs. To do this, we will implement the BASIC commands outline in the guide: <code>SAVE<\/code>, <code>UNSAVE<\/code>, <code>NEW<\/code>, and <code>OLD<\/code>. To save a program, we will repurpose our existing <em>list<\/em> functionality but directed into a file output stream instead of standard output. Likewise, to read a saved file, we will change the <code>yyin<\/code> file pointer to point to a file that we open, instead of standard input. There will be some minor changes to the Bison and flex input files to look for these commands, but the heavy lifting will take place in the <code>Basic<\/code> class.<\/p>\n<p>In the header file, <em>basic.h<\/em>, we need to include <code>&lt;iostream&gt;<\/code>, which we will use in a modification to <code>list()<\/code>. We also add four new public functions corresponding to the new commands we are implementing, as well as a private function to erase all lines of the current program, and a private variable containing the name of the current program.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-highlight=\"6,17,20-23,31,35\">#ifndef _BASIC_H_\r\n#define _BASIC_H_\r\n\r\n#include &lt;map&gt;\r\n#include &lt;string&gt;\r\n#include &lt;iostream&gt;\r\n\r\n#include \"program.h\"\r\n#include \"doubleexpression.h\"\r\n\r\n\/*\r\nThis is a singleton class which contains all the program lines.\r\n*\/\r\nclass Basic {\r\npublic:\r\n\tvoid add(int index, const Program *program);\t\t\/\/ add a new line to the program\r\n\tvoid list(std::ostream &amp;out);\t\t\t\t\/\/ list out all the existing lines\r\n\tvoid execute();\t\t\t\t\t\t\/\/ run the program\r\n\tvoid remove(int index);\t\t\t\t\t\/\/ remove program line\r\n\tvoid saveProgram();\t\t\t\t\t\/\/ save active program to disk\r\n\tvoid unsaveProgram();\t\t\t\t\t\/\/ delete saved program from disk\r\n\tvoid newProgram();\t\t\t\t\t\/\/ start a new program\r\n\tvoid oldProgram();\t\t\t\t\t\/\/ load program from disk\r\n\t\r\n\tstatic Basic *instance();\t\t\t\t\/\/ access the singleton instance\r\n\r\n\tvoid assign(std::string var, double value);\t\t\/\/ assign a value to a variable\r\n\tdouble resolve(std::string var);\t\t\t\/\/ return variable value\r\n\t\r\nprivate:\r\n\tvoid erase();\t\t\t\t\t\t\/\/ clear stored program lines\r\n\t\r\n\tstd::map&lt;int, const Program*&gt; lines;\t\t\t\/\/ store the lines in a map\r\n\tstd::map&lt;std::string, double&gt; vars;\t\t\t\/\/ store variables\r\n\tstd::string name;\t\t\t\t\t\/\/ name of active program\r\n\t\r\n\tstatic Basic *b;\t\t\t\t\t\/\/ singleton instance\r\n};\r\n\r\n#endif<\/pre>\n<p>Now, for the implementation. At the top of <em>basic.cpp<\/em>, include <code>&lt;fstream&gt;<\/code> and <code>&lt;cstdio&gt;<\/code>. We will use these for reading and writing files. Also, make a declaration of the external variable <code>yyin<\/code> (the input stream used by flex and Bison), since we will be re-directing it for file operations:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">extern \"C\" FILE *yyin;<\/pre>\n<p>Since we changed the method signature of list to take an <code>ostream<\/code> as an argument, we need to update the implementation to use that instead of <code>std::cout<\/code>:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\/\/ print out the program lines\r\nvoid Basic::list(std::ostream &amp;out){\r\n\tfor( map&lt;int, const Program *&gt;::iterator it = lines.begin(); it!= lines.end(); ++it ){\r\n\t\tout &lt;&lt; it-&gt;first &lt;&lt; \" \"; it-&gt;second-&gt;list(out);\r\n\t\tout &lt;&lt; std::endl;\r\n\t}\r\n}<\/pre>\n<p>Our first new function, <code>saveProgram()<\/code>, opens a file output stream with the member variable <code>name<\/code> and calls the new <code>list()<\/code> function:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\/\/ save active program to disk\r\nvoid Basic::saveProgram(){\r\n\tstd::ofstream out;\r\n\tout.open(name + \".bas\");\r\n\tlist(out);\r\n}<\/pre>\n<p>The function <code>unsaveProgram()<\/code> deletes the currently-named program from disk:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\/\/ delete saved program from disk\r\nvoid Basic::unsaveProgram(){\r\n\t::remove((name + \".bas\").c_str());\r\n}<\/pre>\n<p>The <code>newProgram()<\/code> function erases whatever program lines are currently in memory, prompts the user for a program name, and then eats the newline character to prevent flex from printing out a prompt character when it reads it:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\/\/ start a new program\r\nvoid Basic::newProgram(){\r\n\terase();\r\n\tstd::cout &lt;&lt; \"Enter a program name: \"; std::cin &gt;&gt; name;\r\n\tstd::cin.ignore();\t\/\/ consume the newline character\r\n}<\/pre>\n<p>The final command function, <code>oldProgram()<\/code>, also starts by erasing the currently stored program and prompting the user for a program name. Then it attempts to open a file with that name, and points the <code>yyin<\/code> file pointer to it for flex\/Bison. If it fails to open a file with that name, it restores <code>yyin<\/code> to the standard input and reports the error:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\/\/ load program from disk\r\nvoid Basic::oldProgram(){\r\n\terase();\r\n\tstd::cout &lt;&lt; \"Enter program to read: \"; std::cin &gt;&gt; name;\r\n\tyyin = fopen((name + \".bas\").c_str(), \"r\");\r\n\tif( !yyin ){\r\n\t\tstd::cout &lt;&lt; \"ERROR: could not read file: \" &lt;&lt; name &lt;&lt; \".bas\\n\";\r\n\t\tyyin = stdin;\r\n\t}\r\n}<\/pre>\n<p>Lastly, we have our utility function, <code>erase()<\/code>. This iterates through the stored program and deletes the pointers, then empties the map:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\/\/ clear stored program lines\r\nvoid Basic::erase(){\r\n\tfor( map&lt;int, const Program *&gt;::iterator it = lines.begin(); it!= lines.end(); ++it ){\r\n\t\tdelete it-&gt;second;\r\n\t}\r\n\tlines.clear();\r\n}<\/pre>\n<p>That&#8217;s all the C++ class code, now we just need to update the Bison and flex input files to use the new functionality. In <em>basic.y<\/em>, start by declaring another C function, <code>yywrap<\/code>. This is used in Bison to handle when we switch input files:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">extern \"C\" int yywrap();<\/pre>\n<p>Next, add four constant tokens for our new commands:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">%token SAVE\r\n%token UNSAVE\r\n%token NEW\r\n%token OLD<\/pre>\n<p>We update the <code>stmt<\/code> rule to use these, as well as our modified <code>list()<\/code> function:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\" data-enlighter-highlight=\"5-9\">stmt:\r\n\tLINE\t\t\t{ Basic::instance()-&gt;remove($1); }\r\n\t| LINE program\t\t{ Basic::instance()-&gt;add($1, $2); }\r\n\t| RUN\t\t\t{ Basic::instance()-&gt;execute(); }\r\n\t| LIST\t\t\t{ Basic::instance()-&gt;list(std::cout); }\r\n\t| NEW\t\t\t{ Basic::instance()-&gt;newProgram(); }\r\n\t| OLD\t\t\t{ Basic::instance()-&gt;oldProgram(); }\r\n\t| SAVE\t\t\t{ Basic::instance()-&gt;saveProgram(); }\r\n\t| UNSAVE\t\t{ Basic::instance()-&gt;unsaveProgram(); }\r\n;<\/pre>\n<p>Since we now have the concept of named programs, we will call <code>newProgram()<\/code> when our interpreter starts up. Modify the <code>main()<\/code> function to do this:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\" data-enlighter-highlight=\"2-4\">int main(int argc, char **argv){\r\n\tstd::cout &lt;&lt; \"Welcome to BASIC!\\n\";\r\n\tBasic::instance()-&gt;newProgram();\r\n\tstd::cout &lt;&lt; '&gt;';\r\n\tdo {\r\n\t\tyyparse();\r\n\t} while( !feof(yyin) );\r\n\t\r\n\treturn 0;\r\n}<\/pre>\n<p>Lastly, we need to add the <code>yywrap<\/code> function we declared at the beginning of the file. This function gets called by flex when it reaches the end of the current input it&#8217;s reading. If <code>yywrap<\/code> returns 1, flex ends parsing; if it returns 0, flex expects <code>yyin<\/code> to be pointed to a new input file, and continues parsing. If <code>yywrap<\/code> is called while <code>yyin<\/code> is the standard input, that means the user has sent the <em>end-of-file signal, so we should stop parsing. If it points to any other input file, that means we have finished reading an input file being loaded using the <code>oldProgram()<\/code> function, so we should close that input file and point <code>yyin<\/code> back to standard input to continue processing user commands:<\/em><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">int yywrap(){\r\n\tif( yyin == stdin )\r\n\t\treturn 1;\r\n\tfclose(yyin);\r\n\tyyin = stdin;\r\n\treturn 0;\r\n}<\/pre>\n<p>Almost done! There are just a couple small changes to make to the flex input file, and we will be done with this part of the tutorial. First, since we are now defining a <code>yywrap()<\/code> function, we need to remove the <code>noyywrap<\/code> option given at the top of file:<\/p>\n<pre class=\"EnlighterJSRAW\">%option case-insensitive<\/pre>\n<p>We could now compile and run our interpreter, but if we read in an old program, we would get a prompt character printed out every time the scanner read a new line! So we need to modify our scanner so it only prints prompt characters when it&#8217;s reading from the standard input:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"cpp\" data-enlighter-linenumbers=\"false\">\\n\t\t{\r\n\t\t\tif( yyin == stdin )\r\n\t\t\t\tstd::cout &lt;&lt; \"&gt;\";\r\n\t\t\treturn ENDL;\r\n\t\t}<\/pre>\n<p>Excellent! Now you can save and load programs!<\/p>\n<pre>Welcome to BASIC!\r\nEnter a program name: first\r\n&gt;10 print \"first!\"\r\n&gt;20 let a = 1\r\n&gt;30 print a\r\n&gt;save\r\n&gt;new\r\nEnter a program name: second\r\n&gt;10 print \"second!\"\r\n&gt;20 let b = 2\r\n&gt;30 print b\r\n&gt;save\r\n&gt;old\r\nEnter program to read: first\r\n&gt;run\r\nfirst!\r\n1.000000<\/pre>\n<p>The complete code for this part can be found here: <a href=\"https:\/\/github.com\/VisceralLogic\/basic\/tree\/part-4\" target=\"_blank\" rel=\"noopener\">https:\/\/github.com\/VisceralLogic\/basic\/tree\/part-4<\/a><\/p>\n<p>Continue to\u00a0<a href=\"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-v\/\">Part V<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>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.<\/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-1s","jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":72,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpeter-part-iii\/","url_meta":{"origin":90,"position":0},"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":149,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-vii\/","url_meta":{"origin":90,"position":1},"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":90,"position":2},"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":111,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-v\/","url_meta":{"origin":90,"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":3,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/numerical-expression-solver-in-java\/","url_meta":{"origin":90,"position":4},"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":[]},{"id":131,"url":"https:\/\/www.viscerallogic.com\/programming\/blog\/basic-interpreter-part-vi\/","url_meta":{"origin":90,"position":5},"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":[]}],"_links":{"self":[{"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/posts\/90"}],"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=90"}],"version-history":[{"count":19,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/posts\/90\/revisions"}],"predecessor-version":[{"id":167,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/posts\/90\/revisions\/167"}],"wp:attachment":[{"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/media?parent=90"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/categories?post=90"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.viscerallogic.com\/programming\/blog\/wp-json\/wp\/v2\/tags?post=90"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}