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;

namespace Anonymus.Recognizers
{
	public class SimpleArgRecognizer : ArgRecognizer
	{
		public SimpleArgRecognizer()
		{
			Operators = new string[] { "," };
			NewLineLeft = NewLineRight = Operators;
			Init();
		}

		public override bool SplitArgs(CompilerState State, PString Self, List<PString> Ret, bool EnableMessages = true)
		{
			var RetValue = true;
			var Sep = (PString)null;
			foreach (var e in Self.EnumSplit(",", StringSplitOptions.RemoveEmptyEntries, true, true))
			{
				if (e.IsSeparator)
				{
					if (Sep != null)
					{
						if (EnableMessages) State.Messages.Add(MessageId.MissingParam, Sep);
						RetValue = false;
					}

					Sep = e.String;
				}
				else
				{
					Ret.Add(e.String);
					Sep = null;
				}
			}

			if (Sep != null)
			{
				if (EnableMessages) State.Messages.Add(MessageId.MissingParam, Sep);
				RetValue = false;
			}

			return RetValue;
		}
	}

	public abstract class MultiExprRecognizer : ExprRecognizer
	{
		public List<ExprRecognizer> Recognizers = new List<ExprRecognizer>();

		public override void Init()
		{
			var AllOperators = new List<string>();
			var AllNewLineLeft = new List<string>();
			var AllNewLineRight = new List<string>();
			var AllOnlyLeft = new List<string>();
			var AllOnlyRight = new List<string>();

			for (var i = 0; i < Recognizers.Count; i++)
			{
				var Rec = Recognizers[i];
				if (Rec.Operators != null)
				{
					var Skip = new List<string>();
					AllOperators.AddRange(Rec.Operators);

					for (var j = i + 1; j < Recognizers.Count; j++)
					{
						var jOps = Recognizers[j].Operators;
						if (jOps == null) continue;

						foreach (var e in jOps)
						{
							foreach (var Op in Rec.Operators)
								if (e.IndexOf(Op) != -1 && e != Op)
								{
									Skip.Add(e);
									break;
								}
						}
					}

					if (Skip.Count == 0) this.Skip = null;
					else Rec.Skip = Skip.ToArray();
				}

				if (Rec.NewLineLeft != null) AllNewLineLeft.AddRange(Rec.NewLineLeft);
				if (Rec.NewLineRight != null) AllNewLineRight.AddRange(Rec.NewLineRight);
				if (Rec.OnlyLeft != null) AllOnlyLeft.AddRange(Rec.OnlyLeft);
				if (Rec.OnlyRight != null) AllOnlyRight.AddRange(Rec.OnlyRight);
			}

			Operators = ToArray(AllOperators);
			NewLineLeft = ToArray(AllNewLineLeft);
			NewLineRight = ToArray(AllNewLineRight);
			OnlyLeft = ToArray(AllOnlyLeft);
			OnlyRight = ToArray(AllOnlyRight);
		}

		private T[] ToArray<T>(List<T> List) where T : class
		{
			Helper.RemoveSameObject(List);
			if (List.Count == 0) return null;
			else return List.ToArray();
		}

		public override T GetRecognizer<T>()
		{
			foreach (var e in Recognizers)
				if (e is T) return e as T;

			return base.GetRecognizer<T>();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			foreach (var e in Recognizers)
			{
				var Res = e.Recognize(Code, PlugIn, ref Ret);
				if (Res != ExprRecognizerRes.UnknownOp) return Res;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class LiteralRecognizer : ExprRecognizer
	{
		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			if (Expressions.IsLiteral(Code.String))
			{
				Ret = Expressions.GetLiteral(PlugIn, Code);
				if (Ret == null) return ExprRecognizerRes.Failed;
				return ExprRecognizerRes.Succeeded;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class IdRecognizer : ExprRecognizer
	{
		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			if (Helper.IsValidIdentifierName(Code.String))
			{
				Ret = Expressions.GetId(PlugIn, Code);
				if (Ret == null) return ExprRecognizerRes.Failed;
				return ExprRecognizerRes.DontCallNewNode;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class RefRecognizer : ExprRecognizer
	{
		public RefRecognizer()
		{
			NewLineRight = new string[] { "ref" };
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			if (Code.String.StartsWith("ref", true))
			{
				var SubCode = Code.TrimmedSubstring(3);
				var Child = Expressions.Recognize(SubCode, PlugIn, true);
				if (Child == null) return ExprRecognizerRes.Failed;

				var IdChild = Child as IdExpressionNode;
				if (Child.Type is TypeOfType && IdChild != null)
				{
					var Type = (IdChild.Id as Type).CreateRefType();
					Ret = new IdExpressionNode(Type, Code);
				}
				else
				{
					var Ch = new List<ExpressionNode>() { Child };
					Ret = new OpExpressionNode(Operator.Ref, Ch, Code);
				}

				return ExprRecognizerRes.Succeeded;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class NewRecognizer : ExprRecognizer
	{
		public NewRecognizer()
		{
			NewLineRight = new string[] { "new" };
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			if (Code.String.StartsWith("new", true))
			{
				var State = PlugIn.State;
				var Container = PlugIn.Container;

				var SubCode = Code.TrimmedSubstring(3);
				var Len = SubCode.StrLen;
				var LChar = SubCode[Len - 1];

				var Ch = new List<ExpressionNode>();
				if (LChar == ']' || LChar == ')')
				{
					var ZPos = BracketHelper.ZPos(SubCode.String, RightToLeft: true);
					if (ZPos == -1)
					{
						State.Messages.Add(MessageId.ZNumErr, SubCode.Substring(Len - 1));
						return ExprRecognizerRes.Failed;
					}

					var StrParams = SubCode.TrimmedSubstring(ZPos + 1, Len - ZPos - 1);
					SubCode = SubCode.TrimmedSubstring(0, ZPos);

					var Params = Expressions.CreateParamNodes(PlugIn, Code, null, StrParams);
					if (Params == null) return ExprRecognizerRes.Failed;
					Ch.AddRange(Params);
				}

				var Type = Container.GetId<Type>(SubCode);
				if (Type == null) return ExprRecognizerRes.Failed;
				Type = Type.RealType;

				if (!(Type is StructuredType))
				{
					State.Messages.Add(MessageId.CantOpApplied, Code, Type.Name.String);
					return ExprRecognizerRes.Failed;
				}

				var Structured = Type as StructuredType;
				var Id = Structured.Constructor;
				if (Id != null)
				{
					var IdNode = PlugIn.NewNode(new IdExpressionNode(Id, Code));
					if (IdNode == null) return ExprRecognizerRes.Failed;
					Ch.Insert(0, IdNode);
				}

				Ret = new OpExpressionNode(Operator.New, Ch, Code);
				Ret.Type = Type;
				return ExprRecognizerRes.Succeeded;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class IfThenRecognizer : ExprRecognizer
	{
		public IfThenRecognizer()
		{
			NewLineRight = new string[] { "if", "then", "else" };
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			if (Code.String.StartsWith("if", true))
			{
				var State = PlugIn.State;
				var Container = PlugIn.Container;

				FindRes Result;
				var SubCode = Code.Substring(2);
				if (SubCode == null || (Result = SubCode.String.Find(new string[] { "then" }, InZ: true, NotIdChar: true)).Position == -1)
				{
					State.Messages.Add(MessageId.NeedThenElse, Code);
					return ExprRecognizerRes.Failed;
				}

				var ConditionStr = SubCode.TrimmedSubstring(0, Result.Position);
				SubCode = SubCode.Substring(Result.Position + Result.String.Length);

				if (SubCode == null || (Result = SubCode.String.Find(new string[] { "else" },
					InZ: true, NotIdChar: true)).Position == -1)
				{
					State.Messages.Add(MessageId.NeedThenElse, Code);
					return ExprRecognizerRes.Failed;
				}

				var ThenStr = SubCode.TrimmedSubstring(0, Result.Position);
				var ElseStr = SubCode.TrimmedSubstring(Result.Position + Result.String.Length);

				if (ThenStr == null || ElseStr == null || ConditionStr == null ||
					ThenStr.String == "" || ElseStr.String == null || ConditionStr.String == "")
				{
					State.Messages.Add(MessageId.DeficientExpr, Code);
					return ExprRecognizerRes.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 ExprRecognizerRes.Failed;

				var Ch = new List<ExpressionNode>() { Condition, Then, Else };
				Ret = new OpExpressionNode(Operator.Condition, Ch, Code);
				return ExprRecognizerRes.Succeeded;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

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

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{	
			var Result = Code.String.Find(Operators, InZ: true, Skip: Skip);
			if (Result.Position != -1)
			{
				var Ch = Expressions.TwoParamOpNode(Code, Result, PlugIn);
				if (Ch == null) return ExprRecognizerRes.Failed;

				var Op = Operator.Nothing;
				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.Or; break;
					case 8: Op = Operator.And; break;
					case 9: Op = Operator.Xor; break;

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

					default:
						throw new Exception("ERROR");
				}

				if (Op != Operator.Nothing)
				{
					var RId = Ch[0];
					Ret = PlugIn.NewNode(new OpExpressionNode(Op, Ch, Code));
					if (Ret == null) return ExprRecognizerRes.Failed;

					Ch = new List<ExpressionNode>() { RId, Ret };
					Ret = new OpExpressionNode(Operator.Assignment, Ch, Code);
				}

				return ExprRecognizerRes.Succeeded;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class TupleCreatingRecognizer : ExprRecognizer
	{
		public TupleCreatingRecognizer()
		{
			Operators = new string[] { "{" };
			NewLineRight = Operators;
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			if (Code.String.Find(',', InZ: true, Back: true) != -1)
			{
				var Members = Expressions.CreateParamNodes(PlugIn, Code, null, Code);
				if (Members == null) return ExprRecognizerRes.Failed;
				Ret = new OpExpressionNode(Operator.CreateTuple, Members, Code);
				return ExprRecognizerRes.Succeeded;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class LogicalRecognizer : ExprRecognizer
	{
		public LogicalRecognizer()
		{
			Operators = new string[] { "and", /* "xor", */ "or" };
			NewLineLeft = NewLineRight = Operators;
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			var Result = Code.String.Find(Operators, InZ: true, NotIdChar: true, Back: true);
			if (Result.Position != -1)
			{
				var Ch = Expressions.TwoParamOpNode(Code, Result, PlugIn);
				if (Ch == null) return ExprRecognizerRes.Failed;

				Operator Op;
				if (Result.Index == 0) Op =Operator.And;
				//else if (Result.Index == 1) Op = Operator.Xor;
				else if (Result.Index == 1) Op = Operator.Or;
				else throw new Exception("ERROR");

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

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class RelEquRecognizer : ExprRecognizer
	{
		public RelEquRecognizer()
		{
			Operators = new string[] { "==", "<>", "<", ">", "<=", "=<", ">=", "=>" };
			NewLineLeft = NewLineRight = Operators;
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			var Results = Code.String.EnumFind(Operators, InZ: true, Skip: Skip, Back: true).ToArray();
			if (Results.Length > 0)
			{
				var ChNodes = new List<ExpressionNode>();
				for (var i = -1; i < Results.Length; i++)
				{
					int Start, Length;
					if (i == -1)
					{
						var Res = Results[0];
						Start = Res.Position + Res.String.Length;
						Length = Code.StrLen - Start;
					}
					else
					{
						if (i + 1 == Results.Length)
						{
							Start = 0;
							Length = Results[i].Position;
						}
						else
						{
							var Res = Results[i + 1];
							Start = Res.Position + Res.String.Length;
							Length = Results[i].Position - Start;
						}
					}

					var PStr = Code.TrimmedSubstring(Start, Length);
					if (PStr.StrLen == 0)
					{
						PlugIn.State.Messages.Add(MessageId.DeficientExpr, Code);
						return ExprRecognizerRes.Failed;
					}

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

				var LinkedNodes = new List<LinkedExprNode>();
				for (var i = 1; i < ChNodes.Count - 1; i++)
					LinkedNodes.Add(new LinkedExprNode(ChNodes[i]));

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

					switch (Result.Index)
					{
						case 0: Op = Operator.Equal; break;
						case 1: Op = Operator.Nonequal; break;
						case 2: Op = Operator.Less; break;
						case 3: Op = Operator.Greater; break;
						case 4: Op = Operator.LessEqual; break;
						case 5: Op = Operator.LessEqual; break;
						case 6: Op = Operator.GreaterEqual; break;
						case 7: Op = Operator.GreaterEqual; break;
						default: throw new Exception("ERROR");
					}

					var Ch = new List<ExpressionNode>();
					Ch.Add(i != Results.Length - 1 ? PlugIn.NewNode(new LinkingNode(LinkedNodes[i], Code)) : ChNodes[i + 1]);
					Ch.Add(i != 0 ? PlugIn.NewNode(new LinkingNode(LinkedNodes[i - 1], Code)) : ChNodes[i]);
					var NewNode = PlugIn.NewNode(new OpExpressionNode(Op, Ch, Code));

					if (NewNode == null) return ExprRecognizerRes.Failed;
					RetNodes.Add(NewNode);
				}

				while (RetNodes.Count > 1)
				{
					var Ch = new List<ExpressionNode>() { RetNodes[0], RetNodes[1] };
					var Node = (ExpressionNode)new OpExpressionNode(Operator.And, Ch, Code);

                    if (LinkedNodes.Count > 0 && RetNodes.Count == 2)
                        Node.LinkedNodes = LinkedNodes;

					if ((Node = PlugIn.NewNode(Node)) == null)
						return ExprRecognizerRes.Failed;

					RetNodes.RemoveAt(0);
					RetNodes[0] = Node;
				}

				Ret = RetNodes[0];
				return ExprRecognizerRes.DontCallNewNode;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class AdditiveRecognizer : ExprRecognizer
	{
		public AdditiveRecognizer()
		{
			Operators = new string[] { "+", "-" };
			NewLineLeft = NewLineRight = Operators;
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{			
			var Result = Expressions.Find2(PlugIn.State, Code.String, Operators, Skip);
			if (Result.Position != -1)
			{
				var Ch = Expressions.TwoParamOpNode(Code, Result, PlugIn);
				if (Ch == null) return ExprRecognizerRes.Failed;

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

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

			return ExprRecognizerRes.UnknownOp;
		}
	}

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

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			var Result = Code.String.Find(Operators, Skip: Skip, InZ: true, End: 1, Back: true);
			if (Result.Position != -1)
			{
				var Ch = Expressions.TwoParamOpNode(Code, Result, PlugIn);
				if (Ch == null) return ExprRecognizerRes.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 Exception("ERROR");

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

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class ShiftRecognizer : ExprRecognizer
	{
		public ShiftRecognizer()
		{
			Operators = new string[] { "<<", ">>" };
			NewLineLeft = NewLineRight = Operators;
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			var Result = Code.String.Find(Operators, InZ: true, Skip: Skip, Back: true);
			if (Result.Position != -1)
			{
				var Ch = Expressions.TwoParamOpNode(Code, Result, PlugIn);
				if (Ch == null) return ExprRecognizerRes.Failed;

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

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

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class BitwiseRecognizer : ExprRecognizer
	{
		public BitwiseRecognizer()
		{
			Operators = new string[] { "&", "|", "^" };
			NewLineLeft = NewLineRight = Operators;
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{		
			var Result = Expressions.Find2(PlugIn.State, Code.String, Operators, Skip);
			if (Result.Position != -1)
			{
				var Ch = Expressions.TwoParamOpNode(Code, Result, PlugIn);
				if (Ch == null) return ExprRecognizerRes.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 Exception("ERROR");

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

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class CastRecognizer : ExprRecognizer
	{
		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			if (Expressions.IsCastString(PlugIn.State, Code.String))
			{
				var State = PlugIn.State;
				var Container = PlugIn.Container;
				var Pos = BracketHelper.ZPos(Code.String, 0);
				if (Pos == -1)
				{
					State.Messages.Add(MessageId.ZNumErr, Code.TrimmedSubstring(0, 1));
					return ExprRecognizerRes.Failed;
				}

				var TypeName = Code.TrimmedSubstring(1, Pos - 1);
				var Type = Container.GetId<Type>(TypeName);
				if (Type == null) return ExprRecognizerRes.Failed;

				var ChildStr = Code.TrimmedSubstring(Pos + 1);
				var Child = Expressions.Recognize(ChildStr, PlugIn, true);
				if (Child == null) return ExprRecognizerRes.Failed;

				Ret = new CastExpressionNode(Type, Child, Code);
				return ExprRecognizerRes.Succeeded;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class NegateRecognizer : ExprRecognizer
	{
		public NegateRecognizer()
		{
			NewLineRight = new string[] { "-", "+" };
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			if (Code.String.Length > 0 && Code.String[0] == '-')
			{
				Ret = Expressions.OneParamOpNode(Code, PlugIn, Operator.Neg);
				if (Ret == null) return ExprRecognizerRes.Failed;
				return ExprRecognizerRes.Succeeded;
			}
            else if (Code.String.Length > 0 && Code.String[0] == '+')
            {
                var SubStr = Code.TrimmedSubstring(1);
                if (SubStr.StrLen == 0)
                {
                    PlugIn.State.Messages.Add(MessageId.DeficientExpr, Code);
                    return ExprRecognizerRes.Failed;
                }

                Ret = Expressions.Recognize(SubStr, PlugIn, true);
                if (Ret == null) return ExprRecognizerRes.Failed;
                return ExprRecognizerRes.DontCallNewNode;
            }

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class NotRecognizer : ExprRecognizer
	{
		public NotRecognizer()
		{
			NewLineRight = new string[] { "!" };
			Init();
		}

        public static ExpressionNode Negate(ExpressionNode Node, ExprPlugIn PlugIn, PString Code)
        {
            if (Node is OpExpressionNode)
            {
                var OpNode = Node as OpExpressionNode;
                var Op = OpNode.Operator;
                var Ch = OpNode.Children;

				if (Anonymus.Operators.IsBoolRetOp(Op))
                {
					OpNode.Operator = Anonymus.Operators.NegateOp(OpNode.Operator);
					if (Anonymus.Operators.IsRelEqualityOp(Op)) return Node;

                    for (var i = 0; i < Ch.Count; i++)
                    {
                        Ch[i] = Negate(Ch[i], PlugIn, Code);
                        if (Ch[i] == null) return null;
                    }

                    return Node;
                }
            }

            var NewCh = new List<ExpressionNode>() { Node };
            return PlugIn.NewNode(new OpExpressionNode(Operator.Not, NewCh, Code));
        }

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			if (Code.String.Length > 0 && Code.String[0] == '!')
			{
				var SubStr = Code.TrimmedSubstring(1);
				if (SubStr.StrLen == 0)
				{
					PlugIn.State.Messages.Add(MessageId.DeficientExpr, Code);
					return ExprRecognizerRes.Failed;
				}

				Ret = Expressions.Recognize(SubStr, PlugIn, true);
				if (Ret == null) return ExprRecognizerRes.Failed;

                if ((Ret = Negate(Ret, PlugIn, Code)) == null)
                    return ExprRecognizerRes.Failed;

				return ExprRecognizerRes.DontCallNewNode;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class AddressRecognizer : ExprRecognizer
	{
		public AddressRecognizer()
		{
			NewLineRight = new string[] { "&" };
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			if (Code.String.Length > 0 && Code.String[0] == '&')
			{
				Ret = Expressions.OneParamOpNode(Code, PlugIn, Operator.Address);
				if (Ret == null) return ExprRecognizerRes.Failed;
				return ExprRecognizerRes.Succeeded;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class ComplementRecognizer : ExprRecognizer
	{
		public ComplementRecognizer()
		{
			NewLineRight = new string[] { "~" };
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			if (Code.String.Length > 0 && Code.String[0] == '~')
			{
				Ret = Expressions.OneParamOpNode(Code, PlugIn, Operator.Complement);
				if (Ret == null) return ExprRecognizerRes.Failed;
				return ExprRecognizerRes.Succeeded;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class IncDecRecognizer : ExprRecognizer
	{
        public IncDecRecognizer()
		{
			Operators = new string[] { "++", "--" };
			NewLineLeft = Operators;
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			if (Code.String.EndsWith("++"))
			{
				Ret = Expressions.IncDecNode(Code, PlugIn, Operator.Add, 2);
				if (Ret == null) return ExprRecognizerRes.Failed;
				return ExprRecognizerRes.DontCallNewNode;
			}
            else if (Code.String.EndsWith("--"))
            {
                Ret = Expressions.IncDecNode(Code, PlugIn, Operator.Subract, 2);
                if (Ret == null) return ExprRecognizerRes.Failed;
                return ExprRecognizerRes.DontCallNewNode;
            }

            return ExprRecognizerRes.UnknownOp;
		}
	}

	public class IndirectionRecognizer : ExprRecognizer
	{
		public IndirectionRecognizer()
		{
			NewLineRight = new string[] { "*" };
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			if (Code.String.Length > 0 && Code.String[0] == '*')
			{
				var PtrCode = Code.TrimmedSubstring(1);
				var PtrNode = Expressions.Recognize(PtrCode, PlugIn, true);
				if (PtrNode == null) return ExprRecognizerRes.Failed;

				var IdPtrNode = PtrNode as IdExpressionNode;
				if (PtrNode.Type is TypeOfType && IdPtrNode != null)
				{
					var Type = (IdPtrNode.Id as Type).CreatePointerType();
					Ret = new IdExpressionNode(Type, Code);
				}
				else
				{
					Ret = PtrNode.Indirection(PlugIn.State, PlugIn.Container, Code, PlugIn);
					if (Ret == null) return ExprRecognizerRes.Failed;
					return ExprRecognizerRes.DontCallNewNode;
				}
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class CallIndexRecognizer : ExprRecognizer
	{
		public List<KeywordFuncRecognizer> Recognizers;

		public CallIndexRecognizer(List<KeywordFuncRecognizer> Recognizers)
		{
			this.Recognizers = Recognizers;
			Operators = new string[] { "(", "[" };
			NewLineRight = Operators;
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{			
			var Result = Code.String.Find(Operators, Skip: Skip);
			if (Result.Position > 0)
			{
				var State = PlugIn.State;
				var Pos = BracketHelper.ZPos(Code.String, Result.Position);
				if (Pos == -1)
				{
					var Str = Code.TrimmedSubstring(Result.Position, 1);
					State.Messages.Add(MessageId.ZNumErr, Str);
					return ExprRecognizerRes.Failed;
				}

				Operator Op;
				if (Result.Index == 0) Op = Operator.Call;
				else if (Result.Index == 1) Op = Operator.Index;
				else throw new Exception("ERROR");

				var Func = Code.TrimmedSubstring(0, Result.Position);
				var ParamStr = Code.Substring(Result.Position + 1, Pos - Result.Position - 1);
				var AllParams = Expressions.ConstructCallIndexParams(State, Func, ParamStr);

				if (Recognizers != null)
				{
					foreach (var e in Recognizers)
					{
						var Res = e.Recognize(Code, AllParams, PlugIn, ref Ret);
						if (Res != ExprRecognizerRes.UnknownOp) return Res;
					}
				}

				Ret = Expressions.CreateCallIndexExpr(Code, PlugIn, Op, AllParams);
				if (Ret == null) return ExprRecognizerRes.Failed;
				return ExprRecognizerRes.DontCallNewNode;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class NullCoalescingRecognizer : ExprRecognizer
	{
		public NullCoalescingRecognizer()
		{
			Operators = new string[] { "??" };
			NewLineLeft = NewLineRight = Operators;
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			var Result = Expressions.Find2(PlugIn.State, Code.String, Operators, Skip);
			if (Result.Position != -1)
			{
				var State = PlugIn.State;
				var Container = PlugIn.Container;
				var GlobalScope = Container.GlobalScope;

				var LeftRight = Expressions.TwoParamOpNode(Code, Result, PlugIn);
				if (LeftRight == null) return ExprRecognizerRes.Failed;
				var Linked = new LinkedExprNode(LeftRight[0]);

				var Null = PlugIn.NewNode(new ConstExpressionNode(GlobalScope.AutoType, 0UL, Code));
				if (Null == null) return ExprRecognizerRes.Failed;
				var RelLnk = PlugIn.NewNode(new LinkingNode(Linked, Code));
				if (RelLnk == null) return ExprRecognizerRes.Failed;

				var RelCh = new List<ExpressionNode>() { RelLnk, Null };
				var Rel = PlugIn.NewNode(new OpExpressionNode(Operator.Nonequal, RelCh, Code));
				if (Rel == null) return ExprRecognizerRes.Failed;

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

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class SafeNavigationRecognizer : ExprRecognizer
	{
		public SafeNavigationRecognizer()
		{
			Operators = new string[] { "?.", "?->" };
			NewLineLeft = NewLineRight = Operators;
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			var Result = Expressions.Find2(PlugIn.State, Code.String, Operators, Skip);
			if (Result.Position != -1)
			{
				var State = PlugIn.State;
				var Container = PlugIn.Container;
				var GlobalScope = Container.GlobalScope;

				var Left_Str = Code.TrimmedSubstring(0, Result.Position);
				var Right_Str = Code.TrimmedSubstring(Result.Position + Result.String.Length);
				if (Left_Str.StrLen == 0 || Right_Str.StrLen == 0)
				{
					State.Messages.Add(MessageId.DeficientExpr, Code);
					return ExprRecognizerRes.Failed;
				}

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

				//--------------------------------------------------------------------------------------
				var Null = PlugIn.NewNode(new ConstExpressionNode(GlobalScope.AutoType, 0UL, Code));
				if (Null == null) return ExprRecognizerRes.Failed;
				var RelLnk = PlugIn.NewNode(new LinkingNode(Linked, Code));
				if (RelLnk == null) return ExprRecognizerRes.Failed;

				var RelCh = new List<ExpressionNode>() { RelLnk, Null };
				var Rel = PlugIn.NewNode(new OpExpressionNode(Operator.Nonequal, RelCh, Code));
				if (Rel == null) return ExprRecognizerRes.Failed;

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

				if (Result.Index == 1)
				{
					ThenSrc = ThenSrc.Indirection(State, Container, Code, PlugIn);
					if (ThenSrc == null) return ExprRecognizerRes.Failed;
				}

				var ThenSrcType = ThenSrc.Type as StructuredType;
				if (ThenSrcType == null)
				{
					State.Messages.Add(MessageId.HasntGotMembers, Left_Str, ThenSrc.Type.Name.String);
					return ExprRecognizerRes.Failed;
				}

				var Member = ThenSrcType.GetId<Identifier>(Right_Str.String);
				if (Member == null)
				{
					State.Messages.Add(MessageId.UnknownId, Right_Str);
					return ExprRecognizerRes.Failed;
				}
				else if (Member.IsStatic)
				{
					State.Messages.Add(MessageId.Static, Right_Str);
					return ExprRecognizerRes.Failed;
				}

				var MemberNode = PlugIn.NewNode(new IdExpressionNode(Member, Code));
				if (MemberNode == null) return ExprRecognizerRes.Failed;
				var ThenCh = new List<ExpressionNode>() { ThenSrc, MemberNode };
				var Then = PlugIn.NewNode(new OpExpressionNode(Operator.Member, ThenCh, Code));
				if (Then == null) return ExprRecognizerRes.Failed;

				//--------------------------------------------------------------------------------------
				var Else = PlugIn.NewNode(new ConstExpressionNode(GlobalScope.AutoType, 0UL, Code));
				if (Else == null) return ExprRecognizerRes.Failed;
				var RetCh = new List<ExpressionNode>() { Rel, Then, Else };
				Ret = new OpExpressionNode(Operator.Condition, RetCh, Code);
				Ret.LinkedNodes = new List<LinkedExprNode>() { Linked };
				return ExprRecognizerRes.Succeeded;
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class MemberRecognizer : ExprRecognizer
	{
		public MemberRecognizer()
		{
			Operators = new string[] { ".", "->" };
			NewLineLeft = NewLineRight = Operators;
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			var Result = Code.String.Find(Operators, Skip: Skip, InZ: true);
			if (Result.Position > 0)
			{
				var State = PlugIn.State;
				var Container = PlugIn.Container;
				var Left_Str = Code.TrimmedSubstring(0, Result.Position);
				var Right_Str = Code.TrimmedSubstring(Result.Position + Result.String.Length);

				if (Right_Str.StrLen == 0 || Left_Str.StrLen == 0)
				{
					State.Messages.Add(MessageId.DeficientExpr, Code);
					return ExprRecognizerRes.Failed;
				}

                if (!Helper.IsValidIdentifierName(Right_Str.String) && !Right_Str.String.IsNum())
				{
					State.Messages.Add(MessageId.NotValidName, Right_Str);
					return ExprRecognizerRes.Failed;
				}

				var Left = Expressions.Recognize(Left_Str, PlugIn, true);
				if (Left == null) return ExprRecognizerRes.Failed;

				if (Result.Index == 1)
				{
					Left = Left.Indirection(State, Container, Code, PlugIn);
					if (Left == null) return ExprRecognizerRes.Failed;
				}

				var Ch = new List<ExpressionNode>() { Left };
				var RealType = Left.Type.RealType;
				if (RealType is StructuredType)
				{
					var SRealType = RealType as StructuredType;
					var Id = (Identifier)null;

					if (SRealType == null || (Id = SRealType.GetId<Identifier>(Right_Str.String)) == null)
					{
						State.Messages.Add(MessageId.UnknownId, Right_Str);
						return ExprRecognizerRes.Failed;
					}

					if (Id.IsStatic)
					{
						State.Messages.Add(MessageId.Static, Right_Str);
						return ExprRecognizerRes.Failed;
					}

					var V = PlugIn.NewNode(new IdExpressionNode(Id, Code));
					if (V == null) return ExprRecognizerRes.Failed;
					Ch.Add(V);
					Ret = new OpExpressionNode(Operator.Member, Ch, Code);
					return ExprRecognizerRes.Succeeded;
				}
				else if (RealType is TypeOfType)
				{
					var IdNode = Left as IdExpressionNode;
					var Id = (Identifier)null;

					if (IdNode.Id is EnumType)
					{
						var EType = IdNode.Id as EnumType;
						var Val = EType.GetValue(Right_Str.String);
						if (Val == null)
						{
							State.Messages.Add(MessageId.UnknownId, Right_Str);
							return ExprRecognizerRes.Failed;
						}

						Ret = Val.GetNode(State, Code, PlugIn);
						return ExprRecognizerRes.DontCallNewNode;
					}
					else if (IdNode.Id is StructuredType)
					{
						var Type = IdNode.Id as StructuredType;
						if ((Id = Type.GetId<Identifier>(Right_Str.String)) == null)
						{
							State.Messages.Add(MessageId.UnknownId, Right_Str);
							return ExprRecognizerRes.Failed;
						}

						if (!Id.IsStatic)
						{
							State.Messages.Add(MessageId.NonStatic, Right_Str);
							return ExprRecognizerRes.Failed;
						}

						Ret = new IdExpressionNode(Id, Code);
						return ExprRecognizerRes.Succeeded;
					}
					else
					{
						State.Messages.Add(MessageId.UnknownId, Right_Str);
						return ExprRecognizerRes.Failed;
					}
				}
				else
				{
					State.Messages.Add(MessageId.HasntGotMembers, Left_Str, RealType.Name.String);
					return ExprRecognizerRes.Failed;
				}
			}

			return ExprRecognizerRes.UnknownOp;
		}
	}

	public class ExprVarDeclRecognizer : ExprRecognizer
	{
		public ExprVarDeclRecognizer()
		{
			Operators = new string[] { " ", "\t", "\r", "\n" };
			Init();
		}

		public override ExprRecognizerRes Recognize(PString Code, ExprPlugIn PlugIn, ref ExpressionNode Ret)
		{
			var Result = Code.String.Find(Operators, InZ: true);
			if (Result.Position != -1)
			{
				var VarName = Code.TrimmedSubstring(Result.Position);
				if (!Helper.IsValidIdentifierName(VarName.String))
					return ExprRecognizerRes.UnknownOp;

				var Container = PlugIn.Container;
				var State = PlugIn.State;

				var TypeName = Code.TrimmedSubstring(0, Result.Position);
				Ret = PlugIn.DeclareVariable(Code, TypeName, VarName);
                if (Ret == null) return ExprRecognizerRes.Failed;
                else return ExprRecognizerRes.DontCallNewNode;
			}

			return ExprRecognizerRes.UnknownOp;
		} 
	}

}

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
Web04 | 2.8.150327.1 | Last Updated 1 Jan 2013
Article Copyright 2011 by Dávid Kocsis
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid