using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Anonymus.Recognizers
{
public abstract class MultiCommRecognizer : CommRecognizer
{
public List<CommRecognizer> Recognizers = new List<CommRecognizer>();
public override T GetRecognizer<T>()
{
foreach (var e in Recognizers)
if (e is T) return e as T;
return base.GetRecognizer<T>();
}
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
foreach (var e in Recognizers)
{
var Res = e.Recognize(Code, Word, Line, Index, Scope);
if (Res != CommRecognizerRes.UnknownOp) return Res;
}
return CommRecognizerRes.UnknownOp;
}
}
public class AsmCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "asm")
{
var State = Scope.State;
var Inner = Scope.FInnerScope(Word, Line, Index);
if (Inner != null)
{
foreach (var e in Inner)
{
var Command = Scope.CreateAsmCommand();
if (!Command.Process(State, e.Trim()))
return CommRecognizerRes.Failed;
else if (!Scope.AddCommand(Code, Command))
return CommRecognizerRes.Failed;
}
}
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class IfCommRecognizer : CommRecognizer
{
public static bool ProcIf(PString FLine, PString Line, int Index, CodeScopeNode Scope, ConditionCommand CCondComm = null)
{
var RetValue = true;
var Inner = Scope.InnerScope(null, Index);
if (Inner == null) return false;
var ElseInner = (PString[])null;
var State = Scope.State;
var Res = Line.String.Find(new string[] { "then" }, InZ: true, NotIdChar: true);
if (Res.Index != -1)
{
if (Inner.Length != 0)
{
State.Messages.Add(MessageId.NotExpected, Line.Substring(Res.Position).Trim());
Line = Line.Substring(0, Res.Position);
RetValue = false;
}
else
{
var String = Line.Substring(Res.Position + Res.String.Length);
var ElseRes = String.String.Find(new string[] { "else" }, InZ: true, NotIdChar: true, Back: true);
if (ElseRes.Index != -1)
{
var Else = String.Substring(ElseRes.Position + ElseRes.String.Length);
String = String.Substring(0, ElseRes.Position);
ElseInner = new PString[] { Else };
}
Inner = new PString[] { String };
}
}
else if (Inner.Length == 0)
{
State.Messages.Add(MessageId.EmptyScope, FLine);
}
var CondComm = CCondComm != null ? CCondComm : Scope.CreateConditionCommand();
var Part = CondComm.CreateCondition();
var PlugIn = Part.GetPlugIn();
PlugIn.GetPlugIn<TypeMgrPlugIn>().RetType = Scope.GlobalScope.BoolType;
var ConStr = Line.Substring(0, Res.Index == -1 ? Line.Length : Res.Position);
var Node = Expressions.NewExpressionTree(ConStr, PlugIn, true);
if (Node == null) RetValue = false;
else Part.Condition = Node;
var ThenScope = Part.CreateCodeScopeNode(Inner);
if (!ThenScope.ProcessCode()) RetValue = false;
else Part.Then = ThenScope;
CodeScopeNode ElseScope = null;
if (ElseInner != null)
{
ElseScope = Part.CreateCodeScopeNode(ElseInner);
if (!ElseScope.ProcessCode()) RetValue = false;
else Part.Else = ElseScope;
}
if (CondComm != CCondComm && !Scope.AddCommand(FLine, CondComm))
RetValue = false;
return RetValue;
}
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "if")
{
if (!ProcIf(Code, Line, Index, Scope))
return CommRecognizerRes.Failed;
else return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class ElseCommRecognizer : CommRecognizer
{
public static bool ProcElse(PString FLine, PString Line, int LineIndex, CodeScopeNode Scope)
{
var RetValue = true;
var FFLine = Line.Copy();
var Word2 = Line.Word();
var State = Scope.State;
var CondComm = Scope.LastCommand as ConditionCommand;
var LastPart = CondComm != null ? CondComm.LastCondition : null;
if (CondComm == null || LastPart.Else != null)
{
State.Messages.Add(MessageId.NoMatchingIf, FLine);
RetValue = false;
}
else
{
if (Word2.String == "if")
{
if (!IfCommRecognizer.ProcIf(FLine, Line, LineIndex, Scope, CondComm))
RetValue = false;
}
else
{
Line = FFLine;
var Inner = Scope.FInnerScope(FLine, Line, LineIndex);
if (Inner == null) return false;
LastPart.Else = LastPart.CreateCodeScopeNode(Inner);
if (!LastPart.Else.ProcessCode()) RetValue = false;
}
}
return RetValue;
}
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "else")
{
if (!ProcElse(Code, Line, Index, Scope))
return CommRecognizerRes.Failed;
else return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class LabelCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Line.String.Length > 0 && Line.String[0] == ':')
{
var State = Scope.State;
var Cmd = Scope.CreateLabelCommand(State.NextLabelIndex);
if (!Scope.AddCommand(Code, Cmd)) return CommRecognizerRes.Failed;
var FScope = Scope.FuncScope;
if (!Helper.IsValidIdentifierName(Word.String))
{
State.Messages.Add(MessageId.NotValidName, Code);
return CommRecognizerRes.Failed;
}
else if (FScope.GetLabelCmd(Word.String) != null)
{
State.Messages.Add(MessageId.LabelAlreadyDefined, Code);
return CommRecognizerRes.Failed;
}
else
{
FScope.Labels.Add(Word.String, Cmd);
}
Line = Line.TrimmedSubstring(1);
if (Line.StrLen != 0)
{
if (!Scope.RecognizeCommand(Line, Index))
return CommRecognizerRes.Failed;
}
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class GotoCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "goto")
{
var State = Scope.State;
if (!Helper.IsValidIdentifierName(Line.String))
{
State.Messages.Add(MessageId.NotValidName, Line);
return CommRecognizerRes.Failed;
}
var Cmd = Scope.CreateGotoCommand(Line);
Scope.FuncScope.Gotos.Add(Cmd);
if (!Scope.AddCommand(Code, Cmd))
return CommRecognizerRes.Failed;
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class BreakCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "break")
{
var State = Scope.State;
if (!State.ChkNotExpected(Line)) return CommRecognizerRes.Failed;
var Comm = Scope.GetScope<BreakableCommand>();
if (Comm == null)
{
State.Messages.Add(MessageId.UnBreakCountinueable, Word);
return CommRecognizerRes.Failed;
}
var Brk = Scope.CreateBreakCommand(Comm.BreakLabel);
if (!Scope.AddCommand(Word, Brk))
return CommRecognizerRes.Failed;
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class ContinueCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "continue")
{
var State = Scope.State;
if (!State.ChkNotExpected(Line)) return CommRecognizerRes.Failed;
var Comm = Scope.GetScope<BreakableCommand>();
if (Comm == null)
{
State.Messages.Add(MessageId.UnBreakCountinueable, Word);
return CommRecognizerRes.Failed;
}
var Goto = Scope.CreateContinueCommand(Comm.BreakLabel);
if (!Scope.AddCommand(Word, Goto)) return CommRecognizerRes.Failed;
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class SwitchCommRecognizer : CommRecognizer
{
public static PString ChkCaseDef(PString FLine, CodeScopeNode Scope, ref PString Line)
{
var State = Scope.State;
var Pos = Line.IndexOf(':', InZ: true);
if (Pos == -1)
{
State.Messages.Add(MessageId.CaseSystaxErr, FLine);
Line = null;
return null;
}
var ExprStr = Line.TrimmedSubstring(0, Pos);
Line = Line.TrimmedSubstring(Pos + 1);
return ExprStr;
}
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "switch")
{
var Comm = Scope.CreateSwitchCommand();
Comm.Node = Expressions.NewExpressionTree(Line, Scope.GetPlugIn());
if (Comm.Node == null) return CommRecognizerRes.Failed;
if (!Scope.AddCommand(Line, Comm)) return CommRecognizerRes.Failed;
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class CaseCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "case")
{
var State = Scope.State;
var LComm = Scope.LastCommand;
var Inner = Scope.FInnerScope(Code, Line, Index);
if (Inner == null) return CommRecognizerRes.Failed;
var Switch = LComm != null ? LComm as SwitchCommand : null;
if (Switch == null)
{
State.Messages.Add(MessageId.CaseWithoutSwitch, Code);
return CommRecognizerRes.Failed;
}
//-------------------------------------------------------------------
var ExprStr = SwitchCommRecognizer.ChkCaseDef(Code, Scope,ref Line);
if (ExprStr == null) return CommRecognizerRes.Failed;
if (ExprStr.StrLen == 0)
{
State.Messages.Add(MessageId.DeficientExpr, Code);
return CommRecognizerRes.Failed;
}
var Part = Switch.CreateCondition();
Part.Then = Part.CreateCodeScopeNode(Inner);
//-------------------------------------------------------------------
var PlugIn = Scope.GetPlugIn();
var Node = Expressions.NewExpressionTree(ExprStr, PlugIn, false);
if (Node == null) return CommRecognizerRes.Failed;
var Lnk = PlugIn.NewNode(new LinkingNode(new LinkedExprNode(Switch.Node), ExprStr));
if (Lnk == null) return CommRecognizerRes.Failed;
var Ch = new List<ExpressionNode>() { Lnk, Node };
var Cmp = PlugIn.NewNode(new OpExpressionNode(Operator.Equal, Ch, ExprStr));
if (Cmp == null) return CommRecognizerRes.Failed;
if ((Part.Condition = PlugIn.End(Cmp)) == null)
return CommRecognizerRes.Failed;
if (!Part.Then.ProcessCode()) return CommRecognizerRes.Failed;
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class DefaultCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "default")
{
var State = Scope.State;
var LComm = Scope.LastCommand;
var Inner = Scope.FInnerScope(Code, Line, Index);
if (Inner == null) return CommRecognizerRes.Failed;
var Switch = LComm != null ? LComm as SwitchCommand : null;
if (Switch == null)
{
State.Messages.Add(MessageId.CaseWithoutSwitch, Code);
return CommRecognizerRes.Failed;
}
else if (Switch.HasElseNIf())
{
State.Messages.Add(MessageId.SwitchAlreadyHasDef, Code);
return CommRecognizerRes.Failed;
}
//-------------------------------------------------------------------
var ExprStr = SwitchCommRecognizer.ChkCaseDef(Code, Scope, ref Line);
if (ExprStr == null) return CommRecognizerRes.Failed;
if (ExprStr.StrLen != 0)
{
State.Messages.Add(MessageId.NotExpected, ExprStr);
return CommRecognizerRes.Failed;
}
var Part = Switch.CreateCondition();
Part.Then = Part.CreateCodeScopeNode(Inner);
if (!Part.Then.ProcessCode()) return CommRecognizerRes.Failed;
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class DoCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "do")
{
var Comm = Scope.CreateWhileCommand(null, true);
var Inner = Scope.FInnerScope(Code, Line, Index);
if (Inner == null) return CommRecognizerRes.Failed;
Comm.InnerScope = Comm.CreateCodeScopeNode(Inner);
if (!Comm.InnerScope.ProcessCode()) return CommRecognizerRes.Failed;
if (!Scope.AddCommand(Code, Comm)) return CommRecognizerRes.Failed;
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class RepeatCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "repeat")
{
var Comm = Scope.CreateLoopCommand();
var Inner = Scope.FInnerScope(Code, null, Index);
if (Inner == null) return CommRecognizerRes.Failed;
Comm.InnerScope = Comm.CreateCodeScopeNode(Inner);
if (!Comm.InnerScope.ProcessCode()) return CommRecognizerRes.Failed;
if (!Scope.AddCommand(Code, Comm)) return CommRecognizerRes.Failed;
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class WhileCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "while")
{
var WhileComm = Scope.CreateWhileCommand(null);
var Inner = Scope.FInnerScope(Code, null, Index);
if (Inner == null) return CommRecognizerRes.Failed;
var NewScope = WhileComm.CreateCodeScopeNode(Inner);
WhileComm.InnerScope = NewScope;
var PlugIn = WhileComm.GetPlugIn();
PlugIn.GetPlugIn<TypeMgrPlugIn>().RetType = Scope.GlobalScope.BoolType;
var Condition = Expressions.NewExpressionTree(Line, PlugIn, true);
if (Condition == null) return CommRecognizerRes.Failed;
else WhileComm.Condition = Condition;
var LastComm = Scope.LastCommand as WhileCommand;
if (LastComm != null && LastComm.DoWhile && LastComm.Condition == null)
{
LastComm.Condition = Condition;
return CommRecognizerRes.Failed;
}
if (!NewScope.ProcessCode()) return CommRecognizerRes.Failed;
if (!Scope.AddCommand(Code, WhileComm)) return CommRecognizerRes.Failed;
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class ForCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "for")
{
var State = Scope.State;
var RetValue = true;
var Res = Line.String.Find(new string[] { "to", "downto", "until", "eachin" }, InZ: true, NotIdChar: true);
var Func = Res.Index;
var ForCommand = Scope.CreateForCommand(null, null, null);
var Inner = Scope.FInnerScope(Code, null, Index);
if (Inner == null) return CommRecognizerRes.Failed;
var NewScope = ForCommand.CreateCodeScopeNode(Inner);
ForCommand.InnerScope = NewScope;
var PlugIn = ForCommand.GetPlugIn();
if (Func == -1)
{
State.Messages.Add(MessageId.ForToDownToUntil, Code);
RetValue = false;
}
else
{
var InitStr = Line.Substring(0, Res.Position);
Line = Line.TrimmedSubstring(Res.Position + Res.String.Length);
if (Line.String == "")
{
State.Messages.Add(MessageId.NoForVar, Code);
RetValue = false;
}
else
{
var VarNode = (ExpressionNode)null;
var InitNode = Expressions.NewExpressionTree(InitStr, PlugIn);
var OpNode = InitNode as OpExpressionNode;
if (OpNode == null || OpNode.Operator != Operator.Assignment)
{
State.Messages.Add(MessageId.NoForVar, Code);
RetValue = false;
}
else
{
VarNode = OpNode.Children[0];
ForCommand.Init = InitNode;
}
if (RetValue)
{
var EndStr = Line;
Res = Line.String.Find(new string[] { "step" }, InZ: true, NotIdChar: true);
if (Res.Position != -1)
{
EndStr = Line.TrimmedSubstring(0, Res.Position);
Line = Line.TrimmedSubstring(Res.Position + Res.String.Length);
}
// Condition
var Condition = Expressions.NewExpressionTree(EndStr, PlugIn, End: false);
var LoopVarNode = VarNode.Copy(State, PlugIn: PlugIn);
if (LoopVarNode == null || Condition == null)
{
RetValue = false;
}
else
{
var Op = Operator.Nothing;
if (Func == 0) Op = Operator.LessEqual;
else if (Func == 1) Op = Operator.GreaterEqual;
else if (Func == 2) Op = Operator.Less;
else throw new Exception("ERROR");
var Ch = new List<ExpressionNode>() { LoopVarNode, Condition };
Condition = PlugIn.NewNode(new OpExpressionNode(Op, Ch, Code));
if (Condition == null || (Condition = PlugIn.End(Condition)) == null)
RetValue = false;
ForCommand.Condition = Condition;
}
// Loop
var StepNode = (ExpressionNode)null;
PlugIn = Scope.GetPlugIn();
PlugIn.GetPlugIn<TypeMgrPlugIn>().RetType = InitNode.Type;
if (Res.Position != -1)
{
StepNode = Expressions.NewExpressionTree(Line, PlugIn, End: false);
}
else
{
PlugIn.Begin();
StepNode = PlugIn.NewNode(new ConstExpressionNode(LoopVarNode.Type, 1, Code));
}
if (StepNode != null)
{
LoopVarNode = VarNode.Copy(State, PlugIn: PlugIn);
if (LoopVarNode == null)
{
RetValue = false;
}
else
{
var Ch = new List<ExpressionNode>() { LoopVarNode, StepNode };
var Op = Operator.Nothing;
if (Res.Index == 1) Op = Operator.Subract;
else Op = Operator.Add;
StepNode = PlugIn.NewNode(new OpExpressionNode(Op, Ch, Code));
if (StepNode == null)
{
RetValue = false;
}
else
{
Ch = new List<ExpressionNode>() { LoopVarNode, StepNode };
StepNode = new OpExpressionNode(Operator.Assignment, Ch, Code);
StepNode = PlugIn.NewNode(StepNode);
if (StepNode == null || (StepNode = PlugIn.End(StepNode)) == null)
RetValue = false;
ForCommand.Loop = StepNode;
}
}
}
else
{
RetValue = false;
}
if (RetValue && !NewScope.ProcessCode())
RetValue = false;
}
}
}
if (!Scope.AddCommand(Code, ForCommand)) RetValue = false;
if (RetValue) return CommRecognizerRes.Succeeded;
else return CommRecognizerRes.Failed;
}
return CommRecognizerRes.UnknownOp;
}
}
public class MoreCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
var Spl = Code.Split(";", StringSplitOptions.RemoveEmptyEntries);
if (Spl.Count > 1)
{
foreach (var e in Spl)
{
var Trimmed = e.Trim();
if (Trimmed.String != "" && !Scope.RecognizeCommand(Trimmed, Index))
return CommRecognizerRes.Failed;
}
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class ReturnCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.String == "return")
{
var State = Scope.State;
var FScope = Scope.FuncScope;
var RetType = FScope.Type.RetType;
var Chk = true;
Line.TrimThis();
if (Line.String != "")
{
var PlugIn = Scope.GetPlugIn();
var Node = Expressions.NewExpressionTree(Line, PlugIn, false);
if (Node == null) return CommRecognizerRes.Failed;
else Node = Node.CreateAssignExpr(FScope.RetVar, Line, PlugIn, true);
if (Node == null) return CommRecognizerRes.Failed;
else if (!Scope.AddExpressionCommand(Code, Node)) return CommRecognizerRes.Failed;
Chk = false;
}
else if (!CodeScopeNode.NeedReturnVal(RetType))
{
if (!Scope.CopyRetVal(Code)) return CommRecognizerRes.Failed;
}
else
{
var TypeStrs = new[] { Scope.GlobalScope.VoidType.Name.String, RetType.Name.String };
State.Messages.Add(MessageId.CannotConvert, Code, TypeStrs);
return CommRecognizerRes.Failed;
}
var Comm = Scope.CreateRetCommand(FScope.RetLabel, Chk);
if (!Scope.AddCommand(Code, Comm))
return CommRecognizerRes.Failed;
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class VarDeclCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Scope.StartsWithType(Code))
{
if (!Scope.DeclareVariables(Code, null, VarConvMode.Assignment, GetIdMode.Function))
return CommRecognizerRes.Failed;
if (!Scope.AddCommand(Code, Scope.CreateEmptyCommand()))
return CommRecognizerRes.Failed;
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class ExprCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
var State = Scope.State;
var Rec = State.Language.ExprRecognizer.GetRecognizer<Recognizers.AssignmentRecognizer>();
#warning WARNING
if (Code.String.Find(Rec.Operators, Rec.Skip, true).Position != -1 ||
Code.String.EndsWith("++", false) || Code.String.EndsWith("--", false))
{
var Node = Expressions.NewExpressionTree(Code, Scope.GetPlugIn());
if (Node == null) return CommRecognizerRes.Failed;
if (!Scope.AddExpressionCommand(Code, Node))
return CommRecognizerRes.Failed;
else return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
public class FuncCallCommRecognizer : CommRecognizer
{
public override CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
{
if (Word.StrLen > 0)
{
var CallNode = Expressions.CreateFuncCallNode(Code, Scope.GetPlugIn());
if (CallNode == null || !Scope.AddExpressionCommand(Code, CallNode))
return CommRecognizerRes.Failed;
return CommRecognizerRes.Succeeded;
}
return CommRecognizerRes.UnknownOp;
}
}
}