Пример #1
0
		private ByteBuffer BuildSwitchStatementTables(Parser parser)
		{
			ByteBuffer output = new Crayon.ByteBuffer();
			List<Dictionary<int, int>> intSwitches = parser.GetIntegerSwitchStatements();
			for (int i = 0; i < intSwitches.Count; ++i)
			{
				List<int> args = new List<int>();
				Dictionary<int, int> lookup = intSwitches[i];
				foreach (int key in lookup.Keys) {
					int offset = lookup[key];
					args.Add(key);
					args.Add(offset);
				}

				output.Add(null, OpCode.BUILD_SWITCH_INT, args.ToArray());
			}

			List<Dictionary<string, int>> stringSwitches = parser.GetStringSwitchStatements();
			for (int i = 0; i < stringSwitches.Count; ++i)
			{
				Dictionary<string, int> lookup = stringSwitches[i];
				foreach (string key in lookup.Keys)
				{
					int offset = lookup[key];
					output.Add(null, OpCode.BUILD_SWITCH_STRING, key, i, offset);
				}
			}
			return output;
		}
Пример #2
0
		public ByteBuffer GenerateByteCode(Parser parser, IList<Executable> lines, IList<string> spriteSheetOpsStringArgs, IList<int[]> spriteSheetOpsIntArgs)
		{
			FunctionDefinition mainFunction = lines
				.OfType<FunctionDefinition>()
				.Where<FunctionDefinition>(fd => fd.NameToken.Value == "main")
				.FirstOrDefault<FunctionDefinition>();

			if (mainFunction == null) {
				throw new Exception(); // should have thrown before if there was no main function.
			}

			ByteBuffer userCode = new ByteBuffer();

			this.Compile(parser, userCode, lines);

			ByteBuffer literalsTable = parser.LiteralLookup.BuildByteCode();

			ByteBuffer tokenData = this.BuildTokenData(userCode);

			ByteBuffer fileContent = this.BuildFileContent(parser.GetFilesById());

			ByteBuffer switchStatements = this.BuildSwitchStatementTables(parser);

			ByteBuffer spriteSheetStuff = this.BuildSpriteSheetStuff(spriteSheetOpsStringArgs, spriteSheetOpsIntArgs);

			ByteBuffer header = new Crayon.ByteBuffer();
			header.Concat(literalsTable);
			header.Concat(tokenData);
			header.Concat(fileContent);
			header.Concat(switchStatements);
			header.Concat(spriteSheetStuff);
			header.Add(null, OpCode.FINALIZE_INITIALIZATION);

			ByteBuffer output = new Crayon.ByteBuffer();
			output.Add(null, OpCode.USER_CODE_START, header.Size + 1, parser.VariableIds.Size);
			output.Concat(header);
			output.Concat(userCode);

			// artificially inject a function call to main() at the very end after all declarations are done.
			if (parser.MainFunctionHasArg)
			{
				output.Add(null, OpCode.DEF_LIST, 0); // TODO: op code to build a list of the command line args. For now just pass in an empty list.
				output.Add(null, OpCode.CALL_FUNCTION, (int)FunctionInvocationType.NORMAL_FUNCTION, 1, mainFunction.FunctionID, 0, 0);
			}
			else
			{
				output.Add(null, OpCode.CALL_FUNCTION, (int)FunctionInvocationType.NORMAL_FUNCTION, 0, mainFunction.FunctionID, 0, 0);
			}
			output.Add(null, OpCode.RETURN, 0);

			return output;
		}
Пример #3
0
		private ByteBuffer GenerateByteCode(BuildContext buildContext, string inputFolder, List<string> spriteSheetOpsStringArgs, List<int[]> spriteSheetOpsIntArgs)
		{
			Parser userCodeParser = new Parser(null, buildContext, null);
			ParseTree.Executable[] userCode = userCodeParser.ParseAllTheThings(inputFolder);
			
			foreach (Executable ex in userCode)
			{
				ex.GenerateGlobalNameIdManifest(userCodeParser.VariableIds);
			}

			ByteCodeCompiler bcc = new ByteCodeCompiler();
			ByteBuffer buffer = bcc.GenerateByteCode(userCodeParser, userCode, spriteSheetOpsStringArgs, spriteSheetOpsIntArgs);

			this.LibraryBigSwitchStatement = userCodeParser.SystemLibraryManager.GetLibrarySwitchStatement(this.LanguageId, this.PlatformId);
			this.InterpreterCompiler = new InterpreterCompiler(this, userCodeParser.SystemLibraryManager);
			return buffer;
		}
Пример #4
0
		private static Executable ParseClassDefinition(Parser parser, TokenStream tokens, Executable owner)
		{
			Token classToken = tokens.PopExpected("class");
			Token classNameToken = tokens.Pop();
			Parser.VerifyIdentifier(classNameToken);
			List<Token> baseClassTokens = new List<Token>();
			List<string> baseClassStrings = new List<string>();
			if (tokens.PopIfPresent(":"))
			{
				if (baseClassTokens.Count > 0)
				{
					tokens.PopExpected(",");
				}

				Token baseClassToken = tokens.Pop();
				string baseClassName = baseClassToken.Value;

				Parser.VerifyIdentifier(baseClassToken);
				while (tokens.PopIfPresent("."))
				{
					Token baseClassTokenNext = tokens.Pop();
					Parser.VerifyIdentifier(baseClassTokenNext);
					baseClassName += "." + baseClassTokenNext.Value;
				}

				baseClassTokens.Add(baseClassToken);
				baseClassStrings.Add(baseClassName);
			}

			ClassDefinition cd = new ClassDefinition(
				classToken,
				classNameToken,
				baseClassTokens,
				baseClassStrings,
				parser.CurrentNamespace,
				owner);

			tokens.PopExpected("{");
			List<FunctionDefinition> methods = new List<FunctionDefinition>();
			List<FieldDeclaration> fields = new List<FieldDeclaration>();
			ConstructorDefinition constructorDef = null;
			ConstructorDefinition staticConstructorDef = null;

			while (!tokens.PopIfPresent("}"))
			{
				if (tokens.IsNext("function") || tokens.AreNext("static", "function"))
				{
					methods.Add((FunctionDefinition)ExecutableParser.ParseFunction(parser, tokens, cd));
				}
				else if (tokens.IsNext("constructor"))
				{
					if (constructorDef != null)
					{
						throw new ParserException(tokens.Pop(), "Multiple constructors are not allowed. Use optional arguments.");
					}

					constructorDef = (ConstructorDefinition)ExecutableParser.ParseConstructor(parser, tokens, cd);
				}
				else if (tokens.AreNext("static", "constructor"))
				{
					tokens.Pop(); // static token
					if (staticConstructorDef != null)
					{
						throw new ParserException(tokens.Pop(), "Multiple static constructors are not allowed.");
					}

					staticConstructorDef = (ConstructorDefinition)ExecutableParser.ParseConstructor(parser, tokens, cd);
				}
				else if (tokens.IsNext("field") || tokens.AreNext("static", "field"))
				{
					fields.Add(ExecutableParser.ParseField(tokens, cd));
				}
				else
				{
					tokens.PopExpected("}");
				}
			}

			cd.Methods = methods.ToArray();
			cd.Constructor = constructorDef;
			cd.StaticConstructor = staticConstructorDef;
			cd.Fields = fields.ToArray();

			return cd;
		}
Пример #5
0
		private static Executable ParseNamespace(Parser parser, TokenStream tokens, Executable owner)
		{
			Token namespaceToken = tokens.PopExpected("namespace");
			Token first = tokens.Pop();
			Parser.VerifyIdentifier(first);
			List<Token> namespacePieces = new List<Token>() { first };
			while (tokens.PopIfPresent("."))
			{
				Token nsToken = tokens.Pop();
				Parser.VerifyIdentifier(nsToken);
				namespacePieces.Add(nsToken);
			}

			string name = string.Join(".", namespacePieces.Select<Token, string>(t => t.Value));
			parser.PushNamespacePrefix(name);

			Namespace namespaceInstance = new Namespace(namespaceToken, name, owner);

			tokens.PopExpected("{");
			List<Executable> namespaceMembers = new List<Executable>();
			while (!tokens.PopIfPresent("}"))
			{
				Executable executable = ExecutableParser.Parse(parser, tokens, false, false, true, namespaceInstance);
				if (executable is FunctionDefinition ||
					executable is ClassDefinition ||
					executable is Namespace)
				{
					namespaceMembers.Add(executable);
				}
				else
				{
					throw new ParserException(executable.FirstToken, "Only function, class, and nested namespace declarations may exist as direct members of a namespace.");
				}
			}

			namespaceInstance.Code = namespaceMembers.ToArray();

			parser.PopNamespacePrefix();

			return namespaceInstance;
		}
Пример #6
0
		// Convert anything that looks like a function call into a verified pointer to the function if possible using the
		// available namespaces.
		public static List<Executable> CreateVerifiedFunctionCalls(Parser parser, IList<Executable> original)
		{
			// All code that doesn't have a function or class surrounding it.
			List<Executable> looseCode = new List<Executable>();

			// First create a fully-qualified lookup of all functions and classes.
			Dictionary<string, Executable> functionsAndClasses = new Dictionary<string, Executable>();
			foreach (Executable exec in original)
			{
				if (exec is FunctionDefinition)
				{
					FunctionDefinition fd = (FunctionDefinition)exec;
					string key = fd.Namespace + ":" + fd.NameToken.Value;
					functionsAndClasses[key] = fd;
				}
				else if (exec is ClassDefinition)
				{
					ClassDefinition cd = (ClassDefinition)exec;
					string key = cd.Namespace + ":" + cd.NameToken.Value;
					functionsAndClasses[key] = cd;
				}
			}

			List<Executable> output = new List<Executable>();

			return output;
		}
Пример #7
0
		private void CompileBooleanCombination(Parser parser, ByteBuffer buffer, BooleanCombination boolComb, bool outputUsed)
		{
			if (!outputUsed) throw new ParserException(boolComb.FirstToken, "Cannot have this expression here.");

			ByteBuffer rightBuffer = new ByteBuffer();
			Expression[] expressions = boolComb.Expressions;
			this.CompileExpression(parser, rightBuffer, expressions[expressions.Length - 1], true);
			for (int i = expressions.Length - 2; i >= 0; --i)
			{
				ByteBuffer leftBuffer = new ByteBuffer();
				this.CompileExpression(parser, leftBuffer, expressions[i], true);
				Token op = boolComb.Ops[i];
				if (op.Value == "&&")
				{
					leftBuffer.Add(op, OpCode.JUMP_IF_FALSE_NO_POP, rightBuffer.Size);
				}
				else
				{
					leftBuffer.Add(op, OpCode.JUMP_IF_TRUE_NO_POP, rightBuffer.Size);
				}
				leftBuffer.Concat(rightBuffer);
				rightBuffer = leftBuffer;
			}

			buffer.Concat(rightBuffer);
		}
Пример #8
0
		private static Executable ParseSwitch(Parser parser, TokenStream tokens, Executable owner)
		{
			Token switchToken = tokens.PopExpected("switch");

			Expression explicitMax = null;
			Token explicitMaxToken = null;
			if (tokens.IsNext("{"))
			{
				explicitMaxToken = tokens.Pop();
				explicitMax = ExpressionParser.Parse(tokens, owner);
				tokens.PopExpected("}");
			}

			tokens.PopExpected("(");
			Expression condition = ExpressionParser.Parse(tokens, owner);
			tokens.PopExpected(")");
			tokens.PopExpected("{");
			List<List<Expression>> cases = new List<List<Expression>>();
			List<Token> firstTokens = new List<Token>();
			List<List<Executable>> code = new List<List<Executable>>();
			char state = '?'; // ? - first, O - code, A - case
			bool defaultEncountered = false;
			while (!tokens.PopIfPresent("}"))
			{
				if (tokens.IsNext("case"))
				{
					if (defaultEncountered)
					{
						throw new ParserException(tokens.Peek(), "default condition in a switch statement must be the last condition.");
					}

					Token caseToken = tokens.PopExpected("case");
					if (state != 'A')
					{
						cases.Add(new List<Expression>());
						firstTokens.Add(caseToken);
						code.Add(null);
						state = 'A';
					}
					cases[cases.Count - 1].Add(ExpressionParser.Parse(tokens, owner));
					tokens.PopExpected(":");
				}
				else if (tokens.IsNext("default"))
				{
					Token defaultToken = tokens.PopExpected("default");
					if (state != 'A')
					{
						cases.Add(new List<Expression>());
						firstTokens.Add(defaultToken);
						code.Add(null);
						state = 'A';
					}
					cases[cases.Count - 1].Add(null);
					tokens.PopExpected(":");
					defaultEncountered = true;
				}
				else
				{
					if (state != 'O')
					{
						cases.Add(null);
						firstTokens.Add(null);
						code.Add(new List<Executable>());
						state = 'O';
					}
					code[code.Count - 1].Add(ExecutableParser.Parse(parser, tokens, false, true, false, owner));
				}
			}

			return new SwitchStatement(switchToken, condition, firstTokens, cases, code, explicitMax, explicitMaxToken, owner);
		}
Пример #9
0
		private static Executable ParseTry(Parser parser, TokenStream tokens, Executable owner)
		{
			Token tryToken = tokens.PopExpected("try");
			throw new NotImplementedException();
		}
Пример #10
0
		private void CompileIncrement(Parser parser, ByteBuffer buffer, Increment increment, bool outputUsed)
		{
			if (!outputUsed)
			{
				throw new Exception("This should have been optimized into a += or -=");
			}

			if (increment.Root is Variable)
			{
				// OpCode re-use be damned. This should be not one, but two top-level op codes.
				// INCREMENT_INLINE and INCREMENT_POP (depending on whether outputUsed is true)
				// In fact, the code here in its current form is actually WRONG because someString++ will have 
				// a '1' appended to it when it really should be an error if the variable is not an integer.
				// Same for the others below. Ideally the DUPLICATE_STACK_TOP op should be removed.
				Variable variable = (Variable)increment.Root;
				int scopeId = variable.LocalScopeId;
				this.CompileExpression(parser, buffer, increment.Root, true);
				if (increment.IsPrefix)
				{
					buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
					buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION);
					buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1);
					buffer.Add(variable.FirstToken, OpCode.ASSIGN_LOCAL, scopeId);
				}
				else
				{
					buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1);
					buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
					buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION);
					buffer.Add(variable.FirstToken, OpCode.ASSIGN_LOCAL, scopeId);
				}
			}
			else if (increment.Root is BracketIndex)
			{
				BracketIndex bracketIndex = (BracketIndex)increment.Root;
				this.CompileExpression(parser, buffer, bracketIndex.Root, true);
				this.CompileExpression(parser, buffer, bracketIndex.Index, true);
				buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 2);
				buffer.Add(bracketIndex.BracketToken, OpCode.INDEX);
				if (increment.IsPrefix)
				{
					buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
					buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION);
					buffer.Add(increment.IncrementToken, OpCode.ASSIGN_INDEX, 1);
				}
				else
				{
					buffer.Add(increment.IncrementToken, OpCode.STACK_INSERTION_FOR_INCREMENT);
					buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
					buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION);
					buffer.Add(increment.IncrementToken, OpCode.ASSIGN_INDEX, 0);
				}
			}
			else if (increment.Root is DotStep)
			{
				DotStep dotStep = (DotStep)increment.Root;
				this.CompileExpression(parser, buffer, dotStep.Root, true);
				buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 1);
				buffer.Add(dotStep.DotToken, OpCode.DEREF_DOT, parser.GetId(dotStep.StepToken.Value));
				if (increment.IsPrefix)
				{
					buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
					buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION);
					buffer.Add(increment.IncrementToken, OpCode.ASSIGN_STEP, parser.GetId(dotStep.StepToken.Value), 1);
				}
				else
				{
					buffer.Add(increment.IncrementToken, OpCode.DUPLICATE_STACK_TOP, 2);
					buffer.Add(increment.IncrementToken, OpCode.LITERAL, parser.GetIntConstant(1));
					buffer.Add(increment.IncrementToken, OpCode.BINARY_OP, increment.IsIncrement ? (int)BinaryOps.ADDITION : (int)BinaryOps.SUBTRACTION);
					buffer.Add(increment.IncrementToken, OpCode.ASSIGN_STEP, parser.GetId(dotStep.StepToken.Value), 0);
					buffer.Add(increment.IncrementToken, OpCode.STACK_SWAP_POP);
				}
			}
			else
			{
				throw new ParserException(increment.IncrementToken, "Cannot apply " + (increment.IsIncrement ? "++" : "--") + " to this sort of expression.");
			}
		}
Пример #11
0
		private static Executable ParseWhile(Parser parser, TokenStream tokens, Executable owner)
		{
			Token whileToken = tokens.PopExpected("while");
			tokens.PopExpected("(");
			Expression condition = ExpressionParser.Parse(tokens, owner);
			tokens.PopExpected(")");
			IList<Executable> body = Parser.ParseBlock(parser, tokens, false, owner);
			return new WhileLoop(whileToken, condition, body, owner);
		}
Пример #12
0
		private void CompileNullConstant(Parser parser, ByteBuffer buffer, NullConstant nullConstant, bool outputUsed)
		{
			if (!outputUsed) throw new ParserException(nullConstant.FirstToken, "This expression doesn't do anything.");

			buffer.Add(nullConstant.FirstToken, OpCode.LITERAL, parser.GetNullConstant());
		}
Пример #13
0
		private void CompileFloatConstant(Parser parser, ByteBuffer buffer, FloatConstant floatConstant, bool outputUsed)
		{
			if (!outputUsed) throw new ParserException(floatConstant.FirstToken, "This expression doesn't do anything.");
			buffer.Add(floatConstant.FirstToken, OpCode.LITERAL, parser.GetFloatConstant(floatConstant.Value));
		}
Пример #14
0
		private void CompileThisKeyword(Parser parser, ByteBuffer buffer, ThisKeyword thisKeyword, bool outputUsed)
		{
			if (!outputUsed) throw new ParserException(thisKeyword.FirstToken, "This expression doesn't do anything.");

			buffer.Add(thisKeyword.FirstToken, OpCode.THIS);
		}
Пример #15
0
		private void CompileInstantiate(Parser parser, ByteBuffer buffer, Instantiate instantiate, bool outputUsed)
		{
			ClassDefinition cd = (ClassDefinition)instantiate.Class;
			ConstructorDefinition constructor = cd.Constructor;

			this.CompileExpressionList(parser, buffer, instantiate.Args, true);
			buffer.Add(instantiate.NameToken,
				OpCode.CALL_FUNCTION,
				(int)FunctionInvocationType.CONSTRUCTOR,
				instantiate.Args.Length,
				constructor.FunctionID,
				outputUsed ? 1 : 0,
				cd.ClassID);
		}
Пример #16
0
		private void CompileDictionaryDefinition(Parser parser, ByteBuffer buffer, DictionaryDefinition dictDef, bool outputUsed)
		{
			if (!outputUsed) throw new ParserException(dictDef.FirstToken, "Cannot have a dictionary all by itself.");

			int itemCount = dictDef.Keys.Length;
			List<Expression> expressionList = new List<Expression>();
			for (int i = 0; i < itemCount; ++i)
			{
				expressionList.Add(dictDef.Keys[i]);
				expressionList.Add(dictDef.Values[i]);
			}

			this.CompileExpressionList(parser, buffer, expressionList, true);

			buffer.Add(dictDef.FirstToken, OpCode.DEF_DICTIONARY, itemCount);
		}
Пример #17
0
		private static Executable ParseFunction(Parser parser, TokenStream tokens, Executable nullableOwner)
		{
			bool isStatic = 
				nullableOwner != null && 
				nullableOwner is ClassDefinition && 
				tokens.PopIfPresent("static");

			Token functionToken = tokens.PopExpected("function");

			List<Annotation> functionAnnotations = new List<Annotation>();

			while (tokens.IsNext("@"))
			{
				functionAnnotations.Add(AnnotationParser.ParseAnnotation(tokens));
			}

			Token functionNameToken = tokens.Pop();
			Parser.VerifyIdentifier(functionNameToken);

			FunctionDefinition fd = new FunctionDefinition(functionToken, nullableOwner, isStatic, functionNameToken, functionAnnotations, parser.CurrentNamespace);

			tokens.PopExpected("(");
			List<Token> argNames = new List<Token>();
			List<Expression> defaultValues = new List<Expression>();
			List<Annotation> argAnnotations = new List<Annotation>();
			bool optionalArgFound = false;
			while (!tokens.PopIfPresent(")"))
			{
				if (argNames.Count > 0) tokens.PopExpected(",");

				Annotation annotation = tokens.IsNext("@") ? AnnotationParser.ParseAnnotation(tokens) : null;
				Token argName = tokens.Pop();
				Expression defaultValue = null;
				Parser.VerifyIdentifier(argName);
				if (tokens.PopIfPresent("="))
				{
					optionalArgFound = true;
					defaultValue = ExpressionParser.Parse(tokens, fd);
				}
				else if (optionalArgFound)
				{
					throw new ParserException(argName, "All optional arguments must come at the end of the argument list.");
				}
				argAnnotations.Add(annotation);
				argNames.Add(argName);
				defaultValues.Add(defaultValue);
			}

			IList<Executable> code = Parser.ParseBlock(parser, tokens, true, fd);

			fd.ArgNames = argNames.ToArray();
			fd.DefaultValues = defaultValues.ToArray();
			fd.ArgAnnotations = argAnnotations.ToArray();
			fd.Code = code.ToArray();

			return fd;
		}
Пример #18
0
		public Executable[] ImportLibrary(Parser parser, Token throwToken, string name)
		{
			name = name.Split('.')[0];
			if (alreadyImported.Contains(name))
			{
				return EMPTY_EXECUTABLE;
			}

			alreadyImported.Add(name);

			string dllPath = this.GetSystemLibraryPath(name);

			if (dllPath == null)
			{
				return EMPTY_EXECUTABLE;
			}

			System.Reflection.Assembly assembly = null;
			try
			{
				assembly = System.Reflection.Assembly.LoadFrom(dllPath);
			}
			catch (Exception)
			{
				throw new ParserException(throwToken, "Could not import library: " + name);
			}

			ILibraryConfig libraryConfig = assembly.CreateInstance(name + ".LibraryConfig") as ILibraryConfig;
			if (libraryConfig == null)
			{
				throw new ParserException(throwToken, "Error creating LibraryConfig instance in Library '" + name + "'");
			}

			this.importedLibraries[name] = libraryConfig;
			this.librariesByKey[name.ToLowerInvariant()] = libraryConfig;

			string oldSystemLibrary = parser.CurrentSystemLibrary;
			parser.CurrentSystemLibrary = name;

			string libraryCode = libraryConfig.GetEmbeddedCode();
			Executable[] libraryParseTree = parser.ParseInterpretedCode("[" + name + "]", libraryCode, name);

			parser.CurrentSystemLibrary = oldSystemLibrary;
			return libraryParseTree;
		}
Пример #19
0
		private static Executable ParseFor(Parser parser, TokenStream tokens, Executable owner)
		{
			Token forToken = tokens.PopExpected("for");
			tokens.PopExpected("(");

			if (Parser.IsValidIdentifier(tokens.PeekValue()) && tokens.PeekValue(1) == ":")
			{
				Token iteratorToken = tokens.Pop();
				if (Parser.IsReservedKeyword(iteratorToken.Value))
				{
					throw new ParserException(iteratorToken, "Cannot use this name for an iterator.");
				}
				tokens.PopExpected(":");
				Expression iterationExpression = ExpressionParser.Parse(tokens, owner);
				tokens.PopExpected(")");
				IList<Executable> body = Parser.ParseBlock(parser, tokens, false, owner);

				return new ForEachLoop(forToken, iteratorToken, iterationExpression, body, owner);
			}
			else
			{
				List<Executable> init = new List<Executable>();
				while (!tokens.PopIfPresent(";"))
				{
					if (init.Count > 0) tokens.PopExpected(",");
					init.Add(Parse(parser, tokens, true, false, false, owner));
				}
				Expression condition = null;
				if (!tokens.PopIfPresent(";"))
				{
					condition = ExpressionParser.Parse(tokens, owner);
					tokens.PopExpected(";");
				}
				List<Executable> step = new List<Executable>();
				while (!tokens.PopIfPresent(")"))
				{
					if (step.Count > 0) tokens.PopExpected(",");
					step.Add(Parse(parser, tokens, true, false, false, owner));
				}

				IList<Executable> body = Parser.ParseBlock(parser, tokens, false, owner);

				return new ForLoop(forToken, init, condition, step, body, owner);
			}
		}
Пример #20
0
		private static Executable ParseConstructor(Parser parser, TokenStream tokens, Executable owner)
		{
			Token constructorToken = tokens.PopExpected("constructor");
			tokens.PopExpected("(");
			List<Token> argNames = new List<Token>();
			List<Expression> argValues = new List<Expression>();
			bool optionalArgFound = false;
			while (!tokens.PopIfPresent(")"))
			{
				if (argNames.Count > 0)
				{
					tokens.PopExpected(",");
				}

				Token argName = tokens.Pop();
				Parser.VerifyIdentifier(argName);
				Expression defaultValue = null;
				if (tokens.PopIfPresent("="))
				{
					defaultValue = ExpressionParser.Parse(tokens, owner);
					optionalArgFound = true;
				}
				else if (optionalArgFound)
				{
					throw new ParserException(argName, "All optional arguments must come at the end of the argument list.");
				}

				argNames.Add(argName);
				argValues.Add(defaultValue);
			}

			List<Expression> baseArgs = new List<Expression>();
			Token baseToken = null;
			if (tokens.PopIfPresent(":"))
			{
				baseToken = tokens.PopExpected("base");
				tokens.PopExpected("(");
				while (!tokens.PopIfPresent(")"))
				{
					if (baseArgs.Count > 0)
					{
						tokens.PopExpected(",");
					}

					baseArgs.Add(ExpressionParser.Parse(tokens, owner));
				}
			}

			IList<Executable> code = Parser.ParseBlock(parser, tokens, true, owner);

			return new ConstructorDefinition(constructorToken, argNames, argValues, baseArgs, code, baseToken, owner);
		}
Пример #21
0
		private static Executable ParseDoWhile(Parser parser, TokenStream tokens, Executable owner)
		{
			Token doToken = tokens.PopExpected("do");
			IList<Executable> body = Parser.ParseBlock(parser, tokens, true, owner);
			tokens.PopExpected("while");
			tokens.PopExpected("(");
			Expression condition = ExpressionParser.Parse(tokens, owner);
			tokens.PopExpected(")");
			tokens.PopExpected(";");
			return new DoWhileLoop(doToken, body, condition, owner);
		}
Пример #22
0
		public static Executable Parse(Parser parser, TokenStream tokens, bool simpleOnly, bool semicolonPresent, bool isRoot, Executable owner)
		{
			string value = tokens.PeekValue();

			if (!simpleOnly)
			{
				if (parser.IsTranslateMode && value == "struct")
				{
					if (!isRoot)
					{
						throw new ParserException(tokens.Peek(), "structs cannot be nested into any other construct.");
					}

					// struct is special. If you are not compiling in JS mode, 
					if (Parser.IsValidIdentifier(tokens.PeekValue(1)) && tokens.PeekValue(2) == "{")
					{
						return ParseStruct(tokens, owner);
					}
				}

				if (!isRoot && (value == "function" || value == "class"))
				{
					throw new ParserException(tokens.Peek(), (value == "function" ? "Function" : "Class") + " definition cannot be nested in another construct.");
				}

				if (value == "import")
				{
					Token importToken = tokens.PopExpected("import");

					bool inline = parser.IsTranslateMode && tokens.PopIfPresent("inline");

					if (inline)
					{
						Token fileToken = tokens.Pop();
						char c = fileToken.Value[0];
						if (c != '\'' && c != '"') throw new ParserException(fileToken, "Inline imports are supposed to be strings.");
						tokens.PopExpected(";");
						string inlineImportFileName = fileToken.Value.Substring(1, fileToken.Value.Length - 2);
						string inlineImportFileContents = Util.ReadFileInternally(inlineImportFileName);
						// TODO: Anti-pattern alert. Clean this up.
						if (inlineImportFileContents.Contains("%%%"))
						{
							Dictionary<string, string> replacements = parser.NullablePlatform.InterpreterCompiler.BuildReplacementsDictionary();
							inlineImportFileContents = Constants.DoReplacements(inlineImportFileContents, replacements);
						}
						TokenStream inlineTokens = Tokenizer.Tokenize(inlineImportFileName, inlineImportFileContents, 0, true);

						// OMGHAX - insert the inline import into the current token stream.
						tokens.InsertTokens(inlineTokens);

						return ExecutableParser.Parse(parser, tokens, simpleOnly, semicolonPresent, isRoot, owner); // start exectuable parser anew.
					}

					if (!isRoot)
					{
						throw new ParserException(tokens.Peek(), "Imports can only be made from the root of a file and cannot be nested inside other constructs.");
					}

					List<string> importPathBuilder = new List<string>();
					while (!tokens.PopIfPresent(";"))
					{
						if (importPathBuilder.Count > 0)
						{
							tokens.PopExpected(".");
						}

						Token pathToken = tokens.Pop();
						Parser.VerifyIdentifier(pathToken);
						importPathBuilder.Add(pathToken.Value);
					}
					string importPath = string.Join(".", importPathBuilder);

					return new ImportStatement(importToken, importPath);
				}

				if (value == "enum")
				{
					if (!isRoot)
					{
						throw new ParserException(tokens.Peek(), "Enums can only be defined from the root of a file and cannot be nested inside functions/loops/etc.");
					}

					return ParseEnumDefinition(parser, tokens, owner);
				}

				if (value == "namespace")
				{
					if (!isRoot)
					{
						throw new ParserException(tokens.Peek(), "Namespace declarations cannot be nested in other constructs.");
					}
				}

				switch (value)
				{
					case "namespace": return ParseNamespace(parser, tokens, owner);
					case "function": return ParseFunction(parser, tokens, owner);
					case "class": return ParseClassDefinition(parser, tokens, owner);
					case "enum": return ParseEnumDefinition(parser, tokens, owner);
					case "for": return ParseFor(parser, tokens, owner);
					case "while": return ParseWhile(parser, tokens, owner);
					case "do": return ParseDoWhile(parser, tokens, owner);
					case "switch": return ParseSwitch(parser, tokens, owner);
					case "if": return ParseIf(parser, tokens, owner);
					case "try": return ParseTry(parser, tokens, owner);
					case "return": return ParseReturn(tokens, owner);
					case "break": return ParseBreak(tokens, owner);
					case "continue": return ParseContinue(tokens, owner);
					case "const": return ParseConst(parser, tokens, owner);
					case "constructor": return ParseConstructor(parser, tokens, owner);
					default: break;
				}
			}

			Expression expr = ExpressionParser.Parse(tokens, owner);
			value = tokens.PeekValue();
			if (ASSIGNMENT_OPS.Contains(value))
			{
				Token assignment = tokens.Pop();
				Expression assignmentValue = ExpressionParser.Parse(tokens, owner);
				if (semicolonPresent) tokens.PopExpected(";");
				return new Assignment(expr, assignment, assignment.Value, assignmentValue, owner);
			}

			if (semicolonPresent)
			{
				tokens.PopExpected(";");
			}

			return new ExpressionAsExecutable(expr, owner);
		}
Пример #23
0
		private static Executable ParseIf(Parser parser, TokenStream tokens, Executable owner)
		{
			Token ifToken = tokens.PopExpected("if");
			tokens.PopExpected("(");
			Expression condition = ExpressionParser.Parse(tokens, owner);
			tokens.PopExpected(")");
			IList<Executable> body = Parser.ParseBlock(parser, tokens, false, owner);
			IList<Executable> elseBody;
			if (tokens.PopIfPresent("else"))
			{
				elseBody = Parser.ParseBlock(parser, tokens, false, owner);
			}
			else
			{
				elseBody = new Executable[0];
			}
			return new IfStatement(ifToken, condition, body, elseBody, owner);
		}
Пример #24
0
		public InterpreterCompiler(AbstractPlatform platform, SystemLibraryManager sysLibMan)
		{
			this.platform = platform;
			this.interpreterParser = new Parser(platform, null, sysLibMan);
		}
Пример #25
0
		public Resolver(Parser parser, IList<Executable> originalCode)
		{
			this.parser = parser;
			this.currentCode = originalCode.ToArray();
		}
Пример #26
0
		private void CompileNullCoalescer(Parser parser, ByteBuffer buffer, NullCoalescer nullCoalescer, bool outputUsed)
		{
			EnsureUsed(nullCoalescer.FirstToken, outputUsed);

			this.CompileExpression(parser, buffer, nullCoalescer.PrimaryExpression, true);
			ByteBuffer secondaryExpression = new ByteBuffer();
			this.CompileExpression(parser, secondaryExpression, nullCoalescer.SecondaryExpression, true);
			buffer.Add(nullCoalescer.FirstToken, OpCode.POP_IF_NULL_OR_JUMP, secondaryExpression.Size);
			buffer.Concat(secondaryExpression);
		}
Пример #27
0
		private static Executable ParseConst(Parser parser, TokenStream tokens, Executable owner)
		{
			Token constToken = tokens.PopExpected("const");
			Token nameToken = tokens.Pop();
			Parser.VerifyIdentifier(nameToken);
			tokens.PopExpected("=");
			Expression expression = ExpressionParser.Parse(tokens, owner);
			tokens.PopExpected(";");

			return new ConstStatement(constToken, nameToken, parser.CurrentNamespace, expression, owner);
		}
Пример #28
0
		private void CompileBooleanNot(Parser parser, ByteBuffer buffer, BooleanNot boolNot, bool outputUsed)
		{
			if (!outputUsed) throw new ParserException(boolNot.FirstToken, "Cannot have this expression here.");

			this.CompileExpression(parser, buffer, boolNot.Root, true);
			buffer.Add(boolNot.FirstToken, OpCode.BOOLEAN_NOT);
		}
Пример #29
0
		internal static IList<Executable> ParseBlock(Parser parser, TokenStream tokens, bool bracketsRequired, Executable owner)
		{
			List<Executable> output = new List<Executable>();

			if (tokens.PopIfPresent("{"))
			{
				while (!tokens.PopIfPresent("}"))
				{
					output.Add(ExecutableParser.Parse(parser, tokens, false, true, false, owner));
				}
			}
			else
			{
				if (bracketsRequired)
				{
					tokens.PopExpected("{"); // throws with reasonable exception message.
				}

				if (tokens.PopIfPresent(";"))
				{
					return output;
				}

				output.Add(ExecutableParser.Parse(parser, tokens, false, true, false, owner));
			}
			return output;
		}
Пример #30
0
		private static Executable ParseEnumDefinition(Parser parser, TokenStream tokens, Executable owner)
		{
			Token enumToken = tokens.PopExpected("enum");
			Token nameToken = tokens.Pop();
			Parser.VerifyIdentifier(nameToken);
			string name = nameToken.Value;
			tokens.PopExpected("{");
			bool nextForbidden = false;
			List<Token> items = new List<Token>();
			List<Expression> values = new List<Expression>();
			while (!tokens.PopIfPresent("}"))
			{
				if (nextForbidden) tokens.PopExpected("}"); // crash

				Token enumItem = tokens.Pop();
				Parser.VerifyIdentifier(enumItem);
				if (tokens.PopIfPresent("="))
				{
					values.Add(ExpressionParser.Parse(tokens, owner));
				}
				else
				{
					values.Add(null);
				}
				nextForbidden = !tokens.PopIfPresent(",");
				items.Add(enumItem);
			}

			return new EnumDefinition(enumToken, nameToken, parser.CurrentNamespace, items, values, owner);
		}