Xanathar 10 éve
szülő
commit
253d6ea0e7

+ 6 - 0
src/MoonSharp.Interpreter.Tests/EndToEnd/SimpleTests.cs

@@ -9,6 +9,12 @@ namespace MoonSharp.Interpreter.Tests
 	[TestFixture]
 	public class SimpleTests
 	{
+		[Test]
+		public void EmptyChunk()
+		{
+			Script S = new Script(CoreModules.None);
+			DynValue res = S.DoString("");
+		}
 
 		[Test]
 		public void CSharpStaticFunctionCallStatement()

+ 2 - 0
src/MoonSharp.Interpreter/Execution/ScriptLoadingContext.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using MoonSharp.Interpreter.Debugging;
+using MoonSharp.Interpreter.Tree;
 
 namespace MoonSharp.Interpreter.Execution
 {
@@ -13,6 +14,7 @@ namespace MoonSharp.Interpreter.Execution
 		public SourceCode Source { get; set; }
 		public bool Anonymous { get; set; }
 		public bool IsDynamicExpression { get; set; }
+		public Lexer Lexer { get; set; }
 
 		public ScriptLoadingContext(Script s)
 		{

+ 7 - 1
src/MoonSharp.Interpreter/MoonSharp.Interpreter.csproj

@@ -254,7 +254,6 @@
     <Compile Include="Tree\Expressions\DynamicExpression.cs" />
     <Compile Include="Tree\Expressions\PowerOperatorExpression.cs" />
     <Compile Include="Tree\Expressions\UnaryOperatorExpression.cs" />
-    <Compile Include="Tree\Fast_Interface\llex.cs" />
     <Compile Include="Tree\IVariable.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Tree\Expressions\ExprListExpression.cs" />
@@ -267,6 +266,10 @@
     <Compile Include="Tree\Expressions\OperatorExpression.cs" />
     <Compile Include="Tree\Expressions\SymbolRefExpression.cs" />
     <Compile Include="Tree\Antlr_Interface\Loader_Antlr.cs" />
+    <Compile Include="Tree\Lexer\Lexer.cs" />
+    <Compile Include="Tree\Lexer\LexerBackDoor.cs" />
+    <Compile Include="Tree\Lexer\Token.cs" />
+    <Compile Include="Tree\Lexer\TokenType.cs" />
     <Compile Include="Tree\Loop.cs" />
     <Compile Include="Tree\NodeBase.cs" />
     <Compile Include="Tree\NodeFactory.cs" />
@@ -303,6 +306,9 @@
   <ItemGroup>
     <None Include="packages.config" />
   </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Tree\Fast_Interface\" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
     <PropertyGroup>

+ 5 - 0
src/MoonSharp.Interpreter/Tree/Expression.cs

@@ -14,6 +14,11 @@ namespace MoonSharp.Interpreter.Tree
 			: base(node, lcontext)
 		{ }
 
+		public Expression(ScriptLoadingContext lcontext)
+			: base(null, lcontext)
+		{ }
+
+
 		public abstract DynValue Eval(ScriptExecutionContext context);
 
 		public virtual SymbolRef FindDynamic(ScriptExecutionContext context)

+ 0 - 523
src/MoonSharp.Interpreter/Tree/Fast_Interface/llex.cs

@@ -1,523 +0,0 @@
-#if false
-/*
-** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $
-** Lexical Analyzer
-** See Copyright Notice in lua.h
-*/
-
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Runtime.InteropServices;
-using System.Diagnostics;
-
-namespace KopiLua
-{
-	using TValue = MoonSharp.Interpreter.DataType;
-	using LuaNumberType = System.Double;
-
-	public partial class Lua
-	{
-		public const int FIRSTRESERVED	= 257;
-
-		/* maximum length of a reserved word */
-		public const int TOKENLEN	= 9; // "function"
-
-
-		/*
-		* WARNING: if you change the order of this enumeration,
-		* grep "ORDER RESERVED"
-		*/
-		public enum RESERVED {
-		  /* terminal symbols denoted by reserved words */
-		  TK_AND = FIRSTRESERVED, TK_BREAK,
-		  TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION,
-		  TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT,
-		  TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE,
-		  /* other terminal symbols */
-		  TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER,
-		  TK_NAME, TK_STRING, TK_EOS
-		};
-
-		/* number of reserved words */
-		public const int NUMRESERVED = (int)RESERVED.TK_WHILE - FIRSTRESERVED + 1;
-
-		public class SemInfo {
-			public SemInfo() { }
-			public SemInfo(SemInfo copy)
-			{
-				this.r = copy.r;
-				this.ts = copy.ts;
-			}
-			public LuaNumberType r;
-			public string ts;
-		} ;  /* semantics information */
-
-		public class Token {
-			public Token() { }
-			public Token(Token copy)
-			{
-				this.token = copy.token;
-				this.seminfo = new SemInfo(copy.seminfo);
-			}
-			public int token;
-			public SemInfo seminfo = new SemInfo();
-		};
-
-
-		public class LexState {
-			public int current;  /* current character (charint) */
-			public int linenumber;  /* input line counter */
-			public int lastline;  /* line of last token `consumed' */
-			public Token t = new Token();  /* current token */
-			public Token lookahead = new Token();  /* look ahead token */
-			public FuncState fs;  /* `FuncState' is private to the parser */
-			public LuaState L;
-			public ZIO z;  /* input stream */
-			public Mbuffer buff;  /* buffer for tokens */
-			public string source;  /* current source name */
-			public char decpoint;  /* locale decimal point */
-		};
-
-
-		public static void Next(LexState ls) { ls.current = zgetc(ls.z); }
-
-
-		public static bool CurrIsNewline(LexState ls) { return (ls.current == '\n' || ls.current == '\r'); }
-
-
-		/* ORDER RESERVED */
-		public static readonly string[] LuaXTokens = {
-			"and", "break", "do", "else", "elseif",
-			"end", "false", "for", "function", "if",
-			"in", "local", "nil", "not", "or", "repeat",
-			"return", "then", "true", "until", "while",
-			"..", "...", "==", ">=", "<=", "~=",
-			"<number>", "<name>", "<string>", "<eof>"
-		};
-
-
-		public static void SaveAndNext(LexState ls) {Save(ls, ls.current); Next(ls);}
-
-		private static void Save (LexState ls, int c) {
-		  Mbuffer b = ls.buff;
-		  if (b.n + 1 > b.buffsize) {
-			uint newsize;
-			if (b.buffsize >= MAXSIZET/2)
-			  LuaXLexError(ls, "lexical element too long", 0);
-			newsize = b.buffsize * 2;
-			luaZ_resizebuffer(ls.L, b, (int)newsize);
-		  }
-		  b.buffer[b.n++] = (char)c;
-		}
-
-		
-		public static void LuaXInit (LuaState L) {
-		  int i;
-		  for (i=0; i<NUMRESERVED; i++) {
-			TString ts = luaS_new(L, LuaXTokens[i]);
-			luaS_fix(ts);  /* reserved words are never collected */
-			LuaAssert(LuaXTokens[i].Length+1 <= TOKENLEN);
-			ts.tsv.reserved = CastByte(i+1);  /* reserved word */
-		  }
-		}
-
-
-		public const int MAXSRC          = 80;
-
-
-		public static CharPtr LuaXTokenToString (LexState ls, int token) {
-		  if (token < FIRSTRESERVED) {
-			LuaAssert(token == (byte)token);
-			return (iscntrl(token)) ? LuaOPushFString(ls.L, "char(%d)", token) :
-									  LuaOPushFString(ls.L, "%c", token);
-		  }
-		  else
-			return LuaXTokens[(int)token-FIRSTRESERVED];
-		}
-
-
-		public static CharPtr TextToken (LexState ls, int token) {
-		  switch (token) {
-			case (int)RESERVED.TK_NAME:
-			case (int)RESERVED.TK_STRING:
-			case (int)RESERVED.TK_NUMBER:
-			  Save(ls, '\0');
-			  return luaZ_buffer(ls.buff);
-			default:
-			  return LuaXTokenToString(ls, token);
-		  }
-		}
-
-		public static void LuaXLexError (LexState ls, CharPtr msg, int token) {
-		  CharPtr buff = new char[MAXSRC];
-		  LuaOChunkID(buff, GetStr(ls.source), MAXSRC);
-		  msg = LuaOPushFString(ls.L, "%s:%d: %s", buff, ls.linenumber, msg);
-		  if (token != 0)
-			LuaOPushFString(ls.L, "%s near " + LUA_QS, msg, TextToken(ls, token));
-		  LuaDThrow(ls.L, LUA_ERRSYNTAX);
-		}
-
-		public static void LuaXSyntaxError (LexState ls, CharPtr msg) {
-		  LuaXLexError(ls, msg, ls.t.token);
-		}
-
-		[CLSCompliantAttribute(false)]
-		public static TString LuaXNewString(LexState ls, CharPtr str, uint l)
-		{
-		  LuaState L = ls.L;
-		  TString ts = luaS_newlstr(L, str, l);
-		  TValue o = luaH_setstr(L, ls.fs.h, ts);  /* entry for `str' */
-		  if (TTIsNil (o)) {
-				SetBValue (o, 1);  /* make sure `str' will not be collected */
-				LuaCCheckGC(L);
-		  }
-		  return ts;
-		}
-
-
-		private static void IncLineNumber (LexState ls) {
-		  int old = ls.current;
-		  LuaAssert(CurrIsNewline(ls));
-		  Next(ls);  /* skip `\n' or `\r' */
-		  if (CurrIsNewline(ls) && ls.current != old)
-			Next(ls);  /* skip `\n\r' or `\r\n' */
-		  if (++ls.linenumber >= MAXINT)
-			LuaXSyntaxError(ls, "chunk has too many lines");
-		}
-
-
-		public static void LuaXSetInput (LuaState L, LexState ls, ZIO z, TString source) {
-		  ls.decpoint = '.';
-		  ls.L = L;
-		  ls.lookahead.token = (int)RESERVED.TK_EOS;  /* no look-ahead token */
-		  ls.z = z;
-		  ls.fs = null;
-		  ls.linenumber = 1;
-		  ls.lastline = 1;
-		  ls.source = source;
-		  luaZ_resizebuffer(ls.L, ls.buff, LUAMINBUFFER);  /* initialize buffer */
-		  Next(ls);  /* read first char */
-		}
-
-
-
-		/*
-		** =======================================================
-		** LEXICAL ANALYZER
-		** =======================================================
-		*/
-
-
-		private static int CheckNext (LexState ls, CharPtr set) {
-		  if (strchr(set, (char)ls.current) == null)
-			return 0;
-		  SaveAndNext(ls);
-		  return 1;
-		}
-
-
-		private static void BufferReplace (LexState ls, char from, char to) {
-		  uint n = luaZ_bufflen(ls.buff);
-		  CharPtr p = luaZ_buffer(ls.buff);
-		  while ((n--) != 0)
-			  if (p[n] == from) p[n] = to;
-		}
-
-
-		private static void TryDecPoint (LexState ls, SemInfo seminfo) {
-		  /* format error: try to update decimal point separator */
-			// todo: add proper support for localeconv - mjf
-			//lconv cv = localeconv();
-			char old = ls.decpoint;
-			ls.decpoint = '.'; // (cv ? cv.decimal_point[0] : '.');
-			BufferReplace(ls, old, ls.decpoint);  /* try updated decimal separator */
-			if (LuaOStr2d(luaZ_buffer(ls.buff), out seminfo.r) == 0)
-			{
-				/* format error with correct decimal point: no more options */
-				BufferReplace(ls, ls.decpoint, '.');  /* undo change (for error message) */
-				LuaXLexError(ls, "malformed number", (int)RESERVED.TK_NUMBER);
-			}
-		}
-
-
-		/* LUA_NUMBER */
-		private static void ReadNumeral (LexState ls, SemInfo seminfo) {
-		  LuaAssert(isdigit(ls.current));
-		  do {
-			SaveAndNext(ls);
-		  } while (isdigit(ls.current) || ls.current == '.');
-		  if (CheckNext(ls, "Ee") != 0)  /* `E'? */
-			CheckNext(ls, "+-");  /* optional exponent sign */
-		  while (isalnum(ls.current) || ls.current == '_')
-			SaveAndNext(ls);
-		  Save(ls, '\0');
-		  BufferReplace(ls, '.', ls.decpoint);  /* follow locale for decimal point */
-		  if (LuaOStr2d(luaZ_buffer(ls.buff), out seminfo.r) == 0)  /* format error? */
-			TryDecPoint(ls, seminfo); /* try to update decimal point separator */
-		}
-
-
-		private static int SkipSep (LexState ls) {
-		  int count = 0;
-		  int s = ls.current;
-		  LuaAssert(s == '[' || s == ']');
-		  SaveAndNext(ls);
-		  while (ls.current == '=') {
-			SaveAndNext(ls);
-			count++;
-		  }
-		  return (ls.current == s) ? count : (-count) - 1;
-		}
-
-
-		private static void ReadLongString (LexState ls, SemInfo seminfo, int sep) {
-		  //int cont = 0;
-		  //(void)(cont);  /* avoid warnings when `cont' is not used */
-		  SaveAndNext(ls);  /* skip 2nd `[' */
-		  if (CurrIsNewline(ls))  /* string starts with a newline? */
-			IncLineNumber(ls);  /* skip it */
-		  for (;;) {
-			switch (ls.current) {
-			  case EOZ:
-				LuaXLexError(ls, (seminfo != null) ? "unfinished long string" :
-										   "unfinished long comment", (int)RESERVED.TK_EOS);
-				break;  /* to avoid warnings */
-		#if LUA_COMPAT_LSTR
-			  case '[': {
-				if (skip_sep(ls) == sep) {
-				  save_and_next(ls);  /* skip 2nd `[' */
-				  cont++;
-		#if LUA_COMPAT_LSTR
-				  if (sep == 0)
-					luaX_lexerror(ls, "nesting of [[...]] is deprecated", '[');
-		#endif
-				}
-				break;
-			  }
-		#endif
-			  case ']':
-				if (SkipSep(ls) == sep)
-				{
-				  SaveAndNext(ls);  /* skip 2nd `]' */
-		//#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2
-		//          cont--;
-		//          if (sep == 0 && cont >= 0) break;
-		//#endif
-				  goto endloop;
-				}
-			  break;
-			  case '\n':
-			  case '\r':
-				Save(ls, '\n');
-				IncLineNumber(ls);
-				if (seminfo == null) luaZ_resetbuffer(ls.buff);  /* avoid wasting space */
-				break;
-			  default: {
-				if (seminfo != null) SaveAndNext(ls);
-				else Next(ls);
-			  }
-			  break;
-			}
-		  } endloop:
-		  if (seminfo != null)
-		  {
-			  seminfo.ts = LuaXNewString(ls, luaZ_buffer(ls.buff) + (2 + sep), 
-											(uint)(luaZ_bufflen(ls.buff) - 2*(2 + sep)));
-		  }
-		}
-
-
-		static void ReadString (LexState ls, int del, SemInfo seminfo) {
-		  SaveAndNext(ls);
-		  while (ls.current != del) {
-			switch (ls.current) {
-			  case EOZ:
-				LuaXLexError(ls, "unfinished string", (int)RESERVED.TK_EOS);
-				continue;  /* to avoid warnings */
-			  case '\n':
-			  case '\r':
-				LuaXLexError(ls, "unfinished string", (int)RESERVED.TK_STRING);
-				continue;  /* to avoid warnings */
-			  case '\\': {
-				int c;
-				Next(ls);  /* do not save the `\' */
-				switch (ls.current) {
-				  case 'a': c = '\a'; break;
-				  case 'b': c = '\b'; break;
-				  case 'f': c = '\f'; break;
-				  case 'n': c = '\n'; break;
-				  case 'r': c = '\r'; break;
-				  case 't': c = '\t'; break;
-				  case 'v': c = '\v'; break;
-				  case '\n':  /* go through */
-				  case '\r': Save(ls, '\n'); IncLineNumber(ls); continue;
-				  case EOZ: continue;  /* will raise an error next loop */
-				  default: {
-					if (!isdigit(ls.current))
-					  SaveAndNext(ls);  /* handles \\, \", \', and \? */
-					else {  /* \xxx */
-					  int i = 0;
-					  c = 0;
-					  do {
-						c = 10*c + (ls.current-'0');
-						Next(ls);
-					  } while (++i<3 && isdigit(ls.current));
-					  if (c > System.Byte.MaxValue)
-						LuaXLexError(ls, "escape sequence too large", (int)RESERVED.TK_STRING);
-					  Save(ls, c);
-					}
-					continue;
-				  }
-				}
-				Save(ls, c);
-				Next(ls);
-				continue;
-			  }
-			  default:
-				SaveAndNext(ls);
-				break;
-			}
-		  }
-		  SaveAndNext(ls);  /* skip delimiter */
-		  seminfo.ts = LuaXNewString(ls, luaZ_buffer(ls.buff) + 1,
-		                                  luaZ_bufflen(ls.buff) - 2);
-		}
-
-
-		private static int LLex (LexState ls, SemInfo seminfo) {
-		  luaZ_resetbuffer(ls.buff);
-		  for (;;) {
-			switch (ls.current) {
-			  case '\n':
-			  case '\r': {
-				IncLineNumber(ls);
-				continue;
-			  }
-			  case '-': {
-				Next(ls);
-				if (ls.current != '-') return '-';
-				/* else is a comment */
-				Next(ls);
-				if (ls.current == '[') {
-				  int sep = SkipSep(ls);
-				  luaZ_resetbuffer(ls.buff);  /* `skip_sep' may dirty the buffer */
-				  if (sep >= 0) {
-					ReadLongString(ls, null, sep);  /* long comment */
-					luaZ_resetbuffer(ls.buff);
-					continue;
-				  }
-				}
-				/* else short comment */
-				while (!CurrIsNewline(ls) && ls.current != EOZ)
-				  Next(ls);
-				continue;
-			  }
-			  case '[': {
-				int sep = SkipSep(ls);
-				if (sep >= 0) {
-				  ReadLongString(ls, seminfo, sep);
-				  return (int)RESERVED.TK_STRING;
-				}
-				else if (sep == -1) return '[';
-				else LuaXLexError(ls, "invalid long string delimiter", (int)RESERVED.TK_STRING);
-			  }
-			  break;
-			  case '=': {
-				Next(ls);
-				if (ls.current != '=') return '=';
-				else { Next(ls); return (int)RESERVED.TK_EQ; }
-			  }
-			  case '<': {
-				Next(ls);
-				if (ls.current != '=') return '<';
-				else { Next(ls); return (int)RESERVED.TK_LE; }
-			  }
-			  case '>': {
-				Next(ls);
-				if (ls.current != '=') return '>';
-				else { Next(ls); return (int)RESERVED.TK_GE; }
-			  }
-			  case '~': {
-				Next(ls);
-				if (ls.current != '=') return '~';
-				else { Next(ls); return (int)RESERVED.TK_NE; }
-			  }
-			  case '"':
-			  case '\'': {
-				ReadString(ls, ls.current, seminfo);
-				return (int)RESERVED.TK_STRING;
-			  }
-			  case '.': {
-				SaveAndNext(ls);
-				if (CheckNext(ls, ".") != 0) {
-				  if (CheckNext(ls, ".") != 0)
-					  return (int)RESERVED.TK_DOTS;   /* ... */
-				  else return (int)RESERVED.TK_CONCAT;   /* .. */
-				}
-				else if (!isdigit(ls.current)) return '.';
-				else {
-				  ReadNumeral(ls, seminfo);
-				  return (int)RESERVED.TK_NUMBER;
-				}
-			  }
-			  case EOZ: {
-				  return (int)RESERVED.TK_EOS;
-			  }
-			  default: {
-				if (isspace(ls.current)) {
-				  LuaAssert(!CurrIsNewline(ls));
-				  Next(ls);
-				  continue;
-				}
-				else if (isdigit(ls.current)) {
-				  ReadNumeral(ls, seminfo);
-				  return (int)RESERVED.TK_NUMBER;
-				}
-				else if (isalpha(ls.current) || ls.current == '_') {
-				  /* identifier or reserved word */
-				  TString ts;
-				  do {
-					SaveAndNext(ls);
-				  } while (isalnum(ls.current) || ls.current == '_');
-				  ts = LuaXNewString(ls, luaZ_buffer(ls.buff),
-										  luaZ_bufflen(ls.buff));
-				  if (ts.tsv.reserved > 0)  /* reserved word? */
-					return ts.tsv.reserved - 1 + FIRSTRESERVED;
-				  else {
-					seminfo.ts = ts;
-					return (int)RESERVED.TK_NAME;
-				  }
-				}
-				else {
-				  int c = ls.current;
-				  Next(ls);
-				  return c;  /* single-char tokens (+ - / ...) */
-				}
-			  }
-			}
-		  }
-		}
-
-
-		public static void LuaXNext (LexState ls) {
-		  ls.lastline = ls.linenumber;
-		  if (ls.lookahead.token != (int)RESERVED.TK_EOS)
-		  {  /* is there a look-ahead token? */
-			ls.t = new Token(ls.lookahead);  /* use this one */
-			ls.lookahead.token = (int)RESERVED.TK_EOS;  /* and discharge it */
-		  }
-		  else
-			ls.t.token = LLex(ls, ls.t.seminfo);  /* read next token */
-		}
-
-
-		public static void LuaXLookAhead (LexState ls) {
-			LuaAssert(ls.lookahead.token == (int)RESERVED.TK_EOS);
-		  ls.lookahead.token = LLex(ls, ls.lookahead.seminfo);
-		}
-
-	}
-}
-
-#endif

+ 435 - 0
src/MoonSharp.Interpreter/Tree/Lexer/Lexer.cs

@@ -0,0 +1,435 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MoonSharp.Interpreter.Tree
+{
+	class Lexer
+	{
+		Token m_Current = null;
+
+		string m_Code;
+		int m_Cursor = 0;
+		int m_Line = 0;
+		int m_Col = 0;
+
+		public Lexer(string scriptContent)
+		{
+			m_Code = scriptContent; // have a sentinel
+		}
+
+
+		public Token PeekToken()
+		{
+			if (m_Current == null)
+				m_Current = ReadToken();
+
+			return m_Current;
+		}
+
+		public Token Next()
+		{
+			if (m_Current != null)
+			{
+				Token t = m_Current;
+				m_Current = null;
+				return t;
+			}
+			else
+				return ReadToken();
+		}
+
+		private void CursorNext()
+		{
+			if (CursorNotEof())
+			{
+				if (CursorChar() == '\n')
+				{
+					m_Col = 0;
+					m_Line += 1;
+				}
+				else
+				{
+					m_Col += 1;
+				}
+
+				m_Cursor += 1;
+			}
+		}
+
+		private char CursorChar()
+		{
+			return m_Code[m_Cursor];
+		}
+
+		private char CursorCharNext()
+		{
+			m_Cursor += 1;
+
+			if (m_Cursor < m_Code.Length - 1)
+				return m_Code[m_Cursor];
+			else
+				return '\0'; // fictitious sentinel
+		}
+
+		private bool CursorMatches(string pattern)
+		{
+			for (int i = 0; i < pattern.Length; i++)
+			{
+				int j = m_Cursor + i;
+
+				if (j >= m_Code.Length)
+					return false;
+				if (m_Code[j] != pattern[i])
+					return false;
+			}
+			return true;
+		}
+
+		private bool CursorNotEof()
+		{
+			return m_Cursor < m_Code.Length;
+		}
+
+		private bool IsWhiteSpace(char c)
+		{
+			return char.IsWhiteSpace(c) || (c == ';');
+		}
+
+		private void SkipWhiteSpace()
+		{
+			for (; CursorNotEof() && IsWhiteSpace(CursorChar()); CursorNext())
+			{
+			}
+		}
+
+
+		private Token ReadToken()
+		{
+			SkipWhiteSpace();
+
+			int fromLine = m_Line;
+			int fromCol = m_Col;
+
+			if (!CursorNotEof())
+				return new Token(TokenType.Eof);
+
+			char c = CursorChar();
+
+			switch (c)
+			{
+				case '=':
+					return PotentiallyDoubleCharOperator('=', TokenType.Op_Assignment, TokenType.Op_Equal, fromLine, fromCol);
+				case '<':
+					return PotentiallyDoubleCharOperator('=', TokenType.Op_LessThan, TokenType.Op_LessThanEqual, fromLine, fromCol);
+				case '>':
+					return PotentiallyDoubleCharOperator('=', TokenType.Op_GreaterThan, TokenType.Op_GreaterThanEqual, fromLine, fromCol);
+				case '~':
+				case '!':
+					if (CursorCharNext() != '=')
+						throw new SyntaxErrorException("Expected '=', {0} was found", CursorChar());
+					CursorCharNext();
+					return CreateToken(TokenType.Op_NotEqual, fromLine, fromCol, "~=");
+				case '.':
+					if (CursorCharNext() == '.')
+						return PotentiallyDoubleCharOperator('.', TokenType.Op_Concat, TokenType.VarArgs, fromLine, fromCol);
+					else
+						return CreateToken(TokenType.Dot, fromLine, fromCol, ".");
+				case '+':
+					return CreateSingleCharToken(TokenType.Op_Add, fromLine, fromCol);
+				case '-':
+					{
+						char next = CursorCharNext();
+						if (next == '-')
+						{
+							return ReadComment(fromLine, fromCol);
+						}
+						else
+						{
+							return CreateToken(TokenType.Op_MinusOrSub, fromLine, fromCol, "-");
+						}
+					}
+				case '*':
+					return CreateSingleCharToken(TokenType.Op_Mul, fromLine, fromCol);
+				case '/':
+					return CreateSingleCharToken(TokenType.Op_Div, fromLine, fromCol);
+				case '%':
+					return CreateSingleCharToken(TokenType.Op_Mod, fromLine, fromCol);
+				case '^':
+					return CreateSingleCharToken(TokenType.Op_Pwr, fromLine, fromCol);
+				case '#':
+					return CreateSingleCharToken(TokenType.Op_Len, fromLine, fromCol);
+				case '[':
+					{
+						char next = CursorCharNext();
+						if (next == '=' || next == '[')
+						{
+							string str = ReadLongString();
+							return CreateToken(TokenType.LongString, fromLine, fromCol, str);
+						}
+						return CreateToken(TokenType.Brk_Open_Square, fromLine, fromCol, "[");
+					}
+				case ']':
+					return CreateSingleCharToken(TokenType.Brk_Close_Square, fromLine, fromCol);
+				case '(':
+					return CreateSingleCharToken(TokenType.Brk_Open_Round, fromLine, fromCol);
+				case ')':
+					return CreateSingleCharToken(TokenType.Brk_Close_Round, fromLine, fromCol);
+				case '{':
+					return CreateSingleCharToken(TokenType.Brk_Open_Curly, fromLine, fromCol);
+				case '}':
+					return CreateSingleCharToken(TokenType.Brk_Close_Curly, fromLine, fromCol);
+				case ',':
+					return CreateSingleCharToken(TokenType.Comma, fromLine, fromCol);
+				case ':':
+					return PotentiallyDoubleCharOperator(':', TokenType.Colon, TokenType.DoubleColon, fromLine, fromCol);
+				case '"':
+				case '\'':
+					return ReadSimpleStringToken(fromLine, fromCol);
+				default:
+					{
+						if (char.IsLetter(c) || c == '_')
+						{
+							string name = ReadNameToken();
+							return CreateNameToken(name, fromLine, fromCol);
+						}
+						else if (char.IsDigit(c))
+						{
+							string number = ReadNumberToken();
+							return CreateToken(TokenType.Number, fromLine, fromCol, number);
+						}
+					}
+					throw new SyntaxErrorException("Fallback to default ?!", CursorChar());
+			}
+
+
+
+		}
+
+		private string ReadLongString()
+		{
+			// here we are at the first '=' or second '['
+			StringBuilder text = new StringBuilder(1024);
+			string end_pattern = "]";
+	
+			for (char c = CursorChar(); ; c = CursorCharNext())
+			{
+				if (c == '\0' || !CursorNotEof())
+				{
+					throw new SyntaxErrorException("Unterminated long string or comment"); 
+				}
+				else if (c == '=')
+				{
+					end_pattern += "=";
+				}
+				else if (c == '[')
+				{
+					end_pattern += "]";
+					break;
+				}
+				else
+				{
+					throw new SyntaxErrorException("Unexpected token in long string prefix: {0}", c);
+				}
+			}
+
+
+			for (char c = CursorChar(); ; c = CursorCharNext())
+			{
+				if (c == '\0' || !CursorNotEof())
+				{
+					throw new SyntaxErrorException("Unterminated long string or comment");
+				}
+				else if (c == ']' && CursorMatches(end_pattern))
+				{
+					for (int i = 0; i < end_pattern.Length; i++)
+						CursorCharNext();
+
+					return text.ToString();
+				}
+				else
+				{
+					text.Append(c);
+				}
+			}
+		}
+
+		private string ReadNumberToken()
+		{
+			StringBuilder text = new StringBuilder(32);
+
+			//INT : Digit+
+			//HEX : '0' [xX] HexDigit+
+			//FLOAT : Digit+ '.' Digit* ExponentPart?
+			//		| '.' Digit+ ExponentPart?
+			//		| Digit+ ExponentPart
+			//HEX_FLOAT : '0' [xX] HexDigit+ '.' HexDigit* HexExponentPart?
+			//			| '0' [xX] '.' HexDigit+ HexExponentPart?
+			//			| '0' [xX] HexDigit+ HexExponentPart
+			//
+			// ExponentPart : [eE] [+-]? Digit+
+			// HexExponentPart : [pP] [+-]? Digit+
+
+			bool isHex = false;
+			bool dotAdded = false;
+			bool exponentPart = false;
+
+			text.Append(CursorChar());
+
+			char secondChar = CursorCharNext();
+
+			if (secondChar == 'x' || secondChar == 'X')
+			{
+				isHex = true;
+				text.Append(CursorChar());
+				CursorCharNext();
+			}
+
+			for (char c = CursorChar(); CursorNotEof(); c = CursorCharNext())
+			{
+				if (char.IsDigit(c))
+				{
+					text.Append(c);
+				}
+				else if (c == '.' && !dotAdded)
+				{
+					dotAdded = true;
+					text.Append(c);
+				}
+				else if (Char_IsHexDigit(c) && isHex && !exponentPart)
+				{
+					text.Append(c);
+				}
+				else if (c == 'e' || c == 'E' || (isHex && (c == 'p' || c == 'P')))
+				{
+					text.Append(c);
+					exponentPart = true;
+					dotAdded = true;
+				}
+				else
+				{
+					return text.ToString();
+				}
+			}
+
+			return text.ToString();
+		}
+
+		private bool Char_IsHexDigit(char c)
+		{
+			return char.IsDigit(c) ||
+				c == 'a' || c == 'b' || c == 'c' || c == 'd' || c == 'e' || c == 'f' ||
+				c == 'A' || c == 'B' || c == 'C' || c == 'D' || c == 'E' || c == 'F';
+		}
+
+		private Token CreateSingleCharToken(TokenType tokenType, int fromLine, int fromCol)
+		{
+			char c = CursorChar();
+			CursorCharNext();
+			return CreateToken(tokenType, fromLine, fromCol, c.ToString());
+		}
+
+		private Token ReadComment(int fromLine, int fromCol)
+		{
+			StringBuilder text = new StringBuilder(32);
+
+			char next1 = CursorCharNext();
+
+			// +++ Long comments
+
+			for (char c = CursorChar(); CursorNotEof(); c = CursorCharNext())
+			{
+				if (c == '\n')
+				{
+					CursorCharNext();
+					return CreateToken(TokenType.Comment, fromLine, fromCol, text.ToString());
+				}
+				else if (c != '\r')
+				{
+					text.Append(c);
+				}
+			}
+
+			return CreateToken(TokenType.Comment, fromLine, fromCol, text.ToString());
+		}
+
+		private Token ReadSimpleStringToken(int fromLine, int fromCol)
+		{
+			StringBuilder text = new StringBuilder(32);
+			char separator = CursorChar();
+
+			for (char c = CursorCharNext(); CursorNotEof(); c = CursorCharNext())
+			{
+				if (c == '\\')
+				{
+					text.Append(c);
+					text.Append(CursorCharNext());
+				}
+				else if (c == separator)
+				{
+					CursorCharNext();
+					return CreateToken(TokenType.SimpleString, fromLine, fromCol, text.ToString());
+				}
+				else
+				{
+					text.Append(c);
+				}
+			}
+
+			throw new SyntaxErrorException("Unterminated string");
+		}
+
+		private Token PotentiallyDoubleCharOperator(char expectedSecondChar, TokenType singleCharToken, TokenType doubleCharToken, int fromLine, int fromCol)
+		{
+			string op = CursorChar().ToString() + CursorCharNext().ToString();
+
+			return CreateToken(CursorChar() == expectedSecondChar ? doubleCharToken : singleCharToken,
+				fromLine, fromCol, op);
+		}
+
+
+
+		private Token CreateNameToken(string name, int fromLine, int fromCol)
+		{
+			TokenType? reservedType = Token.GetReservedTokenType(name);
+
+			if (reservedType.HasValue)
+			{
+				return CreateToken(reservedType.Value, fromLine, fromCol, name);
+			}
+			else
+			{
+				return CreateToken(TokenType.Name, fromLine, fromCol, name);
+			}
+		}
+
+
+		private Token CreateToken(TokenType tokenType, int fromLine, int fromCol, string text = null)
+		{
+			return new Token(tokenType, fromLine, fromCol, m_Line, m_Col)
+			{
+				Text = text
+			};
+		}
+
+		private string ReadNameToken()
+		{
+			StringBuilder name = new StringBuilder(32);
+
+			for (char c = CursorChar(); CursorNotEof(); c = CursorCharNext())
+			{
+				if (char.IsLetterOrDigit(c) || c == '_')
+					name.Append(c);
+				else
+					break;
+			}
+
+			return name.ToString();
+		}
+
+
+
+
+	}
+}

+ 39 - 0
src/MoonSharp.Interpreter/Tree/Lexer/LexerBackDoor.cs

@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace MoonSharp.Interpreter.Tree
+{
+	public class LexerBackDoor
+	{
+		public void Test()
+		{
+			string code = File.ReadAllText(@"c:\temp\test.lua");
+			List<string> output = new List<string>();
+
+			Lexer lexer = new Lexer(code);
+
+			try
+			{
+				while (true)
+				{
+					Token tkn = lexer.Next();
+					output.Add(tkn.ToString());
+					if (tkn.Type == TokenType.Eof)
+						break;
+				}
+			}
+			catch (Exception ex)
+			{
+				output.Add(ex.Message);
+			}
+
+			File.WriteAllLines(@"c:\temp\test.lex", output.ToArray());
+		}
+
+
+
+	}
+}

+ 113 - 0
src/MoonSharp.Interpreter/Tree/Lexer/Token.cs

@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MoonSharp.Interpreter.Tree
+{
+	class Token
+	{
+		public readonly int FromCol, ToCol, FromLine, ToLine;
+		public readonly TokenType Type;
+
+		public string Text { get; set; }
+
+		public Token(TokenType type, int fromLine, int fromCol, int toLine, int toCol)
+		{
+			Type = type;
+
+			FromLine = fromLine;
+			FromCol = fromCol;
+			ToCol = toCol;
+			ToLine = toLine;
+		}
+
+		public Token(TokenType type, int line, int col)
+			: this(type, line, col, line, col)
+		{ }
+
+		public Token(TokenType type)
+			: this(type, -1, -1, -1, -1)
+		{ }
+
+		public override string ToString()
+		{
+			string tokenTypeString = (Type.ToString() + "                                                      ").Substring(0, 16);
+			return string.Format("{0}  -  {1}", tokenTypeString, this.Text ?? "");
+		}
+
+
+
+		public static TokenType? GetReservedTokenType(string reservedWord)
+		{
+			switch (reservedWord)
+			{
+				case "and":
+					return TokenType.And;
+				case "break":
+					return TokenType.Break;
+				case "do":
+					return TokenType.Do;
+				case "else":
+					return TokenType.Else;
+				case "elseif":
+					return TokenType.ElseIf;
+				case "end":
+					return TokenType.End;
+				case "false":
+					return TokenType.False;
+				case "for":
+					return TokenType.For;
+				case "function":
+					return TokenType.Function;
+				case "goto":
+					return TokenType.Goto;
+				case "if":
+					return TokenType.If;
+				case "in":
+					return TokenType.In;
+				case "local":
+					return TokenType.Local;
+				case "nil":
+					return TokenType.Nil;
+				case "not":
+					return TokenType.Not;
+				case "or":
+					return TokenType.Or;
+				case "repeat":
+					return TokenType.Repeat;
+				case "return":
+					return TokenType.Return;
+				case "then":
+					return TokenType.Then;
+				case "true":
+					return TokenType.True;
+				case "until":
+					return TokenType.Until;
+				case "while":
+					return TokenType.While;
+				default:
+					return null;
+			}
+		}
+
+
+
+
+		public bool IsEndOfBlock()
+		{
+			switch (Type)
+			{
+				case TokenType.Else:
+				case TokenType.ElseIf:
+				case TokenType.End:
+				case TokenType.Until:
+				case TokenType.Eof:
+					return true;
+				default:
+					return false;
+			}
+		}
+
+	}
+}

+ 68 - 0
src/MoonSharp.Interpreter/Tree/Lexer/TokenType.cs

@@ -0,0 +1,68 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace MoonSharp.Interpreter.Tree
+{
+	enum TokenType
+	{
+		Eof,
+		Name,
+		And,
+		Break,
+		Do,
+		Else,
+		ElseIf,
+		End,
+		False,
+		For,
+		Function,
+		Goto,
+		If,
+		In,
+		Local,
+		Nil,
+		Not,
+		Or,
+		Repeat,
+		Return,
+		Then,
+		True,
+		Until,
+		While,
+		Op_Equal,
+		Op_Assignment,
+		Op_LessThan,
+		Op_LessThanEqual,
+		Op_GreaterThanEqual,
+		Op_GreaterThan,
+		Op_NotEqual,
+		Op_Concat,
+		VarArgs,
+		Dot,
+		Colon,
+		DoubleColon,
+		Comma,
+		Brk_Close_Curly,
+		Brk_Open_Curly,
+		Brk_Close_Round,
+		Brk_Open_Round,
+		Brk_Close_Square,
+		Brk_Open_Square,
+		Op_Len,
+		Op_Pwr,
+		Op_Mod,
+		Op_Div,
+		Op_Mul,
+		Op_MinusOrSub,
+		Op_Add,
+		SimpleString,
+		Comment,
+		Number,
+		LongString,
+	}
+
+
+
+}

+ 37 - 0
src/MoonSharp.Interpreter/Tree/Statement.cs

@@ -19,6 +19,43 @@ namespace MoonSharp.Interpreter.Tree
 			: base(tree, lcontext)
 		{ }
 
+		public Statement(ScriptLoadingContext lcontext)
+			: base(null, lcontext)
+		{ }
+
+
+		protected static Statement CreateStatement(ScriptLoadingContext lcontext, out bool forceLast)
+		{
+			Token tkn = lcontext.Lexer.PeekToken();
+
+			forceLast = false;
+
+			switch (tkn.Type)
+			{
+				case TokenType.If:
+					throw new NotImplementedException();
+				case TokenType.While:
+					throw new NotImplementedException();
+				case TokenType.Do:
+					throw new NotImplementedException();
+				case TokenType.For:
+					throw new NotImplementedException();
+				case TokenType.Repeat:
+					throw new NotImplementedException();
+				case TokenType.Function:
+					throw new NotImplementedException();
+				case TokenType.Local:
+					throw new NotImplementedException();
+				case TokenType.Return:
+					forceLast = true;
+					throw new NotImplementedException();
+				case TokenType.Break:
+					forceLast = true;
+					throw new NotImplementedException();
+				default:
+					throw new NotImplementedException();
+			}
+		}
 	}
 
 

+ 15 - 0
src/MoonSharp.Interpreter/Tree/Statements/ChunkStatement.cs

@@ -21,6 +21,21 @@ namespace MoonSharp.Interpreter.Tree.Statements
 		SymbolRef m_Env;
 		SymbolRef m_VarArgs;
 
+		public ChunkStatement(Lexer lexer, ScriptLoadingContext lcontext, Table globalEnv)
+			: base(lcontext)
+		{
+			//lcontext.Scope.PushFunction(this, true);
+			//m_Env = lcontext.Scope.DefineLocal(WellKnownSymbols.ENV);
+			//m_VarArgs = lcontext.Scope.DefineLocal(WellKnownSymbols.VARARGS);
+
+			//m_GlobalEnv = globalEnv;
+
+			//m_Block = new CompositeStatement(lexer, lcontext);
+
+			//m_StackFrame = lcontext.Scope.PopFunction();
+		}
+
+
 		public ChunkStatement(LuaParser.ChunkContext context, ScriptLoadingContext lcontext, Table globalEnv)
 			: base(context, lcontext)
 		{

+ 20 - 3
src/MoonSharp.Interpreter/Tree/Statements/CompositeStatement.cs

@@ -10,7 +10,7 @@ namespace MoonSharp.Interpreter.Tree.Statements
 {
 	class CompositeStatement : Statement 
 	{
-		Statement[] m_Statements;
+		List<Statement> m_Statements = new List<Statement>();
 
 		public CompositeStatement(LuaParser.StatContext context, ScriptLoadingContext lcontext)
 			: base(context, lcontext)
@@ -20,7 +20,7 @@ namespace MoonSharp.Interpreter.Tree.Statements
 				m_Statements = context.children
 					.Select(t => NodeFactory.CreateStatement(t, lcontext))
 					.Where(s => s != null)
-					.ToArray();
+					.ToList();
 			}
 		}
 
@@ -32,7 +32,24 @@ namespace MoonSharp.Interpreter.Tree.Statements
 				m_Statements = context.children
 					.Select(t => NodeFactory.CreateStatement(t, lcontext))
 					.Where(s => s != null)
-					.ToArray();
+					.ToList();
+			}
+		}
+
+		public CompositeStatement(ScriptLoadingContext lcontext)
+			: base(lcontext)
+		{
+			while (true)
+			{
+				Token t = lcontext.Lexer.PeekToken();
+				if (t.IsEndOfBlock()) break;
+
+				bool forceLast;
+				
+				Statement s = Statement.CreateStatement(lcontext, out forceLast);
+				m_Statements.Add(s);
+
+				if (forceLast) break;
 			}
 		}
 

+ 2 - 0
src/MoonSharp.Interpreter/Tree/Statements/ScopeBlockStatement.cs

@@ -26,6 +26,8 @@ namespace MoonSharp.Interpreter.Tree.Statements
 			m_StackFrame = lcontext.Scope.PopBlock();
 		}
 
+
+
 		public override void Compile(Execution.VM.ByteCode bc)
 		{
 			using(bc.EnterSource(m_Do))

+ 6 - 0
src/Tools/LexerTestBed/App.config

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
+    </startup>
+</configuration>

+ 64 - 0
src/Tools/LexerTestBed/LexerTestBed.csproj

@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{2C77D8EC-0F52-42B2-A408-EFAC85126153}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>LexerTestBed</RootNamespace>
+    <AssemblyName>LexerTestBed</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="App.config" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\MoonSharp.Interpreter\MoonSharp.Interpreter.csproj">
+      <Project>{91ea9b9d-fe03-4273-bdaf-8ad42ede1e59}</Project>
+      <Name>MoonSharp.Interpreter</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 16 - 0
src/Tools/LexerTestBed/Program.cs

@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace LexerTestBed
+{
+	class Program
+	{
+		static void Main(string[] args)
+		{
+			(new MoonSharp.Interpreter.Tree.LexerBackDoor()).Test();
+		}
+	}
+}

+ 36 - 0
src/Tools/LexerTestBed/Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("LexerTestBed")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("LexerTestBed")]
+[assembly: AssemblyCopyright("Copyright ©  2015")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("c21d5fa2-176d-413c-85bc-9e87b502d4bf")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 9 - 0
src/moonsharp.sln

@@ -35,6 +35,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Distribution", "Distributio
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{FA582319-EA17-4C52-870D-C00EF793628F}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LexerTestBed", "Tools\LexerTestBed\LexerTestBed.csproj", "{2C77D8EC-0F52-42B2-A408-EFAC85126153}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -101,6 +103,12 @@ Global
 		{43D3AD52-FED5-4305-B0F4-6B991220CD0A}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{43D3AD52-FED5-4305-B0F4-6B991220CD0A}.Release|Any CPU.Build.0 = Release|Any CPU
 		{43D3AD52-FED5-4305-B0F4-6B991220CD0A}.Release|x86.ActiveCfg = Release|Any CPU
+		{2C77D8EC-0F52-42B2-A408-EFAC85126153}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{2C77D8EC-0F52-42B2-A408-EFAC85126153}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2C77D8EC-0F52-42B2-A408-EFAC85126153}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{2C77D8EC-0F52-42B2-A408-EFAC85126153}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{2C77D8EC-0F52-42B2-A408-EFAC85126153}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2C77D8EC-0F52-42B2-A408-EFAC85126153}.Release|x86.ActiveCfg = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -114,5 +122,6 @@ Global
 		{F4F82CCE-2E13-441B-939C-63CF2343B1C9} = {3C626068-E8CE-4F62-8974-F42A56F4EFD3}
 		{26B3033C-D1E2-4188-870C-D197E95A7F6B} = {59F722D5-6E5C-4544-A849-18E7CE876FDF}
 		{43D3AD52-FED5-4305-B0F4-6B991220CD0A} = {5014C740-F6C7-4995-8D40-C250FB159A20}
+		{2C77D8EC-0F52-42B2-A408-EFAC85126153} = {3C626068-E8CE-4F62-8974-F42A56F4EFD3}
 	EndGlobalSection
 EndGlobal