BuiltIns.cs:
authorMichael Welch <michaelgwelch@gmail.com>
Wed, 27 Dec 2006 21:39:28 +0000 (21:39 +0000)
committerMichael Welch <michaelgwelch@gmail.com>
Wed, 27 Dec 2006 21:39:28 +0000 (21:39 +0000)
Added Print method to match the specifications in User's Reference Guide.

Radix100.cs:
Removed leading and trailing spaces on ToString to support the specifications
for STR$. The trailing and leading spaces are added within Print routines.

TestRadix100.cs:
Updated ToString tests due to changes made in Radix100.

Lexer.cs:
Removed Label and LineNumber properties. Replaced with LineId property which contains both values. Added support for parsing ';' and ':' which are needed for PRINT statement.

mbasic.csproj:
Added LineId.cs

Parser.cs:
Added support for parsing print items in a PRINT statement. Also repurcussions due to remove Label and LineNumber from Lexer. Also repurcussions from requiring a LineId on constructor of every Statement and Expression subclass.

Program.cs:
When saving executable, the assembly, module and filenames are derived from input file name. Also reserved the word TAB.

Print.cs:

The rest of the files in SyntaxTree changed as a result to requring a LineID in the constructor rather than a line number, label, or both.

LineId.cs:
Added

41 files changed:
TiBasicRuntime/BuiltIns.cs
TiBasicRuntime/Radix100.cs
TiBasicRuntime/TestRadix100.cs
mbasic.sln
mbasic/Lexer.cs
mbasic/LineId.cs [new file with mode: 0644]
mbasic/Parser.cs
mbasic/Program.cs
mbasic/SyntaxTree/Add.cs
mbasic/SyntaxTree/Assign.cs
mbasic/SyntaxTree/Block.cs
mbasic/SyntaxTree/Concatenate.cs
mbasic/SyntaxTree/Division.cs
mbasic/SyntaxTree/End.cs
mbasic/SyntaxTree/Equals.cs
mbasic/SyntaxTree/Expression.cs
mbasic/SyntaxTree/For.cs
mbasic/SyntaxTree/Function.cs
mbasic/SyntaxTree/Goto.cs
mbasic/SyntaxTree/GreaterThan.cs
mbasic/SyntaxTree/If.cs
mbasic/SyntaxTree/Increment.cs
mbasic/SyntaxTree/Input.cs
mbasic/SyntaxTree/LessThan.cs
mbasic/SyntaxTree/Multiply.cs
mbasic/SyntaxTree/Negative.cs
mbasic/SyntaxTree/Node.cs
mbasic/SyntaxTree/NumberLiteral.cs
mbasic/SyntaxTree/Power.cs
mbasic/SyntaxTree/Print.cs
mbasic/SyntaxTree/Randomize.cs
mbasic/SyntaxTree/RelationalExpression.cs
mbasic/SyntaxTree/Statement.cs
mbasic/SyntaxTree/StringLiteral.cs
mbasic/SyntaxTree/Subroutine.cs
mbasic/SyntaxTree/Subtract.cs
mbasic/SyntaxTree/VariableReference.cs
mbasic/Token.cs
mbasic/helloworld.mbas
mbasic/mbasic.csproj
mbasic/secretnum.mbas

index f23f5c5..fb7f28a 100644 (file)
@@ -163,5 +163,126 @@ namespace TiBasicRuntime
                 trace = value;\r
             }\r
         }\r
+\r
+        static int printCol = 1;\r
+        public static void Print(params object[] items)\r
+        {\r
+            if (items.Length == 0) \r
+            {\r
+                Console.WriteLine();\r
+                printCol = 1;\r
+                return;\r
+            }\r
+\r
+            bool printSepInEffect = false;\r
+            foreach (object o in items)\r
+            {\r
+                string s;\r
+                if (o is string)\r
+                {\r
+                    s = o as string;\r
+                    if (s.Length == 0) continue;\r
+                    char ch = s[0];\r
+                    switch (ch)\r
+                    {\r
+                        case '\0': // nothing to print.\r
+                            printSepInEffect = true;\r
+                            break;\r
+                        case '\t':\r
+                            if (s.Length == 1) PrintComma();\r
+                            else PrintTab(s);\r
+                            printSepInEffect = true;\r
+                            break;\r
+                        case '\n':\r
+                            PrintNewLine();\r
+                            printSepInEffect = true;\r
+                            break;\r
+                        default:\r
+                            PrintString(s);\r
+                            printSepInEffect = false;\r
+                            break;\r
+                    }\r
+                }\r
+                else\r
+                {\r
+                    PrintNumber((double)o);\r
+                    printSepInEffect = false;\r
+                }\r
+\r
+            }\r
+\r
+            if (!printSepInEffect) PrintNewLine();\r
+\r
+            \r
+        }\r
+\r
+        private static void PrintComma()\r
+        {\r
+            if (printCol < 15) PrintItem(new String(' ', 15 - printCol));\r
+            else PrintNewLine();\r
+        }\r
+        private static void PrintTab(string s)\r
+        {\r
+            int doubleLength = s.Length - 1;\r
+            double d = double.Parse(s.Substring(1, doubleLength));\r
+            int n = (int) (Math.Round(d) % 28) + 1;\r
+            if (printCol > n) PrintNewLine();\r
+            PrintItem(new String(' ', n - printCol));\r
+        }\r
+\r
+        private static void PrintSpace()\r
+        {\r
+            PrintItem(" ");\r
+        }\r
+\r
+        private static void PrintNumber(double d)\r
+        {\r
+            if (d >= 0) PrintSpace(); // Positive numbers are printed with leading space \r
+            string s = Radix100.ToString(d);\r
+            if (s.Length > RemainingPrintColumns) PrintNewLine();\r
+            PrintItem(s);\r
+            if (printCol < 28) PrintSpace();\r
+        }\r
+\r
+        private static void PrintItem(string s)\r
+        {\r
+            Console.Write(s);\r
+            printCol += s.Length;\r
+        }\r
+\r
+        private static void PrintString(string s)\r
+        {\r
+            if (s.Length > RemainingPrintColumns)\r
+            {\r
+                if (printCol != 1) PrintNewLine();\r
+            }\r
+            if (s.Length <= 28)\r
+            {\r
+                PrintItem(s);\r
+                return;\r
+            }\r
+\r
+            int index = 0;\r
+            while (index < s.Length)\r
+            {\r
+                int charsToPrint = Math.Min(28, s.Length - index);\r
+                PrintItem(s.Substring(index, charsToPrint));\r
+                index += charsToPrint;\r
+                if (charsToPrint == 28) PrintNewLine();\r
+            }\r
+        }\r
+\r
+        private static void PrintNewLine()\r
+        {\r
+            Console.WriteLine();\r
+            ResetColumnPos();\r
+        }\r
+\r
+        private static void ResetColumnPos() { printCol = 1; }\r
+        private static int RemainingPrintColumns { get { return 28 - printCol + 1; } }\r
+\r
+\r
+        private static void PrintStuff(params object[] objects) { }\r
+        private static void PrintStuff2() { PrintStuff(3, 5, "hello"); }\r
     }\r
 }\r
index c936566..019609b 100644 (file)
@@ -290,10 +290,10 @@ namespace TiBasicRuntime
                 if (Math.Abs(exponent) >= 50)\r
                 {\r
                     double mantissa = GetMantissa10(this);\r
-                    if (mantissa < 0 && exponent < 0) return String.Format("{0:0.#####}E-** ", mantissa);\r
-                    else if (mantissa < 0) return String.Format("{0:0.#####}E+** ", mantissa);\r
-                    else if (exponent > 0) return String.Format(" {0:0.#####}E+** ", mantissa);\r
-                    else return String.Format(" {0:0.#####}E-** ", mantissa);\r
+                    if (mantissa < 0 && exponent < 0) return String.Format("{0:0.#####}E-**", mantissa);\r
+                    else if (mantissa < 0) return String.Format("{0:0.#####}E+**", mantissa);\r
+                    else if (exponent > 0) return String.Format("{0:0.#####}E+**", mantissa);\r
+                    else return String.Format("{0:0.#####}E-**", mantissa);\r
                 }\r
                 if (exponent < -4 || exponent > 5) return ToScientificForm();\r
                 return ToNormalDecimalForm();\r
@@ -304,8 +304,7 @@ namespace TiBasicRuntime
         public string ToScientificForm()\r
         {\r
             StringBuilder bldr = new StringBuilder();\r
-            if (Math.Sign(this) >= 0) bldr.Append(" ");\r
-            else bldr.Append("-");\r
+            if (Math.Sign(this) < 0) bldr.Append("-");\r
 \r
             Radix100 rounded = Radix100.Round(this, 6);\r
             sbyte exponent = GetExponent(this);\r
@@ -363,7 +362,6 @@ namespace TiBasicRuntime
 \r
             bldr.Append("E");\r
             bldr.Append(decimalExponent.ToString("+00;-00"));\r
-            bldr.Append(" ");\r
             return bldr.ToString();\r
 \r
         }\r
@@ -371,8 +369,7 @@ namespace TiBasicRuntime
         public string ToNormalDecimalForm()\r
         {\r
             StringBuilder bldr = new StringBuilder();\r
-            if (Math.Sign(this) >= 0) bldr.Append(" ");\r
-            else bldr.Append("-");\r
+            if (Math.Sign(this) < 0) bldr.Append("-");\r
 \r
             Radix100 rounded = Radix100.Round(this, 10);\r
             bool isInteger = IsInteger;\r
@@ -434,7 +431,6 @@ namespace TiBasicRuntime
                 bldr.Append(firstDigit);\r
                 bldr.Append(secondDigit.ToString("#")); // if it is zero it won't print.\r
             }\r
-            bldr.Append(" ");\r
             return bldr.ToString();\r
 \r
         }\r
index a3fba51..0b89c1c 100644 (file)
@@ -59,37 +59,37 @@ namespace TiBasicRuntime
             Radix100 x = -10;\r
             Radix100 y = (Radix100)7.1;\r
 \r
-            Assert.AreEqual("-10 ", x.ToString());\r
-            Assert.AreEqual(" 7.1 ", y.ToString()); \r
-            Assert.AreEqual(" 9.34277E+10 ", Radix100.FromInteger(93427685127).ToString());\r
-            Assert.AreEqual(" .0000000001 ", Radix100.FromDouble(1e-10).ToString());\r
-            Assert.AreEqual(" 1.2E-10 ", Radix100.FromDouble(1.2e-10).ToString());\r
-            Assert.AreEqual(" 2.46E-10 ", Radix100.FromDouble(.000000000246).ToString());\r
-            Assert.AreEqual(" 15 ", Radix100.FromInteger(15).ToString());\r
-            Assert.AreEqual("-3 ", Radix100.FromInteger(-3).ToString());\r
-            Assert.AreEqual(" 3.35 ", Radix100.FromDouble(3.350).ToString());\r
-            Assert.AreEqual("-46.1 ", Radix100.FromDouble(-46.1).ToString());\r
-            Assert.AreEqual(" 791.1234568 ", Radix100.FromDouble(791.123456789).ToString());\r
-            Assert.AreEqual(" 7.91123E+10 ", Radix100.FromDouble(79112345678).ToString());\r
-            Assert.AreEqual(" 7911234568. ", Radix100.FromDouble(7911234567.8).ToString());\r
-            Assert.AreEqual("-7911234568. ", Radix100.FromDouble(-7911234567.8).ToString());\r
-            Assert.AreEqual("-.0127 ", Radix100.FromDouble(-12.7E-3).ToString());\r
-            Assert.AreEqual(" .64 ", Radix100.FromDouble(0.64).ToString());\r
-            Assert.AreEqual(" 1.97853E-10 ", Radix100.FromDouble(.0000000001978531).ToString());\r
-            Assert.AreEqual("-9.877E+22 ", Radix100.FromDouble(-98.77E21).ToString());\r
-            Assert.AreEqual(" 7.364E+12 ", Radix100.FromDouble(736.400E10).ToString());\r
-            Assert.AreEqual(" 1.23659E-14 ", Radix100.FromDouble(12.36587E-15).ToString());\r
-            Assert.AreEqual(" 1.25E-09 ", Radix100.FromDouble(1.25e-9).ToString());\r
-            Assert.AreEqual("-4.36E+13 ", Radix100.FromDouble(-43.6e12).ToString());\r
-            Assert.AreEqual(" 7.6E+** ", Radix100.FromDouble(.76E126).ToString());\r
-            Assert.AreEqual(" 8.1E-** ", Radix100.FromDouble(81e-115).ToString());\r
-            Assert.AreEqual("-7.6E+** ", Radix100.FromDouble(-.76E126).ToString());\r
-            Assert.AreEqual("-8.1E-** ", Radix100.FromDouble(-81e-115).ToString());\r
-            Assert.AreEqual(" 2.E+10 ", Radix100.FromInteger(19999999999).ToString());\r
-            Assert.AreEqual(" 8.23498E+12 ", Radix100.FromDouble(8234983729385).ToString());\r
+            Assert.AreEqual("-10", x.ToString());\r
+            Assert.AreEqual("7.1", y.ToString()); \r
+            Assert.AreEqual("9.34277E+10", Radix100.FromInteger(93427685127).ToString());\r
+            Assert.AreEqual(".0000000001", Radix100.FromDouble(1e-10).ToString());\r
+            Assert.AreEqual("1.2E-10", Radix100.FromDouble(1.2e-10).ToString());\r
+            Assert.AreEqual("2.46E-10", Radix100.FromDouble(.000000000246).ToString());\r
+            Assert.AreEqual("15", Radix100.FromInteger(15).ToString());\r
+            Assert.AreEqual("-3", Radix100.FromInteger(-3).ToString());\r
+            Assert.AreEqual("3.35", Radix100.FromDouble(3.350).ToString());\r
+            Assert.AreEqual("-46.1", Radix100.FromDouble(-46.1).ToString());\r
+            Assert.AreEqual("791.1234568", Radix100.FromDouble(791.123456789).ToString());\r
+            Assert.AreEqual("7.91123E+10", Radix100.FromDouble(79112345678).ToString());\r
+            Assert.AreEqual("7911234568.", Radix100.FromDouble(7911234567.8).ToString());\r
+            Assert.AreEqual("-7911234568.", Radix100.FromDouble(-7911234567.8).ToString());\r
+            Assert.AreEqual("-.0127", Radix100.FromDouble(-12.7E-3).ToString());\r
+            Assert.AreEqual(".64", Radix100.FromDouble(0.64).ToString());\r
+            Assert.AreEqual("1.97853E-10", Radix100.FromDouble(.0000000001978531).ToString());\r
+            Assert.AreEqual("-9.877E+22", Radix100.FromDouble(-98.77E21).ToString());\r
+            Assert.AreEqual("7.364E+12", Radix100.FromDouble(736.400E10).ToString());\r
+            Assert.AreEqual("1.23659E-14", Radix100.FromDouble(12.36587E-15).ToString());\r
+            Assert.AreEqual("1.25E-09", Radix100.FromDouble(1.25e-9).ToString());\r
+            Assert.AreEqual("-4.36E+13", Radix100.FromDouble(-43.6e12).ToString());\r
+            Assert.AreEqual("7.6E+**", Radix100.FromDouble(.76E126).ToString());\r
+            Assert.AreEqual("8.1E-**", Radix100.FromDouble(81e-115).ToString());\r
+            Assert.AreEqual("-7.6E+**", Radix100.FromDouble(-.76E126).ToString());\r
+            Assert.AreEqual("-8.1E-**", Radix100.FromDouble(-81e-115).ToString());\r
+            Assert.AreEqual("2.E+10", Radix100.FromInteger(19999999999).ToString());\r
+            Assert.AreEqual("8.23498E+12", Radix100.FromDouble(8234983729385).ToString());\r
             double val = 1.000000000002;\r
             Radix100 r = Radix100.FromDouble(val);\r
-            Assert.AreEqual(" 1. ", r.ToString());\r
+            Assert.AreEqual("1.", r.ToString());\r
         }\r
 \r
         [Test]\r
index 38bb783..d74fd1b 100644 (file)
@@ -5,6 +5,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mbasic", "mbasic\mbasic.csp
 EndProject\r
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TiBasicRuntime", "TiBasicRuntime\TiBasicRuntime.csproj", "{3EF3FB61-5A24-4268-90EC-8FF9101CEF7D}"\r
 EndProject\r
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApplication1", "ConsoleApplication1\ConsoleApplication1.csproj", "{ECE963CB-0608-494D-AE1E-17BA9E9ACC9C}"\r
+EndProject\r
 Global\r
        GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
                Debug|Any CPU = Debug|Any CPU\r
@@ -19,6 +21,10 @@ Global
                {3EF3FB61-5A24-4268-90EC-8FF9101CEF7D}.Debug|Any CPU.Build.0 = Debug|Any CPU\r
                {3EF3FB61-5A24-4268-90EC-8FF9101CEF7D}.Release|Any CPU.ActiveCfg = Release|Any CPU\r
                {3EF3FB61-5A24-4268-90EC-8FF9101CEF7D}.Release|Any CPU.Build.0 = Release|Any CPU\r
+               {ECE963CB-0608-494D-AE1E-17BA9E9ACC9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r
+               {ECE963CB-0608-494D-AE1E-17BA9E9ACC9C}.Debug|Any CPU.Build.0 = Debug|Any CPU\r
+               {ECE963CB-0608-494D-AE1E-17BA9E9ACC9C}.Release|Any CPU.ActiveCfg = Release|Any CPU\r
+               {ECE963CB-0608-494D-AE1E-17BA9E9ACC9C}.Release|Any CPU.Build.0 = Release|Any CPU\r
        EndGlobalSection\r
        GlobalSection(SolutionProperties) = preSolution\r
                HideSolutionNode = FALSE\r
index e85489c..23c3502 100644 (file)
@@ -51,7 +51,7 @@ namespace mbasic
 \r
         public double NumericValue { get { return double.Parse(value); } }\r
 \r
-        public string Label { get { return label; } }\r
+        //public string Label { get { return label; } }\r
 \r
         public Token Next()\r
         {\r
@@ -133,6 +133,8 @@ namespace mbasic
                     case '^':\r
                     case '(':\r
                     case ')':\r
+                    case ';':\r
+                    case ':':\r
                         reader.Advance();\r
                         return (Token) ch;\r
                     default:\r
@@ -266,7 +268,8 @@ namespace mbasic
             return Token.String;\r
         }\r
 \r
-        public int LineNumber { get { return reader.LineNumber; } }\r
+        public LineId LineId { get { return new LineId(reader.LineNumber, label); } }\r
+        //public int LineNumber { get { return reader.LineNumber; } }\r
         public int Column { get { return reader.Column; } }\r
 \r
         private class Reader\r
diff --git a/mbasic/LineId.cs b/mbasic/LineId.cs
new file mode 100644 (file)
index 0000000..ecdc6b1
--- /dev/null
@@ -0,0 +1,39 @@
+/*******************************************************************************\r
+    Copyright 2006 Michael Welch\r
+    \r
+    This file is part of MBasic99.\r
+\r
+    MBasic99 is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    MBasic99 is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with MBasic99; if not, write to the Free Software\r
+    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
+*******************************************************************************/\r
+\r
+namespace mbasic\r
+{\r
+    using System;\r
+\r
+    class LineId\r
+    {\r
+        readonly int line;\r
+        readonly string label;\r
+        public static readonly LineId None = new LineId(-1, "");\r
+        public LineId(int line, string label)\r
+        {\r
+            this.label = label;\r
+            this.line = line;\r
+        }\r
+\r
+        public string Label { get { return label; } }\r
+        public int Number { get { return line; } }\r
+    }\r
+}
\ No newline at end of file
index 0366540..ef47692 100644 (file)
@@ -53,7 +53,7 @@ namespace mbasic
             if (lookahead == Token.EOF && t == Token.EndOfLine) return;\r
 \r
             if (lookahead == t) lookahead = lexer.Next();\r
-            else throw new Exception(String.Format("Parsing exception on label {0}", lexer.Label));\r
+            else throw new Exception(String.Format("Parsing exception on label {0}", lexer.LineId.Label));\r
         }\r
 \r
         private Statement Statement()\r
@@ -99,14 +99,14 @@ namespace mbasic
 \r
         private Statement EndStatement()\r
         {\r
-            int line = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
             Match(Token.End);\r
             return new End(line);\r
         }\r
 \r
         private Statement CallSubroutine()\r
         {\r
-            int line = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
             Match(Token.Call);\r
             string name = lexer.Value;\r
             Match(Token.Subroutine);\r
@@ -116,20 +116,21 @@ namespace mbasic
 \r
         private Statement Randomize()\r
         {\r
-            int lineNumber = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
             Match(Token.Randomize);\r
             if (lookahead == Token.Number)\r
             {\r
                 double seedValue = lexer.NumericValue;\r
                 Match(Token.Number);\r
-                return new Randomize(Convert.ToInt32(Math.Floor(seedValue)), lexer.LineNumber);\r
+                return new Randomize(Convert.ToInt32(Math.Floor(seedValue)), \r
+                    line);\r
             }\r
-            return new Randomize(lineNumber);\r
+            return new Randomize(line);\r
         }\r
 \r
         private Statement IfStatement()\r
         {\r
-            int line = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
             Match(Token.If);\r
             Expression conditional = Expression();\r
             Match(Token.Then);\r
@@ -147,7 +148,7 @@ namespace mbasic
 \r
         private Statement Goto()\r
         {\r
-            int line = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
             Match(Token.Goto);\r
             string label = lexer.Value;\r
             Match(Token.Number);\r
@@ -156,7 +157,7 @@ namespace mbasic
 \r
         private Statement Input()\r
         {\r
-            int line = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
             Match(Token.Input);\r
             int index = lexer.SymbolIndex;\r
             Match(Token.Variable);\r
@@ -165,7 +166,7 @@ namespace mbasic
 \r
         private Statement Assign()\r
         {\r
-            int line = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
             int index = lexer.SymbolIndex;\r
             Match(Token.Variable);\r
             Match(Token.Equals);\r
@@ -185,7 +186,7 @@ namespace mbasic
         {\r
             if (lookahead == Token.Concatenate)\r
             {\r
-                int line = lexer.LineNumber;\r
+                LineId line = lexer.LineId;\r
                 Match(Token.Concatenate);\r
                 Expression s2 = StringExpr();\r
                 return MoreStringExpr(new Concatenate(s1, s2, line));\r
@@ -203,7 +204,7 @@ namespace mbasic
         {\r
             Expression r2;\r
             Expression r3=null;\r
-            int line = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
 \r
             switch (lookahead)\r
             {\r
@@ -237,7 +238,7 @@ namespace mbasic
 \r
         Expression MoreAdditionExpr(Expression a1)\r
         {\r
-            int line = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
             switch (lookahead)\r
             {\r
                 case Token.Plus:\r
@@ -263,7 +264,7 @@ namespace mbasic
 \r
         Expression MoreMultiplicationExpr(Expression m1)\r
         {\r
-            int line = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
             switch (lookahead)\r
             {\r
                 case Token.Times:\r
@@ -289,7 +290,7 @@ namespace mbasic
 \r
         Expression MoreFactors(Expression f1)\r
         {\r
-            int line = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
             if (lookahead == Token.Exponent)\r
             {\r
                 Match(lookahead);\r
@@ -313,7 +314,7 @@ namespace mbasic
                     string name = lexer.Value;\r
                     Match(Token.Function);\r
                     Expression[] args = ArgList();\r
-                    return new Function(name, lexer.LineNumber, args);\r
+                    return new Function(name, lexer.LineId, args);\r
 \r
                 case Token.Variable:\r
                     return VariableReference();\r
@@ -354,28 +355,28 @@ namespace mbasic
         Expression UnaryMinus()\r
         {\r
             Match(Token.Minus);\r
-            int line = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
             Expression e = Expression();\r
             return new Negative(e, line);\r
         }\r
 \r
         Expression StringLiteral()\r
         {\r
-            StringLiteral literal = new StringLiteral(lexer.Value, lexer.LineNumber);\r
+            StringLiteral literal = new StringLiteral(lexer.Value, lexer.LineId);\r
             Match(Token.String);\r
             return literal;\r
         }\r
 \r
         Expression NumberLiteral()\r
         {\r
-            NumberLiteral literal = new NumberLiteral(lexer.NumericValue, lexer.LineNumber);\r
+            NumberLiteral literal = new NumberLiteral(lexer.NumericValue, lexer.LineId);\r
             Match(Token.Number);\r
             return literal;\r
         }\r
 \r
         Expression VariableReference()\r
         {\r
-            VariableReference var = new VariableReference(lexer.SymbolIndex, lexer.LineNumber);\r
+            VariableReference var = new VariableReference(lexer.SymbolIndex, lexer.LineId);\r
             Match(Token.Variable);\r
             return var;\r
         }\r
@@ -384,29 +385,88 @@ namespace mbasic
         private Expression Negative()\r
         {\r
             Match(Token.Minus);\r
-            return new Negative(Expression(), lexer.LineNumber);\r
+            return new Negative(Expression(), lexer.LineId);\r
         }\r
 \r
         #endregion Expression Handling\r
 \r
         private Statement Print()\r
         {\r
-            int line = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
             Match(Token.Print);\r
             return new Print(PrintList(), line);\r
         }\r
 \r
-        private Expression PrintList()\r
+        private Expression[] PrintList()\r
         {\r
-            return Expression();\r
+            List<Expression> list = new List<Expression>();\r
+\r
+            switch (lookahead)\r
+            {\r
+                case Token.Plus:\r
+                case Token.Minus:\r
+                case Token.Function:\r
+                case Token.LeftParen:\r
+                case Token.Number:\r
+                case Token.String:\r
+                case Token.Variable:\r
+                    list.Add(Expression());\r
+                    list.AddRange(MorePrintList());\r
+                    break;\r
+                case Token.Comma:\r
+                case Token.Semicolon:\r
+                case Token.Colon:\r
+                    list.AddRange(MorePrintList());\r
+                    break;\r
+                case Token.Tab:\r
+                    Match(Token.Tab);\r
+                    Match(Token.LeftParen);\r
+                    list.Add(new StringLiteral("\t" + lexer.NumericValue, lexer.LineId));\r
+                    \r
+                    Match(Token.Number);\r
+                    Match(Token.RightParen);\r
+                    list.AddRange(MorePrintList());\r
+                    break;\r
+                case Token.EndOfLine:\r
+                case Token.EOF:\r
+                    break;\r
+                default:\r
+                    throw new Exception("Error parsing print list on " + lexer.LineId.Label);\r
+            }\r
+            \r
+            return list.ToArray();\r
         }\r
 \r
+        private Expression[] MorePrintList()\r
+        {\r
+            List<Expression> list = new List<Expression>();\r
+            switch (lookahead)\r
+            {\r
+                case Token.Semicolon:\r
+                    list.Add(new StringLiteral("\0", lexer.LineId));\r
+                    Match(Token.Semicolon);\r
+                    break;\r
+                case Token.Colon:\r
+                    list.Add(new StringLiteral("\n", lexer.LineId));\r
+                    Match(Token.Colon);\r
+                    break;\r
+                case Token.Comma:\r
+                    list.Add(new StringLiteral("\t", lexer.LineId));\r
+                    Match(Token.Comma);\r
+                    break;\r
+            }\r
+            list.AddRange(PrintList());\r
+            return list.ToArray();\r
+\r
+        }\r
+\r
+\r
 \r
         private void Error() { throw new Exception("Error during parsing"); }\r
 \r
         private Statement ForStatement()\r
         {\r
-            int line = lexer.LineNumber;\r
+            LineId line = lexer.LineId;\r
             Match(Token.For);\r
 \r
             int index = lexer.SymbolIndex;\r
@@ -422,15 +482,16 @@ namespace mbasic
 \r
             Match(Token.EndOfLine);\r
 \r
+            LineId blockStart = lexer.LineId;\r
             Block block = Block(Token.Next);\r
 \r
-            int endLine = lexer.LineNumber;\r
+            LineId endLine = lexer.LineId;\r
             Match(Token.Next);\r
             Match(Token.Variable);\r
 \r
             Assign init = new Assign(index, startVal, line);\r
-            Assign update = new Assign(index, new Increment(index, line), endLine);\r
-            Expression comparison = new GreaterThan(new VariableReference(index, line), endVal, false, line);\r
+            Assign update = new Assign(index, new Increment(index, endLine), endLine);\r
+            Expression comparison = RelationalExpression.CompareLessThanEquals(new VariableReference(index, line), endVal, line);\r
             return new For(init, comparison, update, block);\r
         }\r
 \r
index 65a0cbc..f659e8e 100644 (file)
@@ -39,7 +39,12 @@ namespace mbasic
         {\r
             bool debug = true;\r
             bool runit = true;\r
+\r
             string fileName = args[0];\r
+            string assemblyName = Path.GetFileNameWithoutExtension(fileName);\r
+            string moduleName = assemblyName + ".exe";\r
+            string exeName = assemblyName + ".exe";\r
+\r
             Stream stream = File.OpenRead(fileName);\r
             SymbolTable symbols = new SymbolTable();\r
             InitializeReservedWords(symbols);\r
@@ -49,9 +54,8 @@ namespace mbasic
             Statement n = parser.Parse();\r
 \r
             Node.symbols = symbols;\r
-\r
             AppDomain domain = AppDomain.CurrentDomain;\r
-            AssemblyName name = new AssemblyName("myassembly");\r
+            AssemblyName name = new AssemblyName(assemblyName);\r
             AssemblyBuilder bldr = domain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);\r
 \r
             if (debug)\r
@@ -63,16 +67,15 @@ namespace mbasic
                     DebuggableAttribute.DebuggingModes.Default });\r
                 bldr.SetCustomAttribute(daBuilder);\r
             }\r
-            ModuleBuilder mbldr = bldr.DefineDynamicModule("mymodule1", "myassembly.exe", debug);\r
+            ModuleBuilder mbldr = bldr.DefineDynamicModule(moduleName, exeName, debug);\r
 \r
-            TypeBuilder typeBuilder = mbldr.DefineType("Program", TypeAttributes.BeforeFieldInit \r
+            TypeBuilder typeBuilder = mbldr.DefineType("TiBasic.Program", TypeAttributes.BeforeFieldInit \r
                 | TypeAttributes.Sealed | TypeAttributes.AnsiClass | TypeAttributes.Abstract);\r
 \r
 \r
 \r
 \r
 \r
-\r
             MethodBuilder mthdbldr = typeBuilder.DefineMethod("Main", MethodAttributes.Static | MethodAttributes.Public);\r
 \r
             ILGenerator gen = mthdbldr.GetILGenerator();\r
@@ -116,7 +119,7 @@ namespace mbasic
 \r
             Type program = typeBuilder.CreateType();\r
             bldr.SetEntryPoint(mthdbldr);\r
-            bldr.Save("myassembly.exe");\r
+            bldr.Save(exeName);\r
 \r
             if (runit)\r
             {\r
@@ -142,6 +145,7 @@ namespace mbasic
             symbols.ReserveWord("LET", Token.Let);\r
             symbols.ReserveWord("END", Token.End);\r
             symbols.ReserveWord("STOP", Token.End);\r
+            symbols.ReserveWord("TAB", Token.Tab);\r
 \r
             // String Functionis\r
             symbols.ReserveWord("ASC", Token.Function);\r
index 101d771..f134e95 100644 (file)
@@ -31,7 +31,7 @@ namespace mbasic.SyntaxTree
         Expression op1;\r
         Expression op2;\r
         BasicType type;\r
-        public Add(Expression e1, Expression e2, int line)\r
+        public Add(Expression e1, Expression e2, LineId line)\r
             : base(line)\r
         {\r
             this.op1 = e1;\r
index 678ef90..74457db 100644 (file)
@@ -28,7 +28,7 @@ namespace mbasic.SyntaxTree
     {\r
         int localIndex;\r
         Expression value;\r
-        public Assign(int index, Expression value, int line)\r
+        public Assign(int index, Expression value, LineId line)\r
             : base(line)\r
         {\r
             this.localIndex = index;\r
index 4f66465..f2b57df 100644 (file)
@@ -32,7 +32,7 @@ namespace mbasic.SyntaxTree
     {\r
         StatementList stmts;\r
         public Block(StatementList stmts)\r
-            : base(-1)\r
+            : base(LineId.None)\r
         {\r
             this.stmts = stmts;\r
         }\r
index 29e92d1..79d9fea 100644 (file)
@@ -34,7 +34,7 @@ namespace mbasic.SyntaxTree
         Expression s1;\r
         Expression s2;\r
         BasicType type;\r
-        public Concatenate(Expression s1, Expression s2, int line)\r
+        public Concatenate(Expression s1, Expression s2, LineId line)\r
             : base(line)\r
         {\r
             this.s1 = s1;\r
index c36c464..f48c9be 100644 (file)
@@ -31,7 +31,7 @@ namespace mbasic.SyntaxTree
         Expression op2;\r
         BasicType type;\r
 \r
-        public Division(Expression e1, Expression e2, int line)\r
+        public Division(Expression e1, Expression e2, LineId line)\r
             : base(line)\r
         {\r
             this.op1 = e1;\r
index af4f6e0..2944987 100644 (file)
@@ -26,7 +26,7 @@ namespace mbasic.SyntaxTree
 {\r
     class End : Statement\r
     {\r
-        public End(int line) : base(line) { }\r
+        public End(LineId line) : base(line) { }\r
 \r
         public override void CheckTypes()\r
         {\r
index 4992c01..25d3160 100644 (file)
@@ -32,7 +32,7 @@ namespace mbasic.SyntaxTree
         private static readonly MethodInfo equalsMethod =\r
             typeof(Object).GetMethod("Equals", new Type[] { typeof(Object), typeof(Object) });\r
 \r
-        public Equals(Expression e1, Expression e2, bool not, int line)\r
+        public Equals(Expression e1, Expression e2, bool not, LineId line)\r
             : base(e1, e2, not, line)\r
         {\r
         }\r
index 8dd52a0..41a2b79 100644 (file)
@@ -27,10 +27,14 @@ namespace mbasic.SyntaxTree
 {\r
     abstract class Expression : Node\r
     {\r
-        protected string label;\r
         public abstract BasicType GetBasicType();\r
 \r
-        protected Expression(int line) : base(line) { label = lexer.Label; }\r
+        protected Expression(LineId line) : base(line) { }\r
 \r
+        protected void TypeMismtach()\r
+        {\r
+            string msg = String.Format("Type Mismatch On {0}", line.Label);\r
+            throw new Exception(msg);\r
+        }\r
     }\r
 }\r
index da73d73..7c4ffbd 100644 (file)
@@ -37,7 +37,7 @@ namespace mbasic.SyntaxTree
         Statement stmt;\r
 \r
         public For(Assign init, Expression comparison, Assign update, Statement stmt)\r
-            : base(-1)\r
+            : base(LineId.None)\r
         {\r
             this.init = init;\r
             this.comparison = comparison;\r
@@ -77,7 +77,7 @@ namespace mbasic.SyntaxTree
             stmt.Emit(gen);\r
 \r
             // Update counter\r
-            update.Emit(gen, true);\r
+            update.Emit(gen, false);\r
 \r
             gen.MarkLabel(condition);\r
             comparison.Emit(gen);\r
index 7d5c49c..8efeb9f 100644 (file)
@@ -80,7 +80,7 @@ namespace mbasic.SyntaxTree
         string functionName;\r
         Expression[] exprs;\r
         BasicType[] argsTypes;\r
-        public Function(string name, int line, params Expression[] expressions)\r
+        public Function(string name, LineId line, params Expression[] expressions)\r
             : base(line)\r
         {\r
             this.functionName = name;\r
@@ -99,25 +99,25 @@ namespace mbasic.SyntaxTree
                     EmitFunctionCall(gen, intMethod, exprs[0]);\r
                     break;\r
                 case "ASC":\r
-                    EmitFunctionCall(gen, ascMethod, label, exprs[0]);\r
+                    EmitFunctionCall(gen, ascMethod, line.Label, exprs[0]);\r
                     break;\r
                 case "CHR$":\r
-                    EmitFunctionCall(gen, chrMethod, label, exprs[0]);\r
+                    EmitFunctionCall(gen, chrMethod, line.Label, exprs[0]);\r
                     break;\r
                 case "LEN":\r
                     EmitFunctionCall(gen, lenMethod, exprs[0]);\r
                     break;\r
                 case "POS":\r
-                    EmitFunctionCall(gen, posMethod, label, exprs[0], exprs[1], exprs[2]);\r
+                    EmitFunctionCall(gen, posMethod, line.Label, exprs[0], exprs[1], exprs[2]);\r
                     break;\r
                 case "SEG$":\r
-                    EmitFunctionCall(gen, segMethod, label, exprs[0], exprs[1], exprs[2]);\r
+                    EmitFunctionCall(gen, segMethod, line.Label, exprs[0], exprs[1], exprs[2]);\r
                     break;\r
                 case "STR$":\r
                     EmitFunctionCall(gen, strMethod, exprs[0]);\r
                     break;\r
                 case "VAL":\r
-                    EmitFunctionCall(gen, valMethod, label, exprs[0]);\r
+                    EmitFunctionCall(gen, valMethod, line.Label, exprs[0]);\r
                     break;\r
 \r
                     // Numeric Functions\r
@@ -134,7 +134,7 @@ namespace mbasic.SyntaxTree
                     EmitFunctionCall(gen, expMethod, exprs[0]);\r
                     break;\r
                 case "LOG":\r
-                    EmitFunctionCall(gen, logMethod, label, exprs[0]);\r
+                    EmitFunctionCall(gen, logMethod, line.Label, exprs[0]);\r
                     break;\r
                 case "SGN":\r
                     EmitFunctionCall(gen, sgnMethod, exprs[0]);\r
@@ -144,7 +144,7 @@ namespace mbasic.SyntaxTree
                     EmitFunctionCall(gen, sinMethod, exprs[0]);\r
                     break;\r
                 case "SQR":\r
-                    EmitFunctionCall(gen, sqrMethod, label, exprs[0]);\r
+                    EmitFunctionCall(gen, sqrMethod, line.Label, exprs[0]);\r
                     break;\r
                 case "TAN":\r
                     EmitFunctionCall(gen, tanMethod, exprs[0]);\r
index 36d384e..6c8626e 100644 (file)
@@ -29,7 +29,7 @@ namespace mbasic.SyntaxTree
     class Goto : Statement\r
     {\r
         string destLabel;\r
-        public Goto(string label, int line)\r
+        public Goto(string label, LineId line)\r
             : base(line)\r
         {\r
             this.destLabel = label;\r
index 4acd229..29f79fa 100644 (file)
@@ -30,7 +30,7 @@ namespace mbasic.SyntaxTree
     {\r
         \r
         public GreaterThan(Expression expr1, Expression expr2, bool not,\r
-            int line)\r
+            LineId line)\r
             : base(expr1, expr2, not, line)\r
         {\r
         }\r
index 45bb814..6c64e0d 100644 (file)
@@ -30,14 +30,14 @@ namespace mbasic.SyntaxTree
         Goto jmp;\r
         Goto elseJmp;\r
         Expression conditional;\r
-        public If(Expression conditional, string label, int line) : base(line)\r
+        public If(Expression conditional, string label, LineId line) : base(line)\r
         {\r
             jmp = new Goto(label, line);\r
             this.conditional = conditional;\r
         }\r
 \r
         public If(Expression conditional, string label, string elseLabel,\r
-            int line)\r
+            LineId line)\r
             : base(line)\r
         {\r
             jmp = new Goto(label, line);\r
@@ -48,7 +48,6 @@ namespace mbasic.SyntaxTree
         public override void CheckTypes()\r
         {\r
             if (conditional.GetBasicType() == BasicType.Number) return;\r
-            TypeMismtach();\r
         }\r
 \r
         public override void Emit(ILGenerator gen)\r
index 7ab06a3..557ad46 100644 (file)
@@ -28,7 +28,7 @@ namespace mbasic.SyntaxTree
     class Increment : Expression\r
     {\r
         int index;\r
-        public Increment(int index, int line)\r
+        public Increment(int index, LineId line)\r
             : base(line)\r
         {\r
             this.index = index;\r
index 7063706..a8ed093 100644 (file)
@@ -36,7 +36,8 @@ namespace mbasic.SyntaxTree
             new Type[] { typeof(string), Type.GetType("System.Double&") });\r
         int index;\r
         BasicType varType;\r
-        public Input(int index, int line) : base(line)\r
+        public Input(int index, LineId line)\r
+            : base(line)\r
         {\r
             this.index = index; \r
         }\r
index 0e23c83..8684caa 100644 (file)
@@ -28,7 +28,7 @@ namespace mbasic.SyntaxTree
     class LessThan : RelationalExpression\r
     {\r
 \r
-        public LessThan(Expression e1, Expression e2, bool not, int line)\r
+        public LessThan(Expression e1, Expression e2, bool not, LineId line)\r
             : base(e1, e2, not, line)\r
         {\r
         }\r
index e52a3e9..eaa5f14 100644 (file)
@@ -32,7 +32,7 @@ namespace mbasic.SyntaxTree
         Expression op2;\r
         BasicType type;\r
 \r
-        public Multiply(Expression e1, Expression e2, int line)\r
+        public Multiply(Expression e1, Expression e2, LineId line)\r
             : base(line)\r
         {\r
             this.op1 = e1;\r
index 496d8c0..ec1903a 100644 (file)
@@ -30,7 +30,7 @@ namespace mbasic.SyntaxTree
     {\r
         Expression value;\r
         BasicType type;\r
-        public Negative(Expression value, int line) : base(line)\r
+        public Negative(Expression value, LineId line) : base(line)\r
         {\r
             this.value = value;\r
         }\r
index e8f6ec9..6b6ed1e 100644 (file)
@@ -38,24 +38,19 @@ using System.Reflection;
         public static LabelList labels;\r
         public static Label endLabel;\r
 \r
+        protected Node(LineId line) { this.line = line; }\r
+\r
         public abstract void Emit(ILGenerator gen);\r
+        protected readonly LineId line;\r
 \r
         public static bool debug;\r
         public static ISymbolDocumentWriter writer;\r
-        protected int line;\r
-        protected Node(int lineNumber)\r
-        {\r
-            this.line = lineNumber;\r
-        }\r
 \r
 \r
 \r
 \r
-        protected void TypeMismtach()\r
-        {\r
-            string msg = String.Format("Type Mismatch on line {0}", line);\r
-            throw new Exception(msg);\r
-        }\r
+\r
+\r
 \r
         private static readonly MethodInfo writeMethod =\r
             typeof(Console).GetMethod("Write", new Type[] { typeof(string) });\r
index 5b9fc03..dd73e8c 100644 (file)
@@ -29,7 +29,7 @@ namespace mbasic.SyntaxTree
     internal class NumberLiteral : Expression\r
     {\r
         double val;\r
-        public NumberLiteral(double d, int line)\r
+        public NumberLiteral(double d, LineId line)\r
             : base(line)\r
         {\r
             this.val = d;\r
index bd3a0e4..4eaa793 100644 (file)
@@ -33,7 +33,7 @@ namespace mbasic.SyntaxTree
         Expression op1;\r
         Expression op2;\r
         BasicType type;\r
-        public Power(Expression e1, Expression e2, int line)\r
+        public Power(Expression e1, Expression e2, LineId line)\r
             : base(line)\r
         {\r
             this.op1 = e1;\r
index 6d72f59..cffe301 100644 (file)
@@ -29,17 +29,15 @@ namespace mbasic.SyntaxTree
 {\r
     internal class Print : Statement\r
     {\r
-        static readonly MethodInfo methodInfoString = \r
-            typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) });\r
+        static readonly MethodInfo printMethod = \r
+            typeof(BuiltIns).GetMethod("Print");\r
 \r
-        static readonly MethodInfo toStringMethod =\r
-            typeof(Radix100).GetMethod("ToString", new Type[] { typeof(double) });\r
-\r
-        Expression value;\r
-        BasicType printItemType;\r
-        public Print(Expression value, int line) : base(line)\r
+        Expression[] values;\r
+        BasicType[] printItemTypes;\r
+        public Print(Expression[] values, LineId line) : base(line)\r
         {\r
-            this.value = value;\r
+            this.values = values;\r
+            printItemTypes = new BasicType[values.Length];\r
         }\r
 \r
         public override void Emit(ILGenerator gen)\r
@@ -51,16 +49,32 @@ namespace mbasic.SyntaxTree
         {\r
             if (!labelSetAlready) MarkLabel(gen);\r
             MarkSequencePoint(gen);\r
-            value.Emit(gen);\r
-            if (printItemType == BasicType.Number) gen.Emit(OpCodes.Call, toStringMethod);\r
 \r
-            gen.EmitCall(OpCodes.Call, methodInfoString, new Type[0]);\r
+\r
+            // create object array\r
+            gen.Emit(OpCodes.Ldc_I4, values.Length);\r
+            gen.Emit(OpCodes.Newarr, typeof(object));\r
+            \r
+\r
+            for (int i = 0; i < values.Length; i++)\r
+            {\r
+                gen.Emit(OpCodes.Dup); // Duplicate the array reference, so it's still on stack after this use\r
+                gen.Emit(OpCodes.Ldc_I4, i);\r
+                values[i].Emit(gen);\r
+                if (printItemTypes[i] == BasicType.Number) gen.Emit(OpCodes.Box, typeof(double));\r
+                gen.Emit(OpCodes.Stelem_Ref);\r
+            }\r
+            gen.Emit(OpCodes.Call, printMethod);\r
+\r
         }\r
 \r
         public override void CheckTypes()\r
         {\r
-            printItemType = value.GetBasicType();\r
-            if (printItemType == BasicType.Error) throw new Exception("Bad type in print statement");\r
+            for (int i = 0; i < values.Length; i++)\r
+            {\r
+                printItemTypes[i] = values[i].GetBasicType();\r
+                if (printItemTypes[i] == BasicType.Error) throw new Exception("Bad type in print statement");\r
+            }\r
         }\r
 \r
 \r
index 5a72be1..80682c1 100644 (file)
@@ -39,12 +39,12 @@ namespace mbasic.SyntaxTree
         int seedValue;\r
         bool seedSpecified;\r
 \r
-        public Randomize(int line) : base(line) \r
+        public Randomize(LineId line) : base(line) \r
         {\r
             seedSpecified = false;\r
         }\r
 \r
-        public Randomize(int seedValue, int line)\r
+        public Randomize(int seedValue, LineId line)\r
             : base(line)\r
         {\r
             this.seedValue = seedValue;\r
index c7f29ec..d1de929 100644 (file)
@@ -39,7 +39,7 @@ namespace mbasic.SyntaxTree
             new Type[] { typeof(string), typeof(string) });\r
 \r
         protected RelationalExpression(Expression e1,\r
-            Expression e2, bool not, int line)\r
+            Expression e2, bool not, LineId line)\r
             : base(line)\r
         {\r
             this.e1 = e1;\r
@@ -82,37 +82,37 @@ namespace mbasic.SyntaxTree
         protected abstract void EmitOperation(ILGenerator gen);\r
 \r
         public static RelationalExpression CompareEquals(\r
-            Expression e1, Expression e2, int line)\r
+            Expression e1, Expression e2, LineId line)\r
         {\r
             return new Equals(e1, e2, false, line);\r
         }\r
 \r
         public static RelationalExpression CompareNotEquals(\r
-            Expression e1, Expression e2, int line)\r
+            Expression e1, Expression e2, LineId line)\r
         {\r
             return new Equals(e1, e2, true, line);\r
         }\r
 \r
         public static RelationalExpression CompareLessThan(\r
-            Expression e1, Expression e2, int line)\r
+            Expression e1, Expression e2, LineId line)\r
         {\r
             return new LessThan(e1, e2, false, line);\r
         }\r
 \r
         public static RelationalExpression CompareLessThanEquals(\r
-            Expression e1, Expression e2, int line)\r
+            Expression e1, Expression e2, LineId line)\r
         {\r
             return new GreaterThan(e1, e2, true, line);\r
         }\r
 \r
         public static RelationalExpression CompareGreaterThan(\r
-            Expression e1, Expression e2, int line)\r
+            Expression e1, Expression e2, LineId line)\r
         {\r
             return new GreaterThan(e1, e2, false, line);\r
         }\r
 \r
         public static RelationalExpression CompareGreaterThanEquals(\r
-            Expression e1, Expression e2, int line)\r
+            Expression e1, Expression e2, LineId line)\r
         {\r
             return new LessThan(e1, e2, true, line);\r
         }\r
index f909a7b..06a9eea 100644 (file)
@@ -29,30 +29,27 @@ namespace mbasic.SyntaxTree
 \r
     abstract class Statement : Node\r
     {\r
-        protected string label; // The actual string label from source (e.g. 100)\r
         Label lineLabel;        // A .NET label used to mark this location.\r
 \r
-        protected Statement(int line)\r
-            : base(line)\r
+        protected Statement(LineId line) : base(line)\r
         {\r
-            this.label = lexer.Label;\r
         }\r
         public abstract void CheckTypes();\r
         public virtual void RecordLabels(ILGenerator gen)\r
         {\r
+            if (labels.ContainsKey(line.Label)) return;\r
             this.lineLabel = gen.DefineLabel();\r
-            if (labels.ContainsKey(label)) return;\r
 \r
-            labels.Add(label, lineLabel);\r
+            labels.Add(line.Label, lineLabel);\r
         }\r
 \r
         private static List<int> lines = new List<int>();\r
         protected void MarkSequencePoint(ILGenerator gen)\r
         {\r
-            if (debug & lines.BinarySearch(line) < 0)\r
+            if (debug & lines.BinarySearch(line.Number) < 0)\r
             {\r
-                gen.MarkSequencePoint(writer, line, 1, line, 100);\r
-                lines.Add(line);\r
+                gen.MarkSequencePoint(writer, line.Number, 1, line.Number, 100);\r
+                lines.Add(line.Number);\r
             }\r
         }\r
 \r
index 5689292..048d95e 100644 (file)
@@ -29,7 +29,7 @@ namespace mbasic.SyntaxTree
     internal class StringLiteral : Expression\r
     {\r
         string val;\r
-        public StringLiteral(string s, int line)\r
+        public StringLiteral(string s, LineId line)\r
             : base(line)\r
         {\r
             this.val = s;\r
index c366a8e..349d3dd 100644 (file)
@@ -33,7 +33,7 @@ namespace mbasic.SyntaxTree
             typeof(Console).GetMethod("Clear");\r
 \r
         string name;\r
-        public Subroutine(string name, int lineNumber)\r
+        public Subroutine(string name, LineId lineNumber)\r
             : base(lineNumber)\r
         {\r
             this.name = name;\r
index 58911bc..6c698f0 100644 (file)
@@ -31,7 +31,7 @@ namespace mbasic.SyntaxTree
         Expression op2;\r
         BasicType type;\r
 \r
-        public Subtract(Expression e1, Expression e2, int line)\r
+        public Subtract(Expression e1, Expression e2, LineId line)\r
             : base(line)\r
         {\r
             this.op1 = e1;\r
index 95a35d8..f85cd30 100644 (file)
@@ -29,7 +29,7 @@ namespace mbasic.SyntaxTree
     internal class VariableReference : Expression\r
     {\r
         int index; // index into variables symbol table\r
-        public VariableReference(int index, int line)\r
+        public VariableReference(int index, LineId line)\r
             : base(line)\r
         {\r
             this.index = index;\r
index f0699d1..84138a6 100644 (file)
@@ -21,6 +21,7 @@
 \r
 internal enum Token \r
 {\r
+    Colon       = ':',\r
     Comma       = ',',\r
     Exponent    = '^',\r
     LessThan    = '<',\r
@@ -33,6 +34,7 @@ internal enum Token
     Minus       = '-',\r
     Times       = '*',\r
     Divides     = '/',\r
+    Semicolon   = ';',\r
     And         = 256,\r
     Call,\r
     Else,\r
@@ -59,6 +61,7 @@ internal enum Token
     Remark, // technically not a token, and should never be returned. Used internally by lexer only.\r
     String,\r
     Subroutine,\r
+    Tab,\r
     Then,\r
     To,\r
     Variable\r
index 2bbd3f3..2b823c4 100644 (file)
@@ -2,5 +2,17 @@
 \r
 100 print -10\r
 105 print 7.1\r
+106 print "abcdefghijklmnopqrstuvwxyzabcdefghijk"\r
 110 print .0000000001978531\r
-120 print .0000000001978535
\ No newline at end of file
+120 print .0000000001978535\r
+130 print "A"::"B"\r
+\r
+\r
+150 A=-26\r
+160 B=-33\r
+170 C$="HELLO"\r
+180 D$="HOW ARE YOU?"\r
+190 PRINT A;B;C$;D$\r
+\r
+200 PRINT TAB(5);"Hello from 5"\r
+210 PRINT TAB(6);"Hello from 6"\r
index 554f665..fe0246d 100644 (file)
@@ -34,6 +34,7 @@
   </ItemGroup>\r
   <ItemGroup>\r
     <Compile Include="Lexer.cs" />\r
+    <Compile Include="LineId.cs" />\r
     <Compile Include="Parser.cs" />\r
     <Compile Include="Program.cs" />\r
     <Compile Include="Properties\AssemblyInfo.cs" />\r
@@ -72,7 +73,9 @@
     <Compile Include="Variable.cs" />\r
   </ItemGroup>\r
   <ItemGroup>\r
+    <None Include="ForStatementTest.mbas" />\r
     <None Include="helloworld.mbas" />\r
+    <None Include="print.mbas" />\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ProjectReference Include="..\TiBasicRuntime\TiBasicRuntime.csproj">\r
index f6d38c5..e5f7216 100644 (file)
 220 IF SECRET<LOW THEN 260
 230 IF SECRET>HIGH THEN 280
 
-240 PRINT MSG1$&" BETWEEN "&MSG2$
+240 PRINT MSG1$&" BETWEEN":MSG2$
 250 GOTO 180
-260 PRINT MSG1$&" LESS THAN " & MSG2$
+260 PRINT MSG1$&" LESS THAN" : MSG2$
 270 GOTO 180
-280 PRINT MSG1$&" LARGER THAN " & MSG2$
+280 PRINT MSG1$&" LARGER THAN": MSG2$
 290 GOTO 180
 300 PRINT "YOU GUESSED THE SECRET"
-310 PRINT "NUMBER IN"
-311 PRINT N
-312 PRINT "TRIES."
+310 PRINT "NUMBER IN";N;"TRIES"
 
 320 PRINT "WANT TO PLAY AGAIN?"
 330 PRINT "ENTER Y OR N: "