Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Bird Programming Language: Part 1

, 1 Jan 2013 GPL3
A new general purpose language that aims to be fast, high level and simple to use.
Bird-noexe.zip
Bird
Archives
crt2.o
crtbegin.o
crtend.o
libadvapi32.a
libcomctl32.a
libcomdlg32.a
libgcc.a
libgdi32.a
libglu32.a
libkernel32.a
libmingw32.a
libmingwex.a
libmoldname.a
libmsvcrt.a
libopengl32.a
libshell32.a
libstdc++.a
libuser32.a
libwinmm.a
libwsock32.a
Libraries
BirdCore
Array.bird
BigInteger.bird
BinaryRW.bird
BirdCore.a
BirdCore.blib
CategoryData.dat
Console.bird
Convert.bird
Debug.bird
Entry.bird
Environment.bird
Exception.bird
Float.bird
LEB128.bird
Math.bird
Memory.bird
Object.bird
Random.bird
Reflection.bird
StandardC.bird
Stream.bird
String.bird
ToLowerData.dat
ToUpperData.dat
Types.bird
ValueType.bird
Win32.bird
x86Helper.bird
BlitzMax
.bmx
Launcher.bmx.gui.release.win32.x86.o
appstub.release.win32.x86.a
bank.release.win32.x86.a
bankstream.release.win32.x86.a
blitz.release.win32.x86.a
BlitzMax.a
BlitzMax.bird
BlitzMax.blib
d3d7max2d.release.win32.x86.a
d3d9max2d.release.win32.x86.a
directx.release.win32.x86.a
dxgraphics.release.win32.x86.a
event.release.win32.x86.a
filesystem.release.win32.x86.a
font.release.win32.x86.a
glgraphics.release.win32.x86.a
glmax2d.release.win32.x86.a
graphics.release.win32.x86.a
hook.release.win32.x86.a
keycodes.release.win32.x86.a
Launcher.bmx
libpng.release.win32.x86.a
linkedlist.release.win32.x86.a
math.release.win32.x86.a
max2d.release.win32.x86.a
opengl.release.win32.x86.a
pixmap.release.win32.x86.a
pngloader.release.win32.x86.a
polledinput.release.win32.x86.a
standardio.release.win32.x86.a
stdc.release.win32.x86.a
stream.release.win32.x86.a
system.release.win32.x86.a
textstream.release.win32.x86.a
win32.release.win32.x86.a
zlib.release.win32.x86.a
PrgLinec.bmx
Samples
Circles
Circles.bird
CppMain.bird
Fire
Fire.bird
Higher Order Functions
C#
Higher Order Functions.v11.suo
Properties
Test.bird
msvcrt.lib
Reflection
Reflection.bird
Squares
Squares.bird
Template
Template.bird
Source
Base
Bird.v11.suo
Expressions
Identifiers
Languages
NativeCode
Properties
Recognizers
Expressions
Scopes
x86
Thumbs.db
Bird.zip
crt2.o
crtbegin.o
crtend.o
libadvapi32.a
libcomctl32.a
libcomdlg32.a
libgcc.a
libgdi32.a
libglu32.a
libkernel32.a
libmingw32.a
libmingwex.a
libmoldname.a
libmsvcrt.a
libopengl32.a
libshell32.a
libstdc++.a
libuser32.a
libwinmm.a
libwsock32.a
Binaries
ar.exe
Bird.exe
fasm.exe
ld.exe
libiconv-2.dll
libintl-8.dll
Array.bird
BigInteger.bird
BinaryRW.bird
BirdCore.a
BirdCore.blib
CategoryData.dat
Console.bird
Convert.bird
Debug.bird
Entry.bird
Environment.bird
Exception.bird
Float.bird
LEB128.bird
Math.bird
Memory.bird
Object.bird
Random.bird
Reflection.bird
StandardC.bird
Stream.bird
String.bird
ToLowerData.dat
ToUpperData.dat
Types.bird
ValueType.bird
Win32.bird
x86Helper.bird
Launcher.bmx.gui.release.win32.x86.o
appstub.release.win32.x86.a
bank.release.win32.x86.a
bankstream.release.win32.x86.a
blitz.release.win32.x86.a
BlitzMax.a
BlitzMax.bird
BlitzMax.blib
d3d7max2d.release.win32.x86.a
d3d9max2d.release.win32.x86.a
directx.release.win32.x86.a
dxgraphics.release.win32.x86.a
event.release.win32.x86.a
filesystem.release.win32.x86.a
font.release.win32.x86.a
glgraphics.release.win32.x86.a
glmax2d.release.win32.x86.a
graphics.release.win32.x86.a
hook.release.win32.x86.a
keycodes.release.win32.x86.a
Launcher.bmx
libpng.release.win32.x86.a
linkedlist.release.win32.x86.a
math.release.win32.x86.a
max2d.release.win32.x86.a
opengl.release.win32.x86.a
pixmap.release.win32.x86.a
pngloader.release.win32.x86.a
polledinput.release.win32.x86.a
standardio.release.win32.x86.a
stdc.release.win32.x86.a
stream.release.win32.x86.a
system.release.win32.x86.a
textstream.release.win32.x86.a
win32.release.win32.x86.a
zlib.release.win32.x86.a
PrgLinec.bmx
PrgLinec.exe
Circles.bird
CppMain.bird
Fire.bird
Higher Order Functions.v11.suo
Test.bird
msvcrt.lib
Reflection.bird
Squares.bird
Template.bird
Bird.v11.suo
Thumbs.db
examples.zip
Examples
As.exe
AsLibs.a
PerfTest
Launcher.bmx
Squares
.bmx
Launcher.bmx
Template
Launcher.bmx
source.zip
Anonymus 7_1
Anonymus.csproj.user
Anonymus.idc
Anonymus.pidb
Anonymus.suo
Anonymus.userprefs
Base
Expressions
Lib
Long
LongDivTest.bmx
ULongConv.bmx
Math
MISZ
AsLibs.a
PerfTest
Launcher.bmx
Squares
Launcher.bmx
Template
Launcher.bmx
PrgLinec.bmx
PrgLinec.exe
Properties
Scopes
Txt
Asm.docx
Code.docx
Lib.aslib
~$Code.docx
x86
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Bird.Languages.Bird;

namespace Bird.Recognizers
{
	public class IsAsToRecognizer : LanguageNode, IExprRecognizer
	{
		public IsAsToRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { "is", "as", "to" };
			NewLineLeft = NewLineRight = Operators;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Out)
		{
			var Result = RecognizerHelper.Find(this, Plugin.State, Code.String);
			if (Result.Position != -1)
			{
				var State = Plugin.State;
				var LeftStr = Code.TrimmedSubstring(State, 0, Result.Position);
				var RightStr = Code.TrimmedSubstring(State, Result.NextChar);
				if (!LeftStr.IsValid || !RightStr.IsValid) return ExprRecResult.Failed;

				var TypeOptions = GetIdOptions.DefaultForType;
				var Type = Identifiers.Recognize(Plugin.Container, RightStr);
				if (Type == null) return ExprRecResult.Failed;

				var Left = Expressions.Recognize(LeftStr, Plugin, true);
				var Right = Plugin.NewNode(new IdExpressionNode(Type, RightStr));
				if (Left == null || Right == null) return ExprRecResult.Failed;

				Operator Op;
				if (Result.Index == 0) Op = Operator.Is;
				else if (Result.Index == 1) Op = Operator.As;
				else if (Result.Index == 2) Op = Operator.Cast;
				else throw new ApplicationException();

				var Ch = new ExpressionNode[] { Left, Right };
				Out = new OpExpressionNode(Op, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class CastRecognizer : LanguageNode, IExprRecognizer, IFind2Handler
	{
		public CastRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { "(" };
		}

		public bool IsCastString(CompilerState State, StringSlice String)
		{
			if (String.StartsWith(Operators, Skip).Position != -1)
			{
				var ZPos = String.GetBracketPos(false, SkippingHandlers);
				var Right = String.Substring(ZPos + 1).Trim();
				if (ZPos == -1 || Right.Length == 0) return false;

				var Lang = State.Language;
                var Res = Right.StartsWith(Lang.Root.NewLineLeft, Lang.Root.OnlyRight, new IdCharCheck(true));
				return Res.Position == -1 || (Right.Length > 0 && Right[0] == '(');
			}

			return false;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			if (IsCastString(Plugin.State, Code.String))
			{
				var State = Plugin.State;
				var Container = Plugin.Container;
				var Pos = Code.GetBracketPos(State);
				if (Pos == -1) return ExprRecResult.Failed;

				var TypeName = Code.TrimmedSubstring(State, 1, Pos - 1);
				var ChildStr = Code.TrimmedSubstring(State, Pos + 1);
				if (!TypeName.IsValid || !ChildStr.IsValid) return ExprRecResult.Failed;

				var Type = Container.RecognizeIdentifier(TypeName, GetIdOptions.DefaultForType);
                if (Type == null) return ExprRecResult.Failed;

				var Child = Expressions.Recognize(ChildStr, Plugin, true);
                var TypeNode = Plugin.NewNode(new IdExpressionNode(Type, TypeName));
                if (Child == null || TypeNode == null) return ExprRecResult.Failed;

                var Ch = new ExpressionNode[] { Child, TypeNode };
                Ret = new OpExpressionNode(Operator.Cast, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}

		public bool IsAcceptable(IdContainer Container, StringSlice String)
		{
			var BracketPos = String.Length - 1;
			if (BracketPos > 0 && String[BracketPos] == ')')
			{
				var Handlers = Container.State.Language.GlobalHandlers;
				var ZPos = String.GetBracketPos(true, Handlers);
				if (ZPos == -1) return true;

				var Left = String.Substring(0, ZPos);
				if (RecognizerHelper.IsAcceptable(Container, Left))
					return true;

				var SubStr = new CodeString(String.Substring(ZPos + 1, BracketPos - ZPos - 1));
				var Options = GetIdOptions.DefaultForType;
				Options.EnableMessages = false;
				return Container.RecognizeIdentifier(SubStr, Options) == null;
			}

			return true;
		}
	}

	public class RangeRecognizer : LanguageNode, IExprRecognizer
	{
		public RangeRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { "...", ".." };
			NewLineLeft = NewLineRight = Operators;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Out)
		{
			var Result = RecognizerHelper.Find(this, Plugin.State, Code.String);
			if (Result.Position != -1)
			{
				var Ch = RecognizerHelper.GetLeftRightNode(Code, Result, Plugin);
				if (Ch == null) return ExprRecResult.Failed;

				Operator Op;
				if (Result.Index == 0) Op = Operator.RangeTo;
				else if (Result.Index == 1) Op = Operator.RangeUntil;
				else throw new ApplicationException();

				Out = new OpExpressionNode(Op, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class VarDeclRecignizer : LanguageNode, IExprRecognizer
	{
		public VarDeclRecignizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Out)
		{
			var State = Plugin.State;
			var AutoType = State.GlobalContainer.CommonIds.Auto;

			if (Code.StartsWith(AutoType.Name.ToString(), new IdCharCheck(true)))
			{
				var VarDeclRec = State.Language.VarDeclRecognizer;
				var Decls = new VarDeclarationList();
				if (!VarDeclRec.Recognize(Plugin.Container, Code, true, Decls))
					return ExprRecResult.Failed;

				var Vars = Decls.ToVariables(Plugin, BeginEndMode.None,
					VarDeclConvMode.Assignment, true, true, true);

				if (Vars == null || Vars.Contains(null)) 
					return ExprRecResult.Failed;

                if (Vars.Length == 1)
				{
					Out = new IdExpressionNode(Vars[0], Decls[0].Declaration);
					return ExprRecResult.Succeeded;
				}

                var RetCh = new ExpressionNode[Vars.Length];
				var HaveInitVals = true;
                for (var i = 0; i < Vars.Length; i++)
				{
					var e = Vars[i];
					if (i == 0)
					{
						HaveInitVals = e.InitValue != null;
					}
					else if ((e.InitValue != null) != HaveInitVals)
					{
						State.Messages.Add(MessageId.ExprVarDeclInitVal, e.Name);
						return ExprRecResult.Failed;
					}

					var Node = e.InitValue;
					if (Node == null)
					{
						Node = Plugin.NewNode(new IdExpressionNode(e, Decls[i].Declaration));
						if (Node == null) return ExprRecResult.Failed;
					}

					RetCh[i] = Node;
				}

				Out = new OpExpressionNode(Operator.Tuple, RetCh, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class RefRecognizer : LanguageNode, IExprRecognizer
	{
		public RefRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			NewLineRight = Operators = new string[] { "unsafe_ref", "ref", "out" };
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			var Result = Code.StartsWith(Operators, Skip, IdCharCheck: new IdCharCheck(true));
			if (Result.Index != -1)
			{
				var SubCode = Code.TrimmedSubstring(Plugin.State, Result.String.Length);
				if (!SubCode.IsValid) return ExprRecResult.Failed;

				var Child = Expressions.Recognize(SubCode, Plugin, true);
				if (Child == null) return ExprRecResult.Failed;

				Operator Op;
				if (Result.Index == 0) Op = Operator.Reference_Unsafe;
				else if (Result.Index == 1) Op = Operator.Reference_IdMustBeAssigned;
				else if (Result.Index == 2) Op = Operator.Reference_IdGetsAssigned;
				else throw new ApplicationException();

				var Ch = new ExpressionNode[] { Child };
				Ret = new OpExpressionNode(Op, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class BirdNewRecognizer : LanguageNode, IExprRecognizer
	{
		public CallRecognizer CallRecognizer;
		public bool EnableWithoutBracket = true;

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

        public override void Init(LanguageInitData InitData)
		{
            CallRecognizer = Language.Root.GetObject<CallRecognizer>();
			base.Init(InitData);
		}

		public NodeGroup GetGroups(PluginRoot Plugin, CodeString Code, int DimensionCount)
		{
			var State = Plugin.State;
			var Container = Plugin.Container;
			var Ret = new NodeGroup(Code);

			var Result = BirdHelper.ForEachLine(State, Code, Line =>
			{
				var Rec = State.Language.ParameterRecognizer;
				var List = Rec.SplitToParameters(State, Line);
				if (List == null) return false;

				var LocalGroup = (NodeGroup)null;
				if (DimensionCount >= 2)
				{
					LocalGroup = new NodeGroup(Line);
					Ret.Children.Add(LocalGroup);
				}

				var RetValue = true;
				for (var i = 0; i < List.Length; i++)
				{
					var String = List[i];
					object Object;

					if (String.Length > 1 && String[0] == '(' && String[String.Length - 1] == ')')
					{
						var SubString = String.TrimmedSubstring(State, 1, String.Length - 2);
						if (!SubString.IsValid) { RetValue = false; continue; }

						var NewGroup = BracketGroupRecognizer.GetGroups(Plugin, SubString, '(', ')');
						if (NewGroup == null) { RetValue = false; continue; }

						if (NewGroup.MaxDepth + 1 == DimensionCount)
						{
							LocalGroup.Children.AddRange(NewGroup.Children);
							continue;
						}

						Object = NewGroup;
					}
					else
					{
						Object = Expressions.Recognize(String, Plugin, true);
						if (Object == null) { RetValue = false; continue; }
					}

					if (LocalGroup == null) Ret.Children.Add(Object);
					else LocalGroup.Children.Add(Object);
				}

				return RetValue;
			});

			return Result ? Ret : null;
		}

		public bool CheckGroups_DimensionsNotSpecified(PluginRoot Plugin,
			NodeGroup Group, ExpressionNode[] Ch, CodeString Code, int DimensionCount)
		{
			var State = Plugin.State;
			var Global = State.GlobalContainer;
			var Container = Plugin.Container;

			var Lengths = Expressions.GetArrayLengths(State, Group);
			if (Lengths == null) return false;

			if (DimensionCount != Lengths.Length)
			{
				State.Messages.Add(MessageId.ArrayInitializerLength, Code);
				return false;
			}

			var Succeeded = true;
			for (var i = 0; i < Lengths.Length; i++)
			{
				var Node = Plugin.NewNode(Constants.GetIntValue(Container, Lengths[i], Code));
				if (Node == null) { Succeeded = false; continue; }

				Ch[i + 1] = Node;
			}

			return Succeeded;
		}

		public bool CheckGroups_DimensionsSpecified(PluginRoot Plugin, 
			NodeGroup Group, ExpressionNode[] Ch, CodeString Code)
		{
			var State = Plugin.State;
			var Global = State.GlobalContainer;

			var Lengths = Expressions.GetArrayLengths(State, Group);
			if (Lengths == null) return false;

			if (Ch.Length - 1 != Lengths.Length)
			{
				State.Messages.Add(MessageId.ArrayInitializerLength, Code);
				return false;
			}

			var RetValue = true;
			for (var i = 0; i < Lengths.Length; i++)
			{
				var Node = Ch[i + 1];
				if (!Node.Type.IsEquivalent(Global.CommonIds.Int32))
				{
					var TypeMngrPlugin = Plugin.GetPlugin<TypeMngrPlugin>();
					if (TypeMngrPlugin == null)
					{
						State.Messages.Add(MessageId.ImplicitlyCast, Node.Code);
						RetValue = false;
						continue;
					}

					Node = TypeMngrPlugin.Convert(Node, Global.CommonIds.Int32, Node.Code);
					if (Node == null) { RetValue = false; continue; }

					Ch[i + 1] = Node;
				}

				var ConstNode = Node as ConstExpressionNode;
				if (ConstNode == null)
				{
					State.Messages.Add(MessageId.MustBeConst, Node.Code);
					RetValue = false;
					continue;
				}

				if (Lengths[i] != ConstNode.Integer)
				{
					State.Messages.Add(MessageId.ArrayInitializerLength, Node.Code);
					RetValue = false;
					continue;
				}
			}

			return RetValue;
		}

		private ExpressionNode CreateIndexNode(PluginRoot Plugin, Identifier Id, List<int> Indices, CodeString Code)
		{
			var Container = Plugin.Container;

			var Ch = new ExpressionNode[Indices.Count + 1];
			Ch[0] = Plugin.NewNode(new IdExpressionNode(Id, Code));
			if (Ch[0] == null) return null;

			for (var i = 0; i < Indices.Count; i++)
			{
				Ch[i + 1] = Plugin.NewNode(Constants.GetIntValue(Container, Indices[i], Code));
				if (Ch[i + 1] == null) return null;
			}

			return Plugin.NewNode(new OpExpressionNode(Operator.Index, Ch, Code));
		}

		public void CreateInitValue_ForArray(NodeGroup Group, List<ExpressionNode> Children, 
			List<ArrayIndices> Indices, List<int> CurrentIndices = null)
		{
			if (CurrentIndices == null)
				CurrentIndices = new List<int>();

			for (var i = 0; i < Group.Children.Count; i++)
			{
				CurrentIndices.Add(i);

				var Object = Group.Children[i];
				if (Object is ExpressionNode)
				{
					Children.Add(Object as ExpressionNode);
					Indices.Add(new ArrayIndices(CurrentIndices.ToArray()));
				}
				else if (Object is NodeGroup)
				{
					CreateInitValue_ForArray(Object as NodeGroup, Children, Indices, CurrentIndices);
				}
				else
				{
					throw new ApplicationException();
				}

				CurrentIndices.RemoveAt(CurrentIndices.Count - 1);
			}
		}

		public bool CreateInitValue_ForArray(PluginRoot Plugin, NodeGroup Group,
			ExpressionNode Node, CodeString Code)
		{
			var Children = new List<ExpressionNode>();
			var Indices = new List<ArrayIndices>();
			CreateInitValue_ForArray(Group, Children, Indices);

			var LNode = Plugin.NewNode(new ArrayInitNode(Children.ToArray(), Indices.ToArray(), Code));
			if (LNode == null) return false;

			Node.LinkedNodes.Add(new LinkedExprNode(LNode, LinkedNodeFlags.NotRemovable));
			return true;
		}

		public bool CreateInitValue_ForObject(PluginRoot Plugin, ExpressionNode Node, CodeString Code)
		{
			var State = Plugin.State;
			var Container = Plugin.Container;
			var SkippingHandlers = State.Language.GlobalHandlers;
			var Refs = new List<IdentifierReference>();
			var Nodes = new List<ExpressionNode>();

			var Result = BirdHelper.ForEachLine(State, Code, Line =>
			{
				var Rec = State.Language.ParameterRecognizer;
				var List = Rec.SplitToParameters(State, Line);
				if (List == null) return false;
				
				var RetValue = true;
				for (var i = 0; i < List.Length; i++)
				{
					var String = List[i];
					var Pos = String.Find('=', false, SkippingHandlers);
					if (Pos == -1) 
					{
						State.Messages.Add(MessageId.NotExpected, String);
						RetValue = false;
						continue;
					}
					
					var Left = String.TrimmedSubstring(State, 0, Pos);
					var Right = String.TrimmedSubstring(State, Pos + 1);
					if (!Left.IsValid || !Right.IsValid) { RetValue = false; continue; }

					if (!Left.IsValidIdentifierName)
					{
						State.Messages.Add(MessageId.NotValidName, Left);
						RetValue = false;
						continue;
					}

					var Value = Expressions.Recognize(Right, Plugin, true);
					if (Node == null) return false;

					Refs.Add(new IdentifierReference(Left));
					Nodes.Add(Value);
				}

				return RetValue;
			});

			var LNode = Plugin.NewNode(new ObjectInitNode(Refs.ToArray(), Nodes.ToArray(), Code));
			if (LNode == null) return false;

			Node.LinkedNodes.Add(new LinkedExprNode(LNode, LinkedNodeFlags.NotRemovable));
			return Result;
		}

		public int GetOnlyDimensions(CodeString Code)
		{
			var Ret = 1;
			for (var i = 0; i < Code.Length; i++)
			{
				var Char = Code[i];
				if (!char.IsWhiteSpace(Char) && Char != ',') return -1;
				else if (Char == ',') Ret++;
			}

			return Ret;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			if (Code.StartsWith("new", new IdCharCheck(true)))
			{
				var State = Plugin.State;
				var Container = Plugin.Container;
				var Global = State.GlobalContainer;

				var EndingResult = State.Language.CommandInnerSeparator.Separate
					(State, Code, CommandInnerSeparatorFlags.InnerIsOptional);

				if (!EndingResult.Command.IsValid) return ExprRecResult.Failed;

				var SubCode = EndingResult.Command.Substring(3).Trim();
				var LChar = SubCode.Length == 0 ? '\0' : SubCode[SubCode.Length - 1];

				var Ch = (ExpressionNode[])null;
				var Op = Operator.Unknown;
				var StrParams = new CodeString();
				var DimensionCount = -1;
				var DimensionsSpecified = true;

				if (LChar == ']' || LChar == ')')
				{
					if (LChar == ']') Op = Operator.NewArray;
					else if (LChar == ')') Op = Operator.NewObject;
					else throw new ApplicationException();

					var ZPos = SubCode.GetBracketPos(State, Back: true);
					if (ZPos == -1) return ExprRecResult.Failed;

					StrParams = SubCode.Substring(ZPos + 1, SubCode.Length - ZPos - 2).Trim();
					SubCode = SubCode.Substring(0, ZPos).Trim();

					DimensionCount = GetOnlyDimensions(StrParams);
					if (Op == Operator.NewArray && DimensionCount != -1)
					{
						DimensionsSpecified = false;
						Ch = new ExpressionNode[DimensionCount + 1];
					}
					else
					{
						Ch = CallRecognizer.ProcessParameters(Plugin, new CodeString(), StrParams);
						if (Ch == null) return ExprRecResult.Failed;
					}

					if (SubCode.Length == 0)
					{
						var Auto = Container.GlobalContainer.CommonIds.Auto;
						Ch[0] = Plugin.NewNode(new IdExpressionNode(Auto, Code));
						if (Ch[0] == null) return ExprRecResult.Failed;
					}
					else
					{
						Ch[0] = Plugin.NewNode(new StrExpressionNode(SubCode));
						if (Ch[0] == null) return ExprRecResult.Failed;
					}
				}
				else if (SubCode.Length == 0)
				{
					if (!EnableWithoutBracket)
					{
						State.Messages.Add(MessageId.DeficientExpr, Code);
						return ExprRecResult.Failed;
					}

					var Auto = Container.GlobalContainer.CommonIds.Auto;
					Op = Operator.NewObject;

					Ch = new ExpressionNode[1];
					Ch[0] = Plugin.NewNode(new IdExpressionNode(Auto, Code));
					if (Ch[0] == null) return ExprRecResult.Failed;
				}
				else
				{
					if (!EnableWithoutBracket)
					{
						State.Messages.Add(MessageId.NotExpected, SubCode);
						return ExprRecResult.Failed;
					}

					Op = Operator.NewObject;
					Ch = new ExpressionNode[1];
					Ch[0] = Plugin.NewNode(new StrExpressionNode(SubCode));
					if (Ch[0] == null) return ExprRecResult.Failed;
				}

				Ret = new OpExpressionNode(Op, Ch, Code);

				if (EndingResult.Inner.IsValid)
				{
					if (Op == Operator.NewArray)
					{
						var Groups = GetGroups(Plugin, EndingResult.Inner, Ch.Length - 1);
						if (Groups == null) return ExprRecResult.Failed;

						if (DimensionsSpecified)
						{
							if (!CheckGroups_DimensionsSpecified(Plugin, Groups, Ch, Code))
								return ExprRecResult.Failed;
						}
						else
						{
							if (!CheckGroups_DimensionsNotSpecified(Plugin, Groups, Ch, Code, DimensionCount))
								return ExprRecResult.Failed;
						}

						if (!CreateInitValue_ForArray(Plugin, Groups, Ret, Code))
							return ExprRecResult.Failed;
					}
					else if (Op == Operator.NewObject)
					{
						if (!CreateInitValue_ForObject(Plugin, Ret, EndingResult.Inner))
							return ExprRecResult.Failed;
					}
					else
					{
						throw new ApplicationException();
					}
				}
				else if (Op == Operator.NewArray && !DimensionsSpecified)
				{
					State.Messages.Add(MessageId.ArrayLengthNotSpecified, StrParams);
					return ExprRecResult.Failed;
				}

				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class NewRecognizer : LanguageNode, IExprRecognizer
	{
		public CallRecognizer CallRecognizer;

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

        public override void Init(LanguageInitData InitData)
		{
            CallRecognizer = Language.Root.GetObject<CallRecognizer>();
			base.Init(InitData);
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			if (Code.StartsWith("new", new IdCharCheck(true)))
			{
				var State = Plugin.State;
				var Container = Plugin.Container;

				var SubCode = Code.TrimmedSubstring(State, 3);
				if (!SubCode.IsValid) return ExprRecResult.Failed;

				var Len = SubCode.Length;
				var LChar = SubCode[Len - 1];

				var Ch = (ExpressionNode[])null;
				var Op = Operator.Unknown;
				if (LChar == ']' || LChar == ')')
				{
					if (LChar == ']') Op = Operator.NewArray;
					else if (LChar == ')') Op = Operator.NewObject;
					else throw new ApplicationException();

					var ZPos = SubCode.GetBracketPos(State, Back: true);
					if (ZPos == -1) return ExprRecResult.Failed;

					var StrParams = SubCode.Substring(ZPos + 1, Len - ZPos - 2).Trim();
					SubCode = SubCode.Substring(0, ZPos).Trim();

					Ch = CallRecognizer.ProcessParameters(Plugin, SubCode, StrParams);
					if (Ch == null) return ExprRecResult.Failed;
				}
				else
				{
					Ch = new ExpressionNode[] { Plugin.NewNode(new StrExpressionNode(SubCode)) };
					if (Ch[0] == null) return ExprRecResult.Failed;

					Op = Operator.NewObject;
				}

				Ret = new OpExpressionNode(Op, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class IfThenRecognizer : LanguageNode, IExprRecognizer
	{
		public string[] ThenStrs = new string[] { ":", "then" };
		public string[] ElseStrs = new string[] { "else" };

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

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			if (Code.StartsWith("if", new IdCharCheck(true)))
			{
				var State = Plugin.State;
				var Container = Plugin.Container;
				var SkippingHandler = State.Language.GlobalHandlers;

				FindResult Result;
				var SCode = Code.Substring(2);
				if (!SCode.IsValid || (Result = SCode.Find(ThenStrs, IdCharCheck: new IdCharCheck(true), Handlers: SkippingHandler)).Position == -1)
				{
					State.Messages.Add(MessageId.NeedThenElse, Code);
					return ExprRecResult.Failed;
				}

				var ConditionStr = SCode.TrimmedSubstring(State, 0, Result.Position);
				SCode = SCode.Substring(Result.NextChar);

				if (!SCode.IsValid || (Result = SCode.Find(ElseStrs, Handlers: SkippingHandler, IdCharCheck: new IdCharCheck(true))).Position == -1)
				{
					State.Messages.Add(MessageId.NeedThenElse, Code);
					return ExprRecResult.Failed;
				}

				var ThenStr = SCode.TrimmedSubstring(State, 0, Result.Position);
				var ElseStr = SCode.TrimmedSubstring(State, Result.NextChar);
				if (!ThenStr.IsValid || !ElseStr.IsValid || !ConditionStr.IsValid)
					return ExprRecResult.Failed;

				var Condition = Expressions.Recognize(ConditionStr, Plugin, true);
				var Then = Expressions.Recognize(ThenStr, Plugin, true);
				var Else = Expressions.Recognize(ElseStr, Plugin, true);

				if (Condition == null || Then == null || Else == null)
					return ExprRecResult.Failed;

				var Ch = new ExpressionNode[] {Condition, Then, Else };
				Ret = new OpExpressionNode(Operator.Condition, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class ConditionRecognizer : LanguageNode, IExprRecognizer
	{
		public ConditionRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { "?", ":" };
			NewLineLeft = NewLineRight = Operators;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			var State = Plugin.State;
			var SkippingHandler = State.Language.GlobalHandlers;

			var Depth = 0;
			var Begin = new FindResult(-1, -1, null);
			var End = new FindResult(-1, -1, null);
			foreach (var e in Code.EnumFind(Operators, Skip, Handlers: SkippingHandler))
			{
				if (e.Index == 0)
				{
					if (Depth == 0) Begin = e;
					Depth++;
				}
				else if (e.Index == 1)
				{
					Depth--;
					if (Depth == 0) End = e;
				}
				else
				{
					throw new ApplicationException();
				}
			}

			if (Begin.Position != -1 && Begin.Index == 0 && End.Position != -1 && End.Index == 1)
			{
				var Left_Str = Code.TrimmedSubstring(State, 0, Begin.Position);
				var MidPos = Begin.Position + Begin.String.Length;
				var Mid_Str = Code.TrimmedSubstring(State, MidPos, End.Position - MidPos);
				var Right_Str = Code.TrimmedSubstring(State, End.Position + End.String.Length);

				if (!Left_Str.IsValid || !Mid_Str.IsValid || !Right_Str.IsValid)
					return ExprRecResult.Failed;

				var Left = Expressions.Recognize(Left_Str, Plugin, true);
				var Mid = Expressions.Recognize(Mid_Str, Plugin, true);
				var Right = Expressions.Recognize(Right_Str, Plugin, true);
				if (Left == null || Mid == null || Right == null)
					return ExprRecResult.Failed;

				var Ch = new ExpressionNode[] { Left, Mid, Right };
				Ret = new OpExpressionNode(Operator.Condition, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class AssignmentRecognizer : LanguageNode, IExprRecognizer
	{
		public AssignmentRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "|=", "&=", "^=", "=" };
			NewLineLeft = NewLineRight = Operators;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			var State = Plugin.State;
			var Result = RecognizerHelper.Find(this, State, Code.String);
			if (Result.Position != -1)
			{
				var Ch = RecognizerHelper.GetLeftRightNode(Code, Result, Plugin);
				if (Ch == null) return ExprRecResult.Failed;

				var Op = Operator.Unknown;
				switch (Result.Index)
				{
					case 0: Op = Operator.Add; break;
					case 1: Op = Operator.Subract; break;
					case 2: Op = Operator.Multiply; break;
					case 3: Op = Operator.Divide; break;
					case 4: Op = Operator.Modolus; break;
					case 5: Op = Operator.ShiftLeft; break;
					case 6: Op = Operator.ShiftRight; break;
					case 7: Op = Operator.BitwiseOr; break;
					case 8: Op = Operator.BitwiseAnd; break;
					case 9: Op = Operator.BitwiseXor; break;

					case 10:
						Ret = new OpExpressionNode(Operator.Assignment, Ch, Code);
						break;

					default:
						throw new ApplicationException();
				}

				if (Op != Operator.Unknown)
				{
					var LinkedNode = new LinkedExprNode(Ch[0]);
					Ch[0] = Plugin.NewNode(new LinkingNode(LinkedNode, Code));
					if (Ch[0] == null) return ExprRecResult.Failed;

					Ret = Plugin.NewNode(new OpExpressionNode(Op, Ch, Code));
					var Dst = Plugin.NewNode(new LinkingNode(LinkedNode, Code));
					if (Ret == null || Dst == null) return ExprRecResult.Failed;

					Ch = new ExpressionNode[] { Dst, Ret };
					Ret = new OpExpressionNode(Operator.Assignment, Ch, Code);
					Ret.LinkedNodes.Add(LinkedNode);
				}

				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class TupleCreatingRecognizer : LanguageNode, IExprRecognizer
	{
		public TupleCreatingRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			var SkippingHandler = Plugin.State.Language.GlobalHandlers;
			if (Code.Find(',', Handlers: SkippingHandler) != -1)
			{
				var Splitted = RecognizerHelper.SplitToParameters(Plugin.State, Code, ',');
				if (Splitted == null) return ExprRecResult.Failed;

				var Members = Expressions.Recognize(Splitted, Plugin);
				if (Members == null) return ExprRecResult.Failed;
				
				Ret = new OpExpressionNode(Operator.Tuple, Members, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

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

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			if (Code.Length > 1 && Code[0] == '[' && Code[Code.Length - 1] == ']')
			{
				var SubStr = Code.TrimmedSubstring(Plugin.State, 1, Code.Length - 2);
				if (!SubStr.IsValid) return ExprRecResult.Failed;

				var Groups = Expressions.GetGroups(Plugin, SubStr);
				if (Groups == null) return ExprRecResult.Failed;

				var Nodes = Groups.GetNodes().ToArray();
				Ret = new OpExpressionNode(Operator.Array, Nodes, Code);
				Ret.Data.Set(Groups);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class LogicalRecognizer : LanguageNode, IExprRecognizer
	{
		public LogicalRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			this.Operators = new string[] { "and", "xor", "or" };
			NewLineLeft = NewLineRight = Operators;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			for (var i = 0; i < Operators.Length; i++)
			{
				var Pos = Code.Find(Operators[i], Skip, true, new IdCharCheck(true), SkippingHandlers);
				var Result = new FindResult(i, Pos, Operators[i]);

				if (Result.Position != -1)
				{
					var Ch = RecognizerHelper.GetLeftRightNode(Code, Result, Plugin);
					if (Ch == null) return ExprRecResult.Failed;

					Operator Op;
					if (Result.Index == 0) Op = Operator.And;
					else if (Result.Index == 1) Op = Operator.Inequality;
					else if (Result.Index == 2) Op = Operator.Or;
					else throw new ApplicationException();

					Ret = new OpExpressionNode(Op, Ch, Code);
					return ExprRecResult.Succeeded;
				}
			}

			return ExprRecResult.Unknown;
		}
	}

	public class RefEqualityRecognizer : LanguageNode, IExprRecognizer
	{
		public RefEqualityRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { "===", "!==" };
			NewLineLeft = NewLineRight = Operators;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			var Result = RecognizerHelper.Find(this, Plugin.State, Code.String);
			if (Result.Position != -1)
			{
				var Ch = RecognizerHelper.GetLeftRightNode(Code, Result, Plugin);
				if (Ch == null) return ExprRecResult.Failed;

				Operator Op;
				if (Result.Index == 0) Op = Operator.RefEquality;
				else if (Result.Index == 1) Op = Operator.RefInequality;
				else throw new ApplicationException();

				Ret = new OpExpressionNode(Op, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

    [Flags]
    public enum RelEquRecognizerFlags : byte
    {
        None = 0,
        DisableOpposed = 1,
    }

	public class RelEquRecognizer : LanguageNode, IExprRecognizer
	{
        public RelEquRecognizerFlags RecFlags;

		public RelEquRecognizer(LanguageNode Parent, RelEquRecognizerFlags Flags)
			: base(Parent)
		{
			Operators = new string[] { "==", "!=", "<=", "<", ">=", ">" };
			NewLineLeft = NewLineRight = Operators;
            this.RecFlags = Flags;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Out)
		{
			var Results = Code.EnumFind(Operators, Skip: Skip, Handlers: SkippingHandlers).ToList();

            if ((RecFlags & RelEquRecognizerFlags.DisableOpposed) != 0)
			{
				for (var i = 0; i < Results.Count; i++)
				{
					if (Results[i].String[0] == '<')
					{
						var Right = Code.Substring(Results[i].Position);
						if (Right.GetBracketPos(false, SkippingHandlers) != -1)
						{
							Results.RemoveAt(i);
							i--;
						}
					}
					else if (Results[i].String[0] == '>')
					{
						var Left = Code.Substring(0, Results[i].Position + 1);
						if (Left.GetBracketPos(true, SkippingHandlers) != -1)
						{
							Results.RemoveAt(i);
							i--;
						}
					}
				}
			}

			if (Results.Count == 0) 
				return ExprRecResult.Unknown;

			var ChNodes = new List<ExpressionNode>(Results.Count + 1);
			for (var i = 0; i <= Results.Count; i++)
			{
				int Start, Length;
				if (i < Results.Count)
				{
					if (i == 0)
					{
						Start = 0;
						Length = Results[i].Position;
					}
					else
					{
						var PrevRes = Results[i - 1];
						Start = PrevRes.Position + PrevRes.String.Length;
						Length = Results[i].Position - Start;
					}
				}
				else
				{
					var PrevRes = Results[i - 1];
					Start = PrevRes.Position + PrevRes.String.Length;
					Length = Code.Length - Start;
				}

				var PStr = Code.TrimmedSubstring(Plugin.State, Start, Length);
				if (!PStr.IsValid) return ExprRecResult.Failed;

				var Node = Expressions.Recognize(PStr, Plugin, true);
				if (Node == null) return ExprRecResult.Failed;
				ChNodes.Add(Node);
			}

			var ResOperators = new List<Operator>(Results.Count);
			for (var i = 0; i < Results.Count; i++)
			{
				var Result = Results[i];
				Operator Op;

				switch (Result.Index)
				{
					case 0: Op = Operator.Equality; break;
					case 1: Op = Operator.Inequality; break;
					case 2: Op = Operator.LessEqual; break;
					case 3: Op = Operator.Less; break;
					case 4: Op = Operator.GreaterEqual; break;
					case 5: Op = Operator.Greater; break;
					default: throw new ApplicationException();
				}

				ResOperators.Add(Op);
			}

			Out = Expressions.ChainedRelation(Plugin, ChNodes, ResOperators, Code);
			return Out == null ? ExprRecResult.Failed : ExprRecResult.Ready;
		}
	}

	public class AdditiveRecognizer : LanguageNode, IExprRecognizer
	{
		public AdditiveRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { "+", "-" };
			NewLineLeft = NewLineRight = Operators;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			var Result = RecognizerHelper.Find2(this, Plugin.Container, Code.String);
			if (Result.Position != -1)
			{
				var Ch = RecognizerHelper.GetLeftRightNode(Code, Result, Plugin);
				if (Ch == null) return ExprRecResult.Failed;

				Operator Op;
				if (Result.Index == 0) Op = Operator.Add;
				else if (Result.Index == 1) Op = Operator.Subract;
				else throw new ApplicationException();

				Ret = new OpExpressionNode(Op, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class MultiplicativeRecognizer : LanguageNode, IExprRecognizer
	{
		public MultiplicativeRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { "*", "/", "%" };
			NewLineLeft = NewLineRight = Operators;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			var Result = RecognizerHelper.Find2(this, Plugin.Container, Code.String);
			if (Result.Position != -1)
			{
				var Ch = RecognizerHelper.GetLeftRightNode(Code, Result, Plugin);
				if (Ch == null) return ExprRecResult.Failed;

				Operator Op;
				if (Result.Index == 0) Op = Operator.Multiply;
				else if (Result.Index == 1) Op = Operator.Divide;
				else if (Result.Index == 2) Op = Operator.Modolus;
				else throw new ApplicationException();

				Ret = new OpExpressionNode(Op, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class ShiftRecognizer : LanguageNode, IExprRecognizer
	{
		public ShiftRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { "<<", ">>" };
			NewLineLeft = NewLineRight = Operators;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			var Result = RecognizerHelper.Find2(this, Plugin.Container, Code.String);
			if (Result.Position != -1)
			{
				var Ch = RecognizerHelper.GetLeftRightNode(Code, Result, Plugin);
				if (Ch == null) return ExprRecResult.Failed;

				Operator Op;
				if (Result.Index == 0) Op = Operator.ShiftLeft;
				else if (Result.Index == 1) Op = Operator.ShiftRight;
				else throw new ApplicationException();

				Ret = new OpExpressionNode(Op, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class BitwiseRecognizer : LanguageNode, IExprRecognizer
	{
		public BitwiseRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { "&", "|", "^" };
			NewLineLeft = NewLineRight = Operators;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			var Result = RecognizerHelper.Find2(this, Plugin.Container, Code.String);
			if (Result.Position != -1)
			{
				var Ch = RecognizerHelper.GetLeftRightNode(Code, Result, Plugin);
				if (Ch == null) return ExprRecResult.Failed;

				Operator Op;
				if (Result.Index == 0) Op = Operator.BitwiseAnd;
				else if (Result.Index == 1) Op = Operator.BitwiseOr;
				else if (Result.Index == 2) Op = Operator.BitwiseXor;
				else throw new ApplicationException();

				Ret = new OpExpressionNode(Op, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class NegateRecognizer : LanguageNode, IExprRecognizer
	{
		public NegateRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			NewLineRight = Operators = new string[] { "-", "+" };
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			if (Code.Length > 0 && Code[0] == '-')
			{
				Ret = RecognizerHelper.OneParamOpNode(Code, Plugin, Operator.Negation);
				return Ret == null ? ExprRecResult.Failed : ExprRecResult.Succeeded;
			}
			else if (Code.Length > 0 && Code[0] == '+')
			{
				Ret = RecognizerHelper.OneParamOpNode(Code, Plugin, Operator.UnaryPlus);
				return Ret == null ? ExprRecResult.Failed : ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class NotRecognizer : LanguageNode, IExprRecognizer
	{
		public NotRecognizer(LanguageNode Parent)
			: base(Parent)
		{
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			if (Code.StartsWith("not", new IdCharCheck(true)))
			{
				var SubStr = Code.TrimmedSubstring(Plugin.State, 3);
				if (SubStr.Length == 0) return ExprRecResult.Failed;

				Ret = Expressions.Recognize(SubStr, Plugin, true);
				if (Ret == null) return ExprRecResult.Failed;

				var RetCh = new ExpressionNode[] { Ret };
				Ret = new OpExpressionNode(Operator.Not, RetCh, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class CNotRecognizer : LanguageNode, IExprRecognizer
	{
		public CNotRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			NewLineRight = Operators = new string[] { "!" };
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			if (Code.StartsWith(Operators, Skip).Position != -1)
			{
				var SubStr = Code.TrimmedSubstring(Plugin.State, 1);
				if (SubStr.Length == 0) return ExprRecResult.Failed;

				Ret = Expressions.Recognize(SubStr, Plugin, true);
				if (Ret == null) return ExprRecResult.Failed;

				var RetCh = new ExpressionNode[] { Ret };
				Ret = new OpExpressionNode(Operator.Not, RetCh, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class AddressRecognizer : LanguageNode, IExprRecognizer
	{
		public AddressRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			NewLineRight = Operators = new string[] { "&" };
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			if (Code.Length > 0 && Code[0] == '&')
			{
				Ret = RecognizerHelper.OneParamOpNode(Code, Plugin, Operator.Address);
				if (Ret == null) return ExprRecResult.Failed;
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class ComplementRecognizer : LanguageNode, IExprRecognizer
	{
		public ComplementRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			NewLineRight = Operators = new string[] { "~" };
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			if (Code.Length > 0 && Code[0] == '~')
			{
				Ret = RecognizerHelper.OneParamOpNode(Code, Plugin, Operator.Complement);
				return Ret == null ? ExprRecResult.Failed : ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class IncDecRecognizer : LanguageNode, IExprRecognizer
	{
		public IncDecRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			NewLineLeft = Operators = new string[] { "++", "--" };
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			Operator Op;
			if (Code.EndsWith("++")) Op = Operator.Increase;
			else if (Code.EndsWith("--")) Op = Operator.Decrease;
			else return ExprRecResult.Unknown;
			
			var ChildStr = Code.TrimmedSubstring(Plugin.State, 0, Code.Length - 2);
			if (!ChildStr.IsValid) return ExprRecResult.Failed;

			var Child = Expressions.Recognize(ChildStr, Plugin, true);
			if (Child == null) return ExprRecResult.Failed;

			var Children = new ExpressionNode[] { Child };
			Ret = new OpExpressionNode(Op, Children, Code);
			return ExprRecResult.Succeeded;
		}
	}

	public class IndirectionRecognizer : LanguageNode, IExprRecognizer
	{
		public IndirectionRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			NewLineRight = Operators = new string[] { "*" };
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			if (Code.Length > 0 && Code[0] == '*')
			{
				var PtrCode = Code.TrimmedSubstring(Plugin.State, 1);
				if (!PtrCode.IsValid) return ExprRecResult.Failed;

				var PtrNode = Expressions.Recognize(PtrCode, Plugin, true);
				if (PtrNode == null) return ExprRecResult.Failed;

				Ret = Expressions.Indirection(Plugin, PtrNode, Code);
				return Ret == null ? ExprRecResult.Failed : ExprRecResult.Ready;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class CallRecognizer : LanguageNode, IExprRecognizer, ICallParamRecognizer
	{
		public List<IBuiltinFuncRecognizer> Recognizers;

		public CallRecognizer(LanguageNode Parent, List<IBuiltinFuncRecognizer> Recognizers)
			: base(Parent)
		{
			this.Recognizers = Recognizers;
			Operators = NewLineRight = new string[] { "(" };
			NewLineLeft = new string[] {  "(", ")" };
		}

		public ExpressionNode[] ProcessParameters(PluginRoot Plugin, CodeString Function, CodeString Parameters)
		{
			var ParamList = RecognizerHelper.GetParamList(Plugin.State, Parameters);
			if (ParamList == null) return null;

			return ProcessParameters(Plugin, Function, ParamList);
		}

		public ExpressionNode[] ProcessParameters(PluginRoot Plugin, CodeString Function, CodeString[] Parameters)
		{
			var RetValue = true;
			var Nodes = new ExpressionNode[Parameters.Length + 1];

			if (Function.IsValid)
			{
				Nodes[0] = Expressions.Recognize(Function, Plugin);
				if (Nodes[0] == null) RetValue = false;
			}

			for (var i = 0; i < Parameters.Length; i++)
			{
				var NamePos = Parameters[i].Find(':', false, SkippingHandlers);
				if (NamePos != -1)
				{
					var Name = Parameters[i].Substring(0, NamePos).Trim();
					var Value = Parameters[i].Substring(NamePos + 1).Trim();

					if (Name.IsValidIdentifierName)
					{
						var Node = Expressions.Recognize(Value, Plugin);
						if (Node == null) { RetValue = false; continue; }

						Nodes[i + 1] = Plugin.NewNode(new NamedParameterNode(Parameters[i], Node, Name));
						if (Nodes[i + 1] == null) { RetValue = false; continue; }
					}
				}

				Nodes[i + 1] = Expressions.Recognize(Parameters[i], Plugin);
				if (Nodes[i + 1] == null) { RetValue = false; continue; }
			}

			return RetValue ? Nodes : null;
		}

		public bool GetParameters(CompilerState State, CodeString Code, out CodeString Function, out CodeString Parameters)
		{
			if (Code.Length > 0 && Code[Code.Length - 1] == ')')
			{
				Function = Code;
				Parameters = RecognizerHelper.ExtractBracket(State, Code, ')', ref Function, true);
				return Parameters.IsValid && Parameters.VerifyNotEmpty(State, Code);
			}
			else
			{
				Function = new CodeString();
				Parameters = new CodeString();

				State.Messages.Add(MessageId.NotExpected, Code);
				return false;
			}
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			if (Code.Length > 0 && Code[Code.Length - 1] == ')')
			{
				var State = Plugin.State;

				var Called = Code;
				var ParamStr = RecognizerHelper.ExtractBracket(State, Code, ')', ref Called, true);
				if (!ParamStr.IsValid || !Called.VerifyNotEmpty(State, Code)) 
					return ExprRecResult.Failed;

				var ParamList = RecognizerHelper.GetParamList(State, ParamStr);
				if (ParamList == null) return ExprRecResult.Failed;

				CodeString[] GenericParams;
				var GenericRec = State.Language.GenericRecognizer;
				var GRes = GenericRec.GetGenericParams(State, ref Called, out GenericParams);
				if (GRes == SimpleRecResult.Failed) return ExprRecResult.Failed;

				if (Recognizers != null)
				{
					var ParamArray = ParamList.ToArray();
					for (var i = 0; i < Recognizers.Count; i++)
					{
						var Res = Recognizers[i].Recognize(Code, Called, 
							ParamArray, GenericParams, Plugin, ref Ret);

						if (Res != ExprRecResult.Unknown) return Res;
					}
				}

				var Nodes = ProcessParameters(Plugin, Called, ParamList);
				if (Nodes == null) return ExprRecResult.Failed;

				Ret = new OpExpressionNode(Operator.Call, Nodes, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class IndexRecognizer : LanguageNode, IExprRecognizer
	{
		public IndexRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = NewLineRight = new string[] { "[" };
			NewLineLeft = new string[] { "[" , "]" };
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			if (Code.Length > 0 && Code[Code.Length - 1] == ']')
			{
				var State = Plugin.State;

				var ArrayStr = Code;
				var ParamStr = RecognizerHelper.ExtractBracket(State, Code, ']', ref ArrayStr, true);
				if (!ParamStr.IsValid || !ArrayStr.VerifyNotEmpty(State, Code))
					return ExprRecResult.Failed;

				var ParamList = RecognizerHelper.GetParamList(State, ParamStr);
				if (ParamList == null) return ExprRecResult.Failed;

				var ParamNodes = Expressions.Recognize(ParamList, Plugin);
				var ArrayNode = Expressions.Recognize(ArrayStr, Plugin);
				if (ParamNodes == null || ArrayNode == null) return ExprRecResult.Failed;

				var Ch = new ExpressionNode[ParamNodes.Length + 1];
				Ch[0] = ArrayNode;
				ParamNodes.CopyTo(Ch, 1);

				Ret = new OpExpressionNode(Operator.Index, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class NullCoalescingRecognizer : LanguageNode, IExprRecognizer
	{
		public NullCoalescingRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { "??" };
			NewLineLeft = NewLineRight = Operators;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			var Container = Plugin.Container;
			var Result = RecognizerHelper.Find2(this, Plugin.Container, Code.String);
			if (Result.Position != -1)
			{
				var State = Plugin.State;
				var GlobalContainer = Container.GlobalContainer;

				var LeftRight = RecognizerHelper.GetLeftRightNode(Code, Result, Plugin);
				if (LeftRight == null) return ExprRecResult.Failed;
				var Linked = new LinkedExprNode(LeftRight[0]);

				var Null = Plugin.NewNode(Constants.GetNullValue(Plugin.Container, Code));
				var RelLnk = Plugin.NewNode(new LinkingNode(Linked, Code));
				if (RelLnk == null || Null == null) return ExprRecResult.Failed;

				var RelCh = new ExpressionNode[] {RelLnk, Null };
				var Rel = Plugin.NewNode(new OpExpressionNode(Operator.Inequality, RelCh, Code));
				if (Rel == null) return ExprRecResult.Failed;

				var RetLnk = Plugin.NewNode(new LinkingNode(Linked, Code));
				if (RetLnk == null) return ExprRecResult.Failed;
				var RetCh = new ExpressionNode[] {Rel, RetLnk, LeftRight[1] };
				Ret = new OpExpressionNode(Operator.Condition, RetCh, Code);
				Ret.LinkedNodes = new List<LinkedExprNode>() { Linked };
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class SafeNavigationRecognizer : LanguageNode, IExprRecognizer
	{
		public SafeNavigationRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { "?.", "?->" };
			NewLineLeft = NewLineRight = Operators;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			var Container = Plugin.Container;
			var Result = RecognizerHelper.Find2(this, Plugin.Container, Code.String);
			if (Result.Position != -1)
			{
				var State = Plugin.State;
				var GlobalContainer = Container.GlobalContainer;

				var Left_Str = Code.TrimmedSubstring(State, 0, Result.Position);
				var Right_Str = Code.TrimmedSubstring(State, Result.NextChar);
				if (!Left_Str.IsValid || !Right_Str.IsValid) return ExprRecResult.Failed;

				var Left = Expressions.Recognize(Left_Str, Plugin, true);
				if (Left == null) return ExprRecResult.Failed;
				var Linked = new LinkedExprNode(Left);

				//--------------------------------------------------------------------------------------
				var Null = Plugin.NewNode(Constants.GetNullValue(Container, Code));
				if (Null == null) return ExprRecResult.Failed;
				var RelLnk = Plugin.NewNode(new LinkingNode(Linked, Code));
				if (RelLnk == null) return ExprRecResult.Failed;

				var RelCh = new ExpressionNode[] {RelLnk, Null };
				var Rel = Plugin.NewNode(new OpExpressionNode(Operator.Inequality, RelCh, Code));
				if (Rel == null) return ExprRecResult.Failed;

				//--------------------------------------------------------------------------------------
				var ThenSrc = Plugin.NewNode(new LinkingNode(Linked, Code));
				if (ThenSrc == null) return ExprRecResult.Failed;

				if (Result.Index == 1)
				{
					ThenSrc = Expressions.Indirection(Plugin, ThenSrc, Code);
					if (ThenSrc == null) return ExprRecResult.Failed;
				}

				var MemberNode = Plugin.NewNode(new StrExpressionNode(Right_Str));
				if (MemberNode == null) return ExprRecResult.Failed;
				var ThenCh = new ExpressionNode[] {ThenSrc, MemberNode };
				var Then = Plugin.NewNode(new OpExpressionNode(Operator.Member, ThenCh, Code));
				if (Then == null) return ExprRecResult.Failed;

				//--------------------------------------------------------------------------------------
				var Else = Plugin.NewNode(Constants.GetNullValue(Container, Code));
				if (Else == null) return ExprRecResult.Failed;
				var RetCh = new ExpressionNode[] {Rel, Then, Else };
				Ret = new OpExpressionNode(Operator.Condition, RetCh, Code);
				Ret.LinkedNodes = new List<LinkedExprNode>() { Linked };
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

    [Flags]
    public enum MemberRecognizerFlags : byte
    {
        None = 0,
        AllowScopeResolution = 1,
    }

	public class MemberRecognizer : LanguageNode, IExprRecognizer
	{
		public MemberRecognizer(LanguageNode Parent, MemberRecognizerFlags Flags = MemberRecognizerFlags.None)
			: base(Parent)
		{
			if ((Flags & MemberRecognizerFlags.AllowScopeResolution) != 0)
                Operators = new string[] { ".", "->", "::" };
            else Operators = new string[] { ".", "->" };

			NewLineLeft = NewLineRight = Operators;
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			var Container = Plugin.Container;
			var Result = RecognizerHelper.Find2(this, Plugin.Container, Code.String);
			if (Result.Position == -1) return ExprRecResult.Unknown;

			var RightStr = Code.Substring(Result.NextChar).Trim();
			if (RightStr.IsValidIdentifierName || RightStr.IsNumber)
			{
				var State = Plugin.State;
				var LeftStr = Code.TrimmedSubstring(State, 0, Result.Position);
				if (!LeftStr.IsValid) return ExprRecResult.Failed;

                var Op = Operator.Member;
				var Left = Expressions.Recognize(LeftStr, Plugin, true);
				if (Left == null) return ExprRecResult.Failed;

                if (Result.Index == 2)
                {
                    Op = Operator.ScopeResolution;
                }
                else
                {
                    Op = Operator.Member;
                    if (Result.Index == 1)
                    {
                        Left = Expressions.Indirection(Plugin, Left, Code);
                        if (Left == null) return ExprRecResult.Failed;
                    }
                }

				var Right = Plugin.NewNode(new StrExpressionNode(RightStr));
				if (Right == null) return ExprRecResult.Failed;
				
				var Ch = new ExpressionNode[] { Left, Right };
                Ret = new OpExpressionNode(Op, Ch, Code);
				return ExprRecResult.Succeeded;
			}

			return ExprRecResult.Unknown;
		}
	}

	public class ExprVarDeclRecognizer : LanguageNode, IExprRecognizer
	{
		public ExprVarDeclRecognizer(LanguageNode Parent)
			: base(Parent)
		{
			Operators = new string[] { " ", "\t", "\r", "\n" };
		}

		public ExprRecResult Recognize(CodeString Code, PluginRoot Plugin, ref ExpressionNode Ret)
		{
			var Result = RecognizerHelper.Find(this, Plugin.State, Code.String);
			if (Result.Position != -1)
			{
				var VarName = Code.Substring(Result.Position).Trim();
				if (!VarName.IsValidIdentifierName) return ExprRecResult.Unknown;

				var Container = Plugin.Container;
				var State = Plugin.State;

				var TypeName = Code.Substring(0, Result.Position).Trim();
				Ret = Plugin.DeclareVarAndCreateIdNode(Code, TypeName, VarName);
				if (Ret == null) return ExprRecResult.Failed;
				else return ExprRecResult.Ready;
			}

			return ExprRecResult.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)

Share

About the Author

Dávid Kocsis
Student
Hungary Hungary
I've been programming for 8 years. My first big project was a remake of a nice bomberman game called Dyna Blaster. When i was little i played a lot with it. Now i'm working on a new programming language and code generator.
I would like to work with someone, so feel free to contact me about it.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.141223.1 | Last Updated 1 Jan 2013
Article Copyright 2011 by Dávid Kocsis
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid