Click here to Skip to main content
15,885,799 members
Articles / High Performance Computing / Vectorization

Bird Programming Language: Part 1

Rate me:
Please Sign up or sign in to vote.
4.92/5 (129 votes)
1 Jan 2013GPL312 min read 376.7K   2.7K   153  
A new general purpose language that aims to be fast, high level and simple to use.
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)


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

Comments and Discussions