Click here to Skip to main content
15,885,366 members
Articles / Programming Languages / ASM

Bird Programming Language: Part 2

Rate me:
Please Sign up or sign in to vote.
4.85/5 (10 votes)
1 Jan 2013GPL36 min read 28.3K   344   16  
A new general purpose language that aims to be fast, high level and simple to use. (I renamed it from Anonymus)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bird.Languages.Bird;

namespace Bird.Recognizers
{
	public class TryCommRecognizer : LanguageNode, IFinishableCommRecognizer
	{
		public static string[] Strings = new string[] { "try", "catch", "finally" };

		public TryCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			var State = Scope.State;
			var FindRes = Code.StartsWith(Strings, null, new IdCharCheck(true));
			if (FindRes.Index != -1)
			{
				var Result = State.Language.CommandInnerSeparator.Separate(State, Code);
				if (!Result.Command.IsValid) return SimpleRecResult.Failed;

				var CommandCode = Code.Substring(0, FindRes.String.Length);
				var Param = Result.Command.Substring(FindRes.String.Length).Trim();

				//----------------------------------------------------------------------------------
				if (FindRes.Index == 0)
				{
					if (Param.Length != 0)
					{
						State.Messages.Add(MessageId.NotExpected, Param);
						return SimpleRecResult.Failed;
					}

					var Comm = new Command(Scope, Code, CommandType.Try);
					var NewScope = new CodeScopeNode(Comm, Result.Inner);
					Comm.Children.Add(NewScope);

					if (!NewScope.ProcessCode()) return SimpleRecResult.Failed;
					if (!Scope.AddFinishableCommand(Comm, this)) return SimpleRecResult.Failed;
					return SimpleRecResult.Succeeded;
				}

				//----------------------------------------------------------------------------------
				else if (FindRes.Index == 1)
				{
					var Comm = Scope.LastChild as Command;
					if (Comm == null || Comm.Type != CommandType.Try || Comm.FinallyScope != null ||
						(Comm.Flags & CommandFlags.CatchesAllException) != 0)
					{
						State.Messages.Add(MessageId.NoMatchingCommand, Result.Command);
						return SimpleRecResult.Failed;
					}

					CodeScopeNode NewScope;
					if (Param.Length != 0)
					{
						var VarDeclListFlags = VarDeclarationListFlags.EnableMessages;
						var VarDeclList = VarDeclarationList.Create(Scope, Param, null, VarDeclListFlags);
						if (VarDeclList == null) return SimpleRecResult.Failed;

						if (VarDeclList.Count != 1)
						{
							State.Messages.Add(MessageId.ParamCount, Param);
							return SimpleRecResult.Failed;
						}

						var Decl = VarDeclList[0];
						NewScope = Commands.CreateCatchScope(Comm, CommandCode, Result.Inner, Decl.Type, Decl.Name);
						if (NewScope == null) return SimpleRecResult.Failed;
					}
					else
					{
						NewScope = Commands.CreateCatchScope(Comm, CommandCode, Result.Inner);
						if (NewScope == null) return SimpleRecResult.Failed;
					}


					if (!NewScope.ProcessCode()) return SimpleRecResult.Failed;
					return SimpleRecResult.Succeeded;
				}

				//----------------------------------------------------------------------------------
				else if (FindRes.Index == 2)
				{
					if (Param.Length != 0)
					{
						State.Messages.Add(MessageId.NotExpected, Param);
						return SimpleRecResult.Failed;
					}

					var Comm = Scope.LastChild as Command;
					if (Comm == null || Comm.Type != CommandType.Try || Comm.FinallyScope != null)
					{
						State.Messages.Add(MessageId.NoMatchingCommand, Result.Command);
						return SimpleRecResult.Failed;
					}

					Comm.FinallyScope = new CodeScopeNode(Comm, Result.Inner);
					Comm.Children.Add(Comm.FinallyScope);

					if (!Comm.FinallyScope.ProcessCode())
						return SimpleRecResult.Failed;

					return SimpleRecResult.Succeeded;
				}

				//----------------------------------------------------------------------------------
				else
				{
					throw new ApplicationException();
				}
			}

			return SimpleRecResult.Unknown;
		}

		public bool Finish(IdContainer Container)
		{
			var Comm = Container as Command;
			if ((Comm.Flags & CommandFlags.CatchesAllException) == 0 && Comm.CatchScope != null)
			{
				if (!Commands.CreateDefaultCatchScope(Comm))
					return false;
			}

			return true;
		}
	}

	public class IfCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string String = "if";
		public static string ElseFind = "else";

		public IfCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public static bool ProcIf(CodeScopeNode Scope, CodeString Code, int CommandLength, Command CCondComm = null)
		{
			var RetValue = true;
			var ElseInner = new CodeString();
			var State = Scope.State;

			var Result = State.Language.CommandInnerSeparator.Separate(State, Code);
			if (!Result.Command.IsValid) return false;

			if (Result.FindRes.Position != -1 && Result.Inner.LineCount == 1)
			{
				var SkippingHandlers = State.Language.GlobalHandlers;
				var ElseRes = Result.Inner.Find(ElseFind, null, false, new IdCharCheck(true), SkippingHandlers);
				if (ElseRes != -1)
				{
					var Else = Result.Inner.Substring(ElseRes).Trim();
					Result.Inner = Result.Inner.Substring(0, ElseRes).Trim();

					ElseInner = State.GetInnerScope(Else, ElseFind.Length);
					if (!ElseInner.IsValid) return false;
				}
			}

			var CondComm = CCondComm;
			if (CondComm == null)
				CondComm = new Command(Scope, Code, CommandType.If);

			var Plugin = CondComm.GetPlugin();
			Plugin.GetPlugin<TypeMngrPlugin>().RetType = Scope.GlobalContainer.CommonIds.Boolean;

			var ConditionStr = Result.Command.Substring(CommandLength).Trim();
			var Condition = Expressions.CreateExpression(ConditionStr, Plugin);
			if (Condition == null) RetValue = false;

			var ThenScope = new CodeScopeNode(CondComm, Result.Inner);
			if (!ThenScope.ProcessCode()) RetValue = false;

			CondComm.AddExpression(Condition);
			CondComm.Children.Add(ThenScope);

			if (ElseInner.IsValid)
			{
				var ElseScope = new CodeScopeNode(CondComm, ElseInner);
				CondComm.Children.Add(ElseScope);

				if (!ElseScope.ProcessCode())
					RetValue = false;
			}

			if (CondComm != CCondComm && !Scope.AddCommand(CondComm))
				return false;

			return RetValue;
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				if (!ProcIf(Scope, Code, String.Length))
					return SimpleRecResult.Failed;
				else return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class ElseCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string String = "else";

		public ElseCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public static bool ProcElse(CodeScopeNode Scope, CodeString Code, int CommandLength)
		{
			var State = Scope.State;
			var CondComm = Scope.LastChild as Command;

			var Command = Code.Substring(0, CommandLength).Trim();
			var Inner = State.GetInnerScope(Code.Substring(CommandLength).Trim(), Command);
			if (!Inner.IsValid) return false;

			if (CondComm == null || CondComm.Type != CommandType.If ||
				CondComm.Children.Count > CondComm.Expressions.Count)
			{
				State.Messages.Add(MessageId.NoMatchingCommand, Command);
				return false;
			}
			else
			{
				if (Inner.Line == Code.Line && Inner.StartsWith(IfCommRecognizer.String, new IdCharCheck(true)))
				{
					if (!IfCommRecognizer.ProcIf(Scope, Inner, IfCommRecognizer.String.Length, CondComm))
						return false;
				}
				else
				{
					var NewScope = new CodeScopeNode(CondComm, Inner);
					if (!NewScope.ProcessCode()) return false;
					CondComm.Children.Add(NewScope);
				}
			}

			return true;
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				if (!ProcElse(Scope, Code, String.Length))
					return SimpleRecResult.Failed;
				else return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class LabelCommRecognizer : LanguageNode, ICommRecognizer
	{
		public LabelCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { ":" };
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			var State = Scope.State;
			var SkippingHandlers = State.Language.GlobalHandlers;

			var Result = Code.Find(Operators, Skip, Handlers: SkippingHandlers);
			if (Result.Position == -1) return SimpleRecResult.Unknown;

			var Name = Code.Substring(0, Result.Position).Trim();
			if (!Name.IsValidIdentifierName) return SimpleRecResult.Unknown;

			var StringName = Name.ToString();
			var FS = Scope.FunctionScope;
			if (FS.GetLabelCmd(StringName) != null)
			{
				State.Messages.Add(MessageId.LabelAlreadyDefined, Code);
				return SimpleRecResult.Failed;
			}

			var Comm = new Command(Scope, Code, CommandType.Label);
			Comm.Label = State.AutoLabel;
			if (!Scope.AddCommand(Comm)) return SimpleRecResult.Failed;

			var Inner = Code.Substring(Result.NextChar).Trim();
			if (Inner.Length != 0 && !Scope.RecognizeCommand(Inner))
				return SimpleRecResult.Failed;

			FS.Labels.Add(StringName, Comm);
			return SimpleRecResult.Succeeded;
		}
	}

	public class GotoCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string String = "goto";

		public GotoCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				var State = Scope.State;
				var Label = Code.Substring(String.Length).Trim();
				if (!Label.IsValidIdentifierName)
				{
					State.Messages.Add(MessageId.NotValidName, Label);
					return SimpleRecResult.Failed;
				}

				var Comm = new Command(Scope, Code, CommandType.Goto)
				{
					LabelName = Label,
				};

				Scope.FunctionScope.Gotos.Add(Comm);
				if (!Scope.AddCommand(Comm)) return SimpleRecResult.Failed;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class BreakCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string String = "break";

		public BreakCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				var State = Scope.State;
				if (Code.Trim().Length > String.Length)
				{
					State.Messages.Add(MessageId.NotExpected, Code.Substring(String.Length).Trim());
					return SimpleRecResult.Failed;
				}

				var Comm = Scope.GetParent<Command>(x => (x.Flags & CommandFlags.Breakable) != 0);
				if (Comm == null)
				{
					State.Messages.Add(MessageId.UnBreakCountinueable, Code.Substring(0, String.Length));
					return SimpleRecResult.Failed;
				}

				var NewComm = new Command(Scope, Code, CommandType.Break);
				NewComm.Label = Comm.BreakLabel;
				if (!Scope.AddCommand(NewComm)) return SimpleRecResult.Failed;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class ContinueCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string String = "continue";

		public ContinueCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				var State = Scope.State;
				if (Code.Trim().Length > String.Length)
				{
					State.Messages.Add(MessageId.NotExpected, Code.Substring(String.Length).Trim());
					return SimpleRecResult.Failed;
				}

				var Comm = Scope.GetParent<Command>(x => (x.Flags & CommandFlags.Continueable) != 0);
				if (Comm == null)
				{
					State.Messages.Add(MessageId.UnBreakCountinueable, Code.Substring(0, String.Length));
					return SimpleRecResult.Failed;
				}

				var NewComm = new Command(Scope, Code, CommandType.Continue);
				NewComm.Label = Comm.ContinueLabel;
				if (!Scope.AddCommand(NewComm)) return SimpleRecResult.Failed;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class SwitchCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string[] Strings = new string[] { "switch", "case", "default" };

		public SwitchCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			var FindRes = Code.StartsWith(Strings, null, new IdCharCheck(true));
			if (FindRes.Index == -1) return SimpleRecResult.Unknown;

			var State = Scope.State;
			if (FindRes.Index != 0)
			{
				State.Messages.Add(MessageId.CaseWithoutSwitch, Code);
				return SimpleRecResult.Failed;
			}

			var EndingResult = State.Language.CommandInnerSeparator.Separate(State, Code);
			if (!EndingResult.Command.IsValid) return SimpleRecResult.Failed;

			var ExpressionString = EndingResult.Command.TrimmedSubstring(State, FindRes.String.Length);
			if (!ExpressionString.IsValid) return SimpleRecResult.Failed;

			var SwitchScope = new CodeScopeNode(Scope, EndingResult.Inner);
			if (!Scope.AddCommand(SwitchScope)) return SimpleRecResult.Failed;

			var Plugin = SwitchScope.GetPlugin();
			var Expression = Expressions.CreateExpression(ExpressionString, Plugin, BeginEndMode.Begin);
			if (Expression == null) return SimpleRecResult.Failed;

			if (Expression is OpExpressionNode)
			{
				var Variable = SwitchScope.CreateAndDeclareVariable(new CodeString(), Expression.Type);
				if (Variable == null) return SimpleRecResult.Failed;

				var AssignNode = Expressions.SetValue(Variable, Expression, Plugin, EndingResult.Command, true);
				if (AssignNode == null) return SimpleRecResult.Failed;

				var AssignCommand = new Command(SwitchScope, EndingResult.Command, CommandType.Expression);
				AssignCommand.Expressions = new List<ExpressionNode>() { AssignNode };
				SwitchScope.Children.Add(AssignCommand);

				Expression = new IdExpressionNode(Variable, Code);
			}

			var Condition = new Command(SwitchScope, Code, CommandType.If);
			SwitchScope.Children.Add(Condition);

			var DefaultAlreadySpecified = false;
			var Result = BirdHelper.ForEachLine(SwitchScope, Line =>
			{
				var LocalRes = Line.StartsWith(Strings, null, new IdCharCheck(true));
				if (LocalRes.Index != 1 && LocalRes.Index != 2)
				{
					State.Messages.Add(MessageId.UnknownCommand, Line);
					return false;
				}

				if (DefaultAlreadySpecified)
				{
					State.Messages.Add(MessageId.SwitchAlreadyHasDef, Line);
					return false;
				}

				if (LocalRes.Index == 1)
				{
					var CaseEndingResult = State.Language.CommandInnerSeparator.Separate(State, Code);
					if (!CaseEndingResult.Command.IsValid) return false;

					var CaseString = CaseEndingResult.Command.TrimmedSubstring(State, LocalRes.String.Length);
					if (!CaseString.IsValid) return false;
					
					var CaseScope = new CodeScopeNode(Condition, CaseEndingResult.Inner);
					Condition.Children.Add(CaseScope);

					var CasePlugin = CaseScope.GetPlugin();
					var Right = Expressions.CreateExpression(CaseString, CasePlugin, BeginEndMode.Begin);
					var Left = Expression.Copy(CasePlugin, Mode: BeginEndMode.None);
					if (Left == null || Right == null) return false;

					var CompareNode = (ExpressionNode)new OpExpressionNode(Operator.Equality, CaseEndingResult.Command);
					CompareNode.Children = new ExpressionNode[] { Left, Right };
					if ((CompareNode = CasePlugin.NewNode(CompareNode)) == null) return false;
					if ((CompareNode = CasePlugin.End(CompareNode)) == null) return false;

					Condition.AddExpression(CompareNode);
					if (!CaseScope.ProcessCode()) return false;
				}
				else
				{
					var DefaultEndingResult = State.Language.CommandInnerSeparator.Separate
						(State, Code, CommandInnerSeparatorFlags.InnerIsOptional);

					if (!DefaultEndingResult.Command.IsValid) return false;

					CodeString DefaultInner;
					if (DefaultEndingResult.FindRes.Position == -1)
						DefaultInner = State.GetInnerScope(Line, LocalRes.String.Length);
					else DefaultInner = DefaultEndingResult.Inner;

					var DefaultScope = new CodeScopeNode(Condition, DefaultInner);
					Condition.Children.Add(DefaultScope);

					if (!DefaultScope.ProcessCode()) return false;
				}

				return true;
			});

			if (!Result) return SimpleRecResult.Failed;
			return SimpleRecResult.Succeeded;
		}
	}

	public class DoCommRecognizer : LanguageNode, IFinishableCommRecognizer
	{
		public static string String = "do";

		public DoCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				var Comm = new Command(Scope, Code, CommandType.DoWhile);
				var Inner = Scope.State.GetInnerScope(Code, String.Length);
				if (!Inner.IsValid) return SimpleRecResult.Failed;

				var NewScope = new CodeScopeNode(Comm, Inner);
				Comm.Children.Add(NewScope);

				if (!NewScope.ProcessCode()) return SimpleRecResult.Failed;
				if (!Scope.AddFinishableCommand(Comm, this)) return SimpleRecResult.Failed;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}

		public bool Finish(IdContainer Container)
		{
			var State = Container.State;
			var Comm = Container as Command;

			if (!Comm.HasExpressions)
			{
				State.Messages.Add(MessageId.DeficientDoWhile, Comm.Code);
				return false;
			}

			return true;
		}
	}

	public class RepeatCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string String = "repeat";

		public RepeatCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				var State = Scope.State;
				var RetValue = true;

				var Result = State.Language.CommandInnerSeparator.Separate(State, Code);
				if (!Result.Command.IsValid) return SimpleRecResult.Failed;

				var Comm = new Command(Scope, Code, CommandType.For);
				var NewScope = new CodeScopeNode(Comm, Result.Inner);
				Comm.Children.Add(NewScope);

				if (!NewScope.ProcessCode()) RetValue = false;

				var Plugin = Comm.GetPlugin();
				var RepeatStr = Result.Command.Substring(String.Length).Trim();
				var Condition = Expressions.CreateExpression(RepeatStr, Plugin, BeginEndMode.Begin);
				if (Condition == null) return SimpleRecResult.Failed;

				Condition = Plugin.FinishNode(Condition);
				if (Condition == null) return SimpleRecResult.Failed;

				var Type = Condition.Type;
				if (!(Type is NonFloatType))
				{
					State.Messages.Add(MessageId.MustBeInteger, RepeatStr);
					RetValue = false;
				}

				var Var = Comm.CreateVariable(new CodeString(), Type) as LocalVariable;
				Var.PreAssigned = true;
				Comm.DeclareIdentifier(Var);

				var IdNode = Plugin.NewNode(new IdExpressionNode(Var, Code));
				if (IdNode != null)
				{
					var CondCh = new ExpressionNode[] { IdNode, Condition };
					Condition = Plugin.NewNode(new OpExpressionNode(Operator.Less, CondCh, Code));
					if (Condition == null || (Condition = Plugin.End(Condition)) == null)
						RetValue = false;
				}

				var Init = Expressions.Zero(Plugin, Var, Code);
				var Loop = Expressions.Increase(Plugin, Var, 1, Code);
				if (Loop == null || Init == null) RetValue = false;

				Comm.Expressions = new List<ExpressionNode>() { Init, Condition, Loop };

				if (!Scope.AddCommand(Comm)) RetValue = false;
				if (RetValue) return SimpleRecResult.Succeeded;
				else return SimpleRecResult.Failed;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class CycleCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string String = "cycle";

		public CycleCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				var Inner = Scope.State.GetInnerScope(Code, String.Length);
				if (!Inner.IsValid) return SimpleRecResult.Failed;

				var Comm = new Command(Scope, Code, CommandType.Cycle);
				var NewScope = new CodeScopeNode(Comm, Inner);
				Comm.Children.Add(NewScope);

				if (!NewScope.ProcessCode())
					return SimpleRecResult.Failed;

				if (!Scope.AddCommand(Comm)) return SimpleRecResult.Failed;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class CheckedUncheckedCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string[] Strings = { "checked", "unchecked" };

		public CheckedUncheckedCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			var Res = Code.StartsWith(Strings, null, new IdCharCheck(true));
			if (Res.Index != -1)
			{
				var Inner = Scope.State.GetInnerScope(Code, Res.String.Length);
				if (!Inner.IsValid) return SimpleRecResult.Failed;

				var NewScope = new CodeScopeNode(Scope, Inner);
				if (Res.Index == 0) NewScope.CheckingMode = CheckingMode.Checked;
				else if (Res.Index == 1) NewScope.CheckingMode = CheckingMode.Unchecked;
				else throw new ApplicationException();

				if (!NewScope.ProcessCode()) return SimpleRecResult.Failed;
				if (!Scope.AddCommand(NewScope)) return SimpleRecResult.Failed;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class WhileCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string String = "while";

		public WhileCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				var State = Scope.State;
				var LastComm = Scope.LastChild as Command;
				var DoWhile = LastComm != null && LastComm.Type == CommandType.DoWhile && !LastComm.HasExpressions;

				var CISFlags = CommandInnerSeparatorFlags.None;
				if (DoWhile) CISFlags |= CommandInnerSeparatorFlags.NoEmptyScopeWarning;
				var Result = State.Language.CommandInnerSeparator.Separate(State, Code, CISFlags);
				if (!Result.Command.IsValid) return SimpleRecResult.Failed;

				Command WhileComm;
				CodeScopeNode NewScope = null;
				if (!DoWhile)
				{
					WhileComm = new Command(Scope, Code, CommandType.While);
					NewScope = new CodeScopeNode(WhileComm, Result.Inner);
					WhileComm.Children.Add(NewScope);
				}
				else
				{
					WhileComm = LastComm;
					Scope.MarkFinished();

					if (Result.Inner.IsValid)
					{
						State.Messages.Add(MessageId.NotExpected);
						return SimpleRecResult.Failed;
					}
				}

				var Plugin = WhileComm.GetPlugin();
				Plugin.GetPlugin<TypeMngrPlugin>().RetType = Scope.GlobalContainer.CommonIds.Boolean;

				var ConditionStr = Result.Command.Substring(String.Length).Trim();
				var Condition = Expressions.CreateExpression(ConditionStr, Plugin);
				if (Condition == null) return SimpleRecResult.Failed;

				if (!WhileComm.HasExpressions) WhileComm.AddExpression(Condition); 
				else WhileComm.Expressions[0] = Condition;

				if (!DoWhile)
				{
					if (!NewScope.ProcessCode()) return SimpleRecResult.Failed;
					if (!Scope.AddCommand(WhileComm)) return SimpleRecResult.Failed;
				}

				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class ForInCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string String = "for";
		public static string[] Strings = new string[] { "in" };
		public static string[] StepStrings = new string[] { "step" };

		struct RangeNodePair
		{
			public ExpressionNode Init;
			public ExpressionNode Until;
			public ExpressionNode Step;
			public Operator Operator;

			public RangeNodePair(ExpressionNode Node)
			{
				this.Init = Node;
				this.Until = null;
				this.Step = null;
				this.Operator = Operator.Unknown;
			}

			public RangeNodePair(ExpressionNode Init, ExpressionNode Until, ExpressionNode Step, Operator Operator)
			{
				this.Init = Init;
				this.Until = Until;
				this.Step = Step;
				this.Operator = Operator;
			}
		}

		static ExpressionNode GetChild(ExpressionNode Node, int Index, CodeString Code)
		{
			if (Expressions.GetOperator(Node) == Operator.Tuple)
				return Node.Children[Index];

			var TType = Node.Type.RealId as TupleType;
			if (TType != null)
			{
				var Members = TType.StructuredScope.IdentifierList;
				var Member = new IdExpressionNode(Members[Index], Code);
				var RetCh = new ExpressionNode[] { Node, Member };
				return new OpExpressionNode(Operator.Member, RetCh, Code);
			}

			return Node;
		}

		static int GetTupleLength(ExpressionNode Node, int Default = 1)
		{
			if (Expressions.GetOperator(Node) == Operator.Tuple)
				return Node.Children.Length;

			var TType = Node.Type.RealId as TupleType;
			if (TType != null) return TType.StructuredScope.IdentifierList.Count;
			return Default;
		}

		static bool CheckLength(CompilerState State, ExpressionNode Node, ExpressionNode Step, int Count)
		{
			if (Count != 1 && GetTupleLength(Node, Count) != Count)
			{
				State.Messages.Add(MessageId.ForInvalidTupleSize, Node.Code);
				return false;
			}

			if (Count != 1 && GetTupleLength(Step, Count) != Count)
			{
				State.Messages.Add(MessageId.ForInvalidTupleSize, Step.Code);
				return false;
			}

			return true;
		}

		static RangeNodePair[] MapRangeNodes(CompilerState State, CodeString Code, ExpressionNode Node, ExpressionNode Step = null, int Count = -1)
		{
			if (Step == null)
			{
				var IntType = State.GlobalContainer.CommonIds.GetIdentifier(UndeclaredIdType.Int32);
				var IntValue = new IntegerValue(new System.Numerics.BigInteger(1));
				Step = new ConstExpressionNode(IntType, IntValue, new CodeString(), ExpressionFlags.AutoConvert);
			}

			var Op = Expressions.GetOperator(Node);
			var Ch = Node.Children;

			if (Bird.Operators.IsRange(Op))
			{
				if (Count == -1) Count = Math.Max(GetTupleLength(Ch[0]), GetTupleLength(Ch[1]));
				if (!CheckLength(State, Node, Step, Count)) return null;

				var Ret = new RangeNodePair[Count];
				if (Count != 1)
				{
					for (var i = 0; i < Count; i++)
					{
						Ret[i] = new RangeNodePair(GetChild(Ch[0], i, Code),
							GetChild(Ch[1], i, Code), GetChild(Step, i, Code), Op);
					}
				}
				else
				{
					Ret[0] = new RangeNodePair(Ch[0], Ch[1], Step, Op);
				}

				return Ret;
			}
			else if (Op == Operator.Tuple)
			{
				if (Count == -1) Count = Ch.Length;
				if (!CheckLength(State, Node, Step, Count))
					return null;

				var Ret = new RangeNodePair[Ch.Length];
				for (var i = 0; i < Ch.Length; i++)
				{
					var ChiOp = Expressions.GetOperator(Ch[i]);
					if (Bird.Operators.IsRange(ChiOp))
					{
						var ChiCh = Ch[i].Children;
						Ret[i] = new RangeNodePair(ChiCh[0], ChiCh[1], 
							GetChild(Step, i, Code), ChiOp);
					}
					else
					{
						Ret[i] = new RangeNodePair(Ch[i]);
					}
				}

				return Ret;
			}
			else
			{
				return new RangeNodePair[] { new RangeNodePair(Node) };
			}
		}

		ConditionResult IsNegative(ExpressionNode Node)
		{
			var CNode = Node as ConstExpressionNode;
			if (CNode == null) return ConditionResult.Unknown;

			if (CNode.Value is DoubleValue)
			{
				if ((CNode.Value as DoubleValue).Value < 0)
					return ConditionResult.True;
				else return ConditionResult.False;
			}
			else if (CNode.Value is FloatValue)
			{
				if ((CNode.Value as FloatValue).Value < 0)
					return ConditionResult.True;
				else return ConditionResult.False;
			}
			else if (CNode.Value is IntegerValue)
			{
				if ((CNode.Value as IntegerValue).Value < 0)
					return ConditionResult.True;
				else return ConditionResult.False;
			}
			else if (CNode.Value is ZeroValue)
			{
				return ConditionResult.False;
			}

			return ConditionResult.Unknown;
		}

		List<ExpressionNode> GetExpressions(Command Command, Identifier Variable,
			RangeNodePair RangeNode, CodeString Line, CodeString FLine)
		{
			var Plugin = Command.GetPlugin();
			var InitNode = RangeNode.Init.Copy(Plugin, Mode: BeginEndMode.Begin);
			if (InitNode == null) return null;

			InitNode = Expressions.SetValue(Variable, InitNode, Plugin, FLine, true);
			if (InitNode == null) return null;

			//-------------------------------------------------------------------------
			if (!Plugin.Begin()) return null;
			var CmpChildren = new ExpressionNode[]
			{
				Plugin.NewNode(new IdExpressionNode(Variable, Variable.Name)),
				RangeNode.Until.Copy(Plugin, Mode: BeginEndMode.None),
			};

			if (CmpChildren[0] == null || CmpChildren[1] == null)
				return null;

			Operator CmpOp;
			var NegRes = IsNegative(RangeNode.Step);
			if (NegRes == ConditionResult.False)
			{
				if (RangeNode.Operator == Operator.RangeUntil) CmpOp = Operator.Less;
				else if (RangeNode.Operator == Operator.RangeTo) CmpOp = Operator.LessEqual;
				else throw new ApplicationException();
			}
			else if (NegRes == ConditionResult.True)
			{
				if (RangeNode.Operator == Operator.RangeUntil) CmpOp = Operator.Greater;
				else if (RangeNode.Operator == Operator.RangeTo) CmpOp = Operator.GreaterEqual;
				else throw new ApplicationException();
			}
			else
			{
				throw new NotImplementedException();
			}

			var CmpNode = Plugin.NewNode(new OpExpressionNode(CmpOp, CmpChildren, FLine));
			if (CmpNode == null || (CmpNode = Plugin.End(CmpNode)) == null)
				return null;

			//-------------------------------------------------------------------------
			if (!Plugin.Begin()) return null;
			var IncChildren = new ExpressionNode[]
			{
				Plugin.NewNode(new IdExpressionNode(Variable, Variable.Name)),
				RangeNode.Step.Copy(Plugin, Mode: BeginEndMode.None),
			};

			if (IncChildren[0] == null || IncChildren[1] == null)
				return null;

			var IncNode = Plugin.NewNode(new OpExpressionNode(Operator.Add, IncChildren, FLine));
			if (IncNode == null) return null;

			IncNode = Expressions.SetValue(Variable, IncNode, Plugin, Line, true);
			if (IncNode == null) return null;

			return new List<ExpressionNode>() { InitNode, CmpNode, IncNode };
		}

		public ForInCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				var State = Scope.State;
				var EndingResult = State.Language.CommandInnerSeparator.Separate(State, Code);
				if (!EndingResult.Command.IsValid) return SimpleRecResult.Failed;

				var FLine = EndingResult.Command;
				var Line = FLine.Substring(String.Length).Trim();

				//--------------------------------------------------------------------------------------
				var FindResult = Line.Find(Strings, null, false, new IdCharCheck(true));
				if (FindResult.Index == -1)
				{
					State.Messages.Add(MessageId.DeficientExpr, FLine);
					return SimpleRecResult.Failed;
				}

				var LeftStr = Line.TrimmedSubstring(State, 0, FindResult.Position);
				var RightStr = Line.TrimmedSubstring(State, FindResult.Position + FindResult.String.Length);
				if (!LeftStr.IsValid || !RightStr.IsValid) return SimpleRecResult.Failed;

				var StepStr = new CodeString();
				var StepResult = RightStr.Find(StepStrings, null, false, new IdCharCheck(true));
				if (StepResult.Index != -1)
				{
					StepStr = RightStr.TrimmedSubstring(State, StepResult.Position + StepResult.String.Length);
					RightStr = RightStr.TrimmedSubstring(State, 0, StepResult.Position);
					if (!StepStr.IsValid || !RightStr.IsValid) return SimpleRecResult.Failed;
				}

				//--------------------------------------------------------------------------------------
				var VarDecls = VarDeclarationList.Create(Scope, LeftStr);
				if (VarDecls == null) return SimpleRecResult.Failed;

				if (VarDecls.Count == 0)
				{
					State.Messages.Add(MessageId.NoForVar, LeftStr);
					return SimpleRecResult.Failed;
				}

				//--------------------------------------------------------------------------------------
				var Plugin = Scope.GetPlugin();
				var RangeNodes_Node = Expressions.CreateExpression(RightStr, Plugin);
				if (RangeNodes_Node == null) return SimpleRecResult.Failed;

				ExpressionNode RangeNodes_Step = null;
				if (StepStr.IsValid)
				{
					RangeNodes_Step = Expressions.CreateExpression(StepStr, Plugin);
					if (RangeNodes_Step == null) return SimpleRecResult.Failed;
				}

				var RangeNodes = MapRangeNodes(State, FLine, RangeNodes_Node, RangeNodes_Step, VarDecls.Count);
				if (RangeNodes == null) return SimpleRecResult.Failed;

				//--------------------------------------------------------------------------------------
				var LastContainer = (IdContainer)Scope;
				var ForCommands = new Command[VarDecls.Count];
				for (var i = 0; i < RangeNodes.Length; i++)
				{
					var Command = new Command(LastContainer, Code, CommandType.For);
					if (i > 0) Command.Flags &= ~CommandFlags.Breakable;

					if (LastContainer == Scope)
					{
						if (!Scope.AddCommand(Command))
							return SimpleRecResult.Failed;
					}
					else
					{
						LastContainer.Children.Add(Command);
					}

					LastContainer = Command;
					ForCommands[i] = Command;

					//-------------------------------------------------------------------------
					var Variable = VarDecls[i].ToVariable(Command, Declare: true);
					if (Variable == null) return SimpleRecResult.Failed;

					var RangeNode = RangeNodes[i];
					if (!Bird.Operators.IsRange(RangeNode.Operator))
					{
						State.Messages.Add(MessageId.ForInvalidOp, RightStr);
						return SimpleRecResult.Failed;
					}
					
					//-------------------------------------------------------------------------
					Command.Expressions = GetExpressions(Command, Variable, RangeNode, Line, FLine);
				}

				var NewScope = new CodeScopeNode(LastContainer, EndingResult.Inner);
				LastContainer.Children.Add(NewScope);

				if (!NewScope.ProcessCode()) return SimpleRecResult.Failed;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class ForToCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string String = "for";
		public static string[] Strings = new string[] { "to", "downto", "until", "eachin" };
		public static string[] StepString = new string[] { "step" };

		public ForToCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				var State = Scope.State;
				var Result = State.Language.CommandInnerSeparator.Separate(State, Code);
				if (!Result.Command.IsValid) return SimpleRecResult.Failed;
				var Line = Result.Command.Substring(String.Length).Trim();

				//--------------------------------------------------------------------------------------
				var SkippingHandlers = State.Language.GlobalHandlers;
				var AssignmentPos = Line.Find('=', Handlers: SkippingHandlers);
				if (AssignmentPos == -1)
				{
					State.Messages.Add(MessageId.NoForVar, Code);
					return SimpleRecResult.Failed;
				}

				var LeftStr = Line.TrimmedSubstring(State, 0, AssignmentPos);
				var RightStr = Line.TrimmedSubstring(State, AssignmentPos + 1);
				if (!LeftStr.IsValid || !RightStr.IsValid) return SimpleRecResult.Failed;

				var VarDecls = VarDeclarationList.Create(Scope, LeftStr);
				if (VarDecls == null) return SimpleRecResult.Failed;

				if (VarDecls.Count != 1)
				{
					if (VarDecls.Count == 0) State.Messages.Add(MessageId.NoForVar, Code);
					else State.Messages.Add(MessageId.MoreForVar, Code);
					return SimpleRecResult.Failed;
				}

				var ForCommand = new Command(Scope, Code, CommandType.For);
				var NewScope = new CodeScopeNode(ForCommand, Result.Inner);
				ForCommand.Children.Add(NewScope);
				
				var Plugin = ForCommand.GetPlugin();
				var ForVar = VarDecls[0].ToVariable(ForCommand, Declare: true);
				if (ForVar == null) return SimpleRecResult.Failed;
				
				//--------------------------------------------------------------------------------------
				var FindRes = RightStr.Find(Strings, IdCharCheck: new IdCharCheck(true), Handlers: SkippingHandlers);
				if (FindRes.Index == -1)
				{
					State.Messages.Add(MessageId.ForToDownToUntil, Code);
					return SimpleRecResult.Failed;
				}

				//--------------------------------------------------------------------------------------
				else if (FindRes.Index < 3)
				{
					var FromStr = RightStr.TrimmedSubstring(State, 0, FindRes.Position);
					var UntilToStr = RightStr.TrimmedSubstring(State, FindRes.NextChar);
					if (!FromStr.IsValid || !UntilToStr.IsValid) return SimpleRecResult.Failed;

					var StepStr = new CodeString();
					var StepRes = UntilToStr.Find(StepString, IdCharCheck: new IdCharCheck(true), Handlers: SkippingHandlers);
					if (StepRes.Index != -1)
					{
						StepStr = UntilToStr.TrimmedSubstring(State, StepRes.Position + StepRes.String.Length);
						UntilToStr = UntilToStr.TrimmedSubstring(State, 0, StepRes.Position);
						if (!StepStr.IsValid || !UntilToStr.IsValid) return SimpleRecResult.Failed;
					}

					var From = Expressions.CreateExpression(FromStr, Plugin, BeginEndMode.Begin);
					if (From == null) return SimpleRecResult.Failed;

					var InitNode = Expressions.SetValue(ForVar, From, Plugin, FromStr, true);
					if (InitNode == null) return SimpleRecResult.Failed;

					var UntilTo = Expressions.CreateExpression(UntilToStr, Plugin, BeginEndMode.Begin);
					var ForVarNode = Plugin.NewNode(new IdExpressionNode(ForVar, Code));
					if (ForVarNode == null || UntilTo == null) return SimpleRecResult.Failed;

					Operator CmpOp;
					if (FindRes.Index == 0) CmpOp = Operator.LessEqual;
					else if (FindRes.Index == 1) CmpOp = Operator.GreaterEqual;
					else if (FindRes.Index == 2) CmpOp = Operator.Less;
					else throw new ApplicationException();

					var CmpList = new ExpressionNode[] { ForVarNode, UntilTo };
					var CmpNode = Plugin.NewNode(new OpExpressionNode(CmpOp, CmpList, RightStr));
					if (CmpNode == null || (CmpNode = Plugin.End(CmpNode)) == null)
						return SimpleRecResult.Failed;

					var StepNode = (ExpressionNode)null;
					if (StepStr.IsValid)
					{
						StepNode = Expressions.CreateExpression(StepStr, Plugin, BeginEndMode.Begin);
						if (StepNode == null) return SimpleRecResult.Failed;

						StepNode = Expressions.Increase(Plugin, ForVar, StepNode, StepStr);
						if (StepNode == null) return SimpleRecResult.Failed;
					}
					else
					{
						var StepOp = FindRes.Index == 1 ? Operator.Subract : Operator.Add;
						StepNode = Expressions.Increase(Plugin, ForVar, 1, Code, StepOp);
						if (StepNode == null) return SimpleRecResult.Failed;
					}

					ForCommand.Expressions = new List<ExpressionNode>() { InitNode, CmpNode, StepNode };
				}

				//--------------------------------------------------------------------------------------
				else if (FindRes.Index == 3)
				{
					throw new NotImplementedException();
				}

				//--------------------------------------------------------------------------------------
				else
				{
					throw new ApplicationException();
				}

				if (!NewScope.ProcessCode()) return SimpleRecResult.Failed;
				if (!Scope.AddCommand(ForCommand)) return SimpleRecResult.Failed;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class ThrowCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string[] Strings = new string[] { "throw", "rethrow" };

		public ThrowCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			var Res = Code.StartsWith(Strings, null, new IdCharCheck(true));
			if (Res.Index != -1)
			{
				var State = Scope.State;
				var Global = State.GlobalContainer;
				var Str = Code.Substring(Res.String.Length).Trim();

				var Plugin = Scope.GetPlugin();
				var TypeMngrPlugin = Plugin.GetPlugin<TypeMngrPlugin>();
				TypeMngrPlugin.RetType = Identifiers.GetByFullNameFast<ClassType>(Global, "System.Exception");
				if (TypeMngrPlugin.RetType == null) return SimpleRecResult.Failed;

				var Node = Expressions.CreateExpression(Str, Plugin);
				if (Node == null) return SimpleRecResult.Failed;

				CommandType CommType;
				if (Res.Index == 0) CommType = CommandType.Throw;
				else if (Res.Index == 1) CommType = CommandType.Rethrow;
				else throw new ApplicationException();

				var Comm = new Command(Scope, Code, CommType);
				Comm.Expressions = new List<ExpressionNode>() { Node };
				if (!Scope.AddCommand(Comm)) return SimpleRecResult.Failed;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}
	
	public class ReturnCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string String = "return";

		public ReturnCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				var Node = (ExpressionNode)null;
				if (Code.Trim().Length > String.Length)
				{
					var RetStr = Code.Substring(String.Length).Trim();
					var Plugin = Scope.GetPlugin();
					var TypeMngrPlugin = Plugin.GetPlugin<TypeMngrPlugin>();
					TypeMngrPlugin.RetType = Scope.FunctionScope.Type.RetType;

					Node = Expressions.CreateExpression(RetStr, Plugin);
					if (Node == null) return SimpleRecResult.Failed;
				}

				if (!Scope.FinishLastCommand()) return SimpleRecResult.Failed;
				if (!Scope.Return(Node, Code)) return SimpleRecResult.Failed;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}
	
	public class WithCommRecognizer : LanguageNode, ICommRecognizer
	{
		public static string String = "with";

		public WithCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public static bool IsNewVariableNeeded(ExpressionNode Node)
		{
			if (Node is IdExpressionNode)
			{
				return false;
			}
			else if (Node is OpExpressionNode)
			{
				var OpNode = Node as OpExpressionNode;
				var Op = OpNode.Operator;
				var Ch = OpNode.Children;

				if (Op == Operator.Index)
				{
					var T = Ch[0].Type.RealId;
					if (T is NonrefArrayType || T is PointerType)
						return false;
				}
			}

			return true;
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				var State = Scope.State;
				var Result = State.Language.CommandInnerSeparator.Separate(State, Code);
				if (!Result.Command.IsValid) return SimpleRecResult.Failed;

				var Plugin = Scope.GetPlugin();
				var NodeStr = Code.Substring(String.Length).Trim();
				var Node = Expressions.CreateExpression(NodeStr, Plugin, BeginEndMode.Begin);
				if (Node == null) return SimpleRecResult.Failed;

				if (!(Node.Type.RealId is StructuredType))
				{
					State.Messages.Add(MessageId.WithMustBeStructured, NodeStr);
					return SimpleRecResult.Failed;
				}

				var NewScope = new WithScopeNode(Scope, Result.Inner, null);
				if (!NewScope.ProcessCode()) return SimpleRecResult.Failed;

				if (!IsNewVariableNeeded(Node))
				{
					NewScope.WithNode = Node;
				}
				else
				{
					var Type = Node.Type;
					var Ref = Type is StructType;

					if (Ref)
					{
						Type = new PointerType(Scope, Type);
						var NewCh = new ExpressionNode[] { Node };
						Node = Plugin.NewNode(new OpExpressionNode(Operator.Address, NewCh, NodeStr));
						if (Node == null) return SimpleRecResult.Failed;
					}

					var Var = NewScope.CreateVariable(new CodeString(), Type);
					NewScope.DeclareIdentifier(Var);

					Node = Expressions.SetValue(Var, Node, Plugin, NodeStr, true);
					if (Node == null) return SimpleRecResult.Failed;

					NewScope.Children.Add(new Command(Scope, NodeStr, CommandType.Expression)
					{
						Expressions = new List<ExpressionNode>() { Node },
					});

					NewScope.WithNode = (ExpressionNode)new IdExpressionNode(Var, NodeStr);
					if (Ref)
					{
						NewScope.WithNode = Expressions.Indirection(Plugin, NewScope.WithNode, NodeStr);
						if (NewScope.WithNode == null || Plugin.End(ref NewScope.WithNode) == PluginResult.Failed)
							return SimpleRecResult.Failed;
					}
				}


				if (!Scope.AddCommand(NewScope)) return SimpleRecResult.Failed;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}
	
	public class VarDeclCommRecognizer : LanguageNode, ICommRecognizer
	{
		public VarDeclCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public bool StartsWithType(IdContainer Container, CodeString Str)
		{
			if (Str.Length == 0) return false;

			var SkippingHandler = Container.State.Language.GlobalHandlers;
			var T = Str.Word(ModThis: false, WordStart: true, Handlers: SkippingHandler);
			if (T.IsEqual("var") || T.IsEqual("unsafe_ref") || T.IsEqual("ref") ||
				T.IsEqual("out") || T.IsEqual("fun")) return true;

			var Options = GetIdOptions.DefaultForType;
			Options.EnableMessages = false;
			Options.Func = x =>
			{
				var Typex = x.RealId as Type;
				return Typex != null && (Typex.TypeFlags & TypeFlags.CanBeVariable) != 0;
			};

			return Container.RecognizeIdentifier(T, Options) != null;
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			var Mods = Modifiers.Recognize(Scope, ref Code);
			if (Mods == null) return SimpleRecResult.Failed;

			if (Mods.Count > 0 || StartsWithType(Scope, Code))
			{
				var Mode = VarDeclConvMode.Assignment;
				if (Modifiers.Contains<ConstModifier>(Mods))
					Mode = VarDeclConvMode.Normal;

				if (!Scope.DeclareVariables(Code, Mods, Mode, GetIdMode.Function))
					return SimpleRecResult.Failed;

				Scope.DisableLastChild = true;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class ExprCommRecognizer : LanguageNode, ICommRecognizer
	{
		public ExprCommRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			var Node = Expressions.CreateExpression_RetValLess(Code, Scope.GetPlugin());
			if (Node == null) return SimpleRecResult.Failed;

			var Comm = new Command(Scope, Code, CommandType.Expression);
			Comm.Expressions = new List<ExpressionNode>() { Node };
			if (!Scope.AddCommand(Comm)) return SimpleRecResult.Failed;
			return SimpleRecResult.Succeeded;
		}
	}

	public class AfterDeclarationData
	{
		public CodeString AfterDeclaration;
		public bool InAfterDeclaration;
	}

	public class AfterDeclarationRecognizer : LanguageNode, ICommRecognizer
	{
		public AfterDeclarationRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public virtual SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			var FS = Scope as FunctionScope;
			if (FS == null) return SimpleRecResult.Unknown;

			var FSData = FS.Data.Get<AfterDeclarationData>();
			if (FSData == null || !FSData.InAfterDeclaration)
				return SimpleRecResult.Unknown;

			return SimpleRecResult.Succeeded;
		}
	}

	public class CtorCallRecognizer : AfterDeclarationRecognizer
	{
		public CtorCallRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		Constructor GetConstructor(CodeScopeNode Scope, Identifier Class, ExpressionNode[] Ch, CodeString Code)
		{
			var List = Identifiers.SearchMember(Scope, Class, null, x => x is Constructor);
			if (List.Count == 0) throw new ApplicationException("Classes must have constructors");

			var Options = GetIdOptions.Default;
			Options.OverloadData = Expressions.GetOverloadSelectData(Ch);

			var Constructor = Identifiers.SelectIdentifier(Scope.State, List, Code, Options);
			if (Constructor == null || !Identifiers.VerifyAccess(Scope, Constructor, Code))
				return null;

			return Constructor as Constructor;
		}

		ExpressionNode GetConstructorNode(PluginRoot Plugin, Identifier Class, ExpressionNode[] Ch, CodeString Code)
		{
			var Scope = Plugin.Container as FunctionScope;
			if (Scope == null) throw new InvalidOperationException();

			var Constructor = GetConstructor(Scope, Class, Ch, Code);
			if (Constructor == null) return null;

			var ConstructorNode = Plugin.NewNode(new IdExpressionNode(Constructor, Code));
			var SelfNode = Plugin.NewNode(new IdExpressionNode(Scope.SelfVariable, Code));
			if (SelfNode == null || ConstructorNode == null) return null;

			var MemberCh = new ExpressionNode[] { SelfNode, ConstructorNode };
			return Plugin.NewNode(new OpExpressionNode(Operator.Member, MemberCh, Code));
		}

		ExpressionNode GetConstructorCaller(PluginRoot Plugin, Identifier Class, ExpressionNode[] Ch, CodeString Code)
		{
			Ch[0] = GetConstructorNode(Plugin, Class, Ch, Code);
			if (Ch[0] == null) return null;

			var TypeMngrPlugin = Plugin.GetPlugin<TypeMngrPlugin>();
			TypeMngrPlugin.Flags |= TypeMngrPluginFlags.AllowConstructorCalls;

			var RetValue = Plugin.NewNode(new OpExpressionNode(Operator.Call, Ch, Code));
			if (RetValue == null) return null;

			return Plugin.End(RetValue);
		}

		public override SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			var BaseRes = base.Recognize(Scope, Code);
			if (BaseRes != SimpleRecResult.Succeeded) return BaseRes;

			var State = Scope.State;
			var Language = State.Language;
			var CodeProcessor = Language.CodeProcessor;
			var FScope = Scope as FunctionScope;

			if (!(FScope.Function is Constructor))
				return SimpleRecResult.Unknown;

			if (Code.StartsWith(CodeProcessor.SelfName, new IdCharCheck(true)) ||
				Code.StartsWith(CodeProcessor.BaseName, new IdCharCheck(true)))
			{
				CodeString Function, Parameters;
                var CallParamRec = Language.Root.GetObject<ICallParamRecognizer>();
				if (!CallParamRec.GetParameters(State, Code, out Function, out Parameters))
					return SimpleRecResult.Failed;

				var StructuredScope = Scope.Parent as StructuredScope;
				var Type = StructuredScope.StructuredType as ClassType;

				if (Type == null)
				{
					State.Messages.Add(MessageId.NotExpected, Code);
					return SimpleRecResult.Failed;
				}

				var TypeToConstruct = (Identifier)null;
				if (Function.IsEqual(CodeProcessor.SelfName))
				{
					TypeToConstruct = Type;
				}
				else if (Function.IsEqual(CodeProcessor.BaseName))
				{
					if (Type.BaseStructures.Length == 0)
					{
						State.Messages.Add(MessageId.UnknownId, Function);
						return SimpleRecResult.Failed;
					}
					else if (Type.BaseStructures.Length > 1)
					{
						State.Messages.Add(MessageId.AmbiguousReference, Function);
						return SimpleRecResult.Failed;
					}

					TypeToConstruct = Type.BaseStructures[0].Base;
				}
				else
				{
					return SimpleRecResult.Unknown;
				}

				var Plugin = Scope.GetPlugin();
				if (!Plugin.Begin()) return SimpleRecResult.Failed;

				var Ch = CallParamRec.ProcessParameters(Plugin, new CodeString(), Parameters);
				if (Ch == null) return SimpleRecResult.Failed;

				if (!Expressions.FinishParameters(Plugin, Ch))
					return SimpleRecResult.Failed;

				var CtorCaller = GetConstructorCaller(Plugin, TypeToConstruct, Ch, Code);
				if (CtorCaller == null) return SimpleRecResult.Failed;

				FScope.ConstructorCall = CtorCaller;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class ExtraStorageRecognizer : AfterDeclarationRecognizer
	{
		public static string String = "_set_extra_storage";

		public ExtraStorageRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public override SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			var BaseRes = base.Recognize(Scope, Code);
			if (BaseRes != SimpleRecResult.Succeeded) return BaseRes;

			var State = Scope.State;
			var Language = State.Language;
			var FScope = Scope as FunctionScope;

			if (!(FScope.Function is Constructor))
				return SimpleRecResult.Unknown;

			if (Code.StartsWith(String, new IdCharCheck(true)))
			{
				CodeString Function, Parameters;
                var CallParamRec = Language.Root.GetObject<ICallParamRecognizer>();
				if (!CallParamRec.GetParameters(State, Code, out Function, out Parameters))
					return SimpleRecResult.Failed;

				if (!Function.IsEqual(String))
					return SimpleRecResult.Unknown;

				var Plugin = Scope.GetPlugin();
				if (!Plugin.Begin()) return SimpleRecResult.Failed;

				var Ch = CallParamRec.ProcessParameters(Plugin, Function, Parameters);
				if (Ch == null) return SimpleRecResult.Failed;

				if (Ch.Length != 2)
				{
					State.Messages.Add(MessageId.ParamCount, Code);
					return SimpleRecResult.Failed;
				}

				var StructureScope = Scope.Parent as StructuredScope;
				var Structure = StructureScope.StructuredType;

				Ch[0] = Plugin.NewNode(Constants.GetIntValue(Scope, Structure.InstanceSize, Code, true));
				var Node = Plugin.NewNode(new OpExpressionNode(Operator.Add, Ch, Code));
				if (Node == null) return SimpleRecResult.Failed;

				FScope.ObjectSize = Node;
				return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}

	public class NonAfterDeclBlocker : AfterDeclarationRecognizer
	{
		public NonAfterDeclBlocker(LanguageNode Parent)
			: base(Parent)
		{
		}

		public override SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			var BaseRes = base.Recognize(Scope, Code);
			if (BaseRes == SimpleRecResult.Succeeded)
			{
				Scope.State.Messages.Add(MessageId.NotExpected, Code);
				return SimpleRecResult.Failed;
			}

			return BaseRes;
		}
	}

	public class LineSplittingRecognizer : LanguageNode, ICommRecognizer
	{
		public LineSplittingRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public SimpleRecResult Recognize(CodeScopeNode Scope, CodeString Code)
		{
			var SkippingHandlers = Scope.State.Language.GlobalHandlers;
			if (Code.Find(';', Handlers: SkippingHandlers) != -1)
			{
				var Spl = Code.Split(';', StringSplitOptions.RemoveEmptyEntries, true, SkippingHandlers);
				var RetValue = true;

				for (var i = 0; i < Spl.Count; i++)
					if (!Scope.RecognizeCommand(Spl[i])) RetValue = false;

				if (!RetValue) return SimpleRecResult.Failed;
				else return SimpleRecResult.Succeeded;
			}

			return SimpleRecResult.Unknown;
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer
Hungary Hungary
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions