public void NumericOperation(Func <BigInteger, BigInteger, object> intInt, Func <double, double, object> doubleDouble) { var item2 = ScliptingUtil.ToNumeric(Pop()); var item1 = ScliptingUtil.ToNumeric(Pop()); if (item1 is double) { if (item2 is double) { CurrentStack.Add(doubleDouble((double)item1, (double)item2)); } else { CurrentStack.Add(doubleDouble((double)item1, (double)(BigInteger)item2)); } } else { if (item2 is double) { CurrentStack.Add(doubleDouble((double)(BigInteger)item1, (double)item2)); } else { CurrentStack.Add(intInt((BigInteger)item1, (BigInteger)item2)); } } }
public void GenerateOutput() { var index = CurrentStack.Count; while (index > 0 && !(CurrentStack[index - 1] is Mark)) { index--; } for (; index < CurrentStack.Count; index++) { _output.Append(ScliptingUtil.ToString(CurrentStack[index])); } }
public void NumericOperation(Func <BigInteger, object> fromInt, Func <double, object> fromDouble) { var item = ScliptingUtil.ToNumeric(Pop()); if (item is double) { CurrentStack.Add(fromDouble((double)item)); } else { CurrentStack.Add(fromInt((BigInteger)item)); } }
private static void findMatchingEnd(string source, int start, int addIndex, out int?conditionEndIndex, out int?elseIndex, out bool elsePops, out int endIndex) { conditionEndIndex = null; elseIndex = null; elsePops = false; var depth = 0; Instruction instruction; NodeType type; for (int i = start; i < source.Length; i++) { if (ScliptingUtil.GetInstructionInfo(source[i], out instruction, out type)) { if (type == NodeType.BlockHead) { depth++; } else if (type == NodeType.BlockConditionEnd && depth == 1) { if (conditionEndIndex != null) { throw new CompileException("“{0}” block cannot have multiple condition-block instructions.".Fmt(source[start]), start + addIndex, i - start + addIndex + 1); } conditionEndIndex = i; } else if (type == NodeType.BlockElse && depth == 1) { if (elseIndex != null) { throw new CompileException("“{0}” block cannot have multiple else-block instructions.".Fmt(source[start]), start + addIndex, i - start + addIndex + 1); } elseIndex = i; elsePops = source[i] == '不'; } else if (type == NodeType.BlockEnd) { depth--; if (depth == 0) { endIndex = i; return; } } } } throw new CompileException("Block instruction “{0}” is missing a matching end instruction.".Fmt(source[start]), start + addIndex, 1); }
private string describe(object item) { byte[] b; List <object> list; Function fnc; if ((b = item as byte[]) != null) { return("Byte array: “{0}” ({1})".Fmt(b.FromUtf8().CLiteralEscape(), ScliptingUtil.ToInt(b))); } else if (item is BigInteger) { return("Integer: {0}".Fmt(item)); } else if (item is string) { return("String: “{0}”".Fmt(((string)item).CLiteralEscape())); } else if (item is double) { return("Float: {0}".Fmt(ExactConvert.ToString((double)item))); } else if (item is Mark) { return("Mark"); } else if ((list = item as List <object>) != null) { return("List ({0} items)".Fmt(list.Count) + list.Select((itm, idx) => Environment.NewLine + describe(itm, idx)).JoinString().Indent(4, false)); } else if ((fnc = item as Function) != null) { return("Function" + (fnc.CapturedItem != null ? "; capture: " + describe(fnc.CapturedItem) : "; no capture")); } // unknown type of object? return("{0} ({1})".Fmt(item, item.GetType().FullName)); }
public static List <Node> Parse(string source, int addIndex) { Instruction instruction; NodeType type; ListStringInstruction listStringType; bool backwards; var ret = new List <Node>(); int index = 0; while (index < source.Length) { var ch = source[index]; if (ch < 0x0100) { // can wlite comments using infeliol Amelican and Eulopean chalactels index++; } else if (ch >= 0xac00 && ch < 0xbc00) { // Beginning of byte allay var origIndex = index; var hangeul = ParseByteArrayToken(source, index); index += hangeul.Length; try { ret.Add(new ByteArray { Array = ScliptingUtil.DecodeByteArray(hangeul), Index = origIndex + addIndex, Count = index - origIndex }); } catch (CompileException ce) { throw new CompileException(ce.Message, ce.Index + origIndex + addIndex, ce.Length); } } else if (ch >= 0xbc00 && ch <= 0xd7a3) { ret.Add(new NegativeNumber { Number = 0xbbff - ch, Index = index++ + addIndex, Count = 1 }); } else if (ch >= '①' && ch <= '⑳') { ret.Add(new StackOrRegexNode { Type = StackOrRegexNodeType.CopyFromBottom, Value = ch - '①' + 1, Index = index++ + addIndex, Count = 1 }); } else if (ch >= '㉑' && ch <= '㉟') { ret.Add(new StackOrRegexNode { Type = StackOrRegexNodeType.CopyFromBottom, Value = ch - '㉑' + 21, Index = index++ + addIndex, Count = 1 }); } else if (ch >= '㊱' && ch <= '㊿') { ret.Add(new StackOrRegexNode { Type = StackOrRegexNodeType.CopyFromBottom, Value = ch - '㊱' + 36, Index = index++ + addIndex, Count = 1 }); } else if (ch >= '⓵' && ch <= '⓾') { ret.Add(new StackOrRegexNode { Type = StackOrRegexNodeType.MoveFromTop, Value = ch - '⓵' + 1, Index = index++ + addIndex, Count = 1 }); } else if (ch >= '❶' && ch <= '❿') { ret.Add(new StackOrRegexNode { Type = StackOrRegexNodeType.CopyFromTop, Value = ch - '❶' + 1, Index = index++ + addIndex, Count = 1 }); } else if (ch >= '⓫' && ch <= '⓴') { ret.Add(new StackOrRegexNode { Type = StackOrRegexNodeType.CopyFromTop, Value = ch - '⓫' + 11, Index = index++ + addIndex, Count = 1 }); } else if (ch >= '⑴' && ch <= '⒇') { ret.Add(new StackOrRegexNode { Type = StackOrRegexNodeType.MoveFromBottom, Value = ch - '⑴' + 1, Index = index++ + addIndex, Count = 1 }); } else if (ch >= '⒈' && ch <= '⒛') { ret.Add(new StackOrRegexNode { Type = StackOrRegexNodeType.SwapFromBottom, Value = ch - '⒈' + 1, Index = index++ + addIndex, Count = 1 }); } else if (ch >= 'Ⓐ' && ch <= 'Ⓩ') { ret.Add(new StackOrRegexNode { Type = StackOrRegexNodeType.RegexCapture, Value = ch - 'Ⓐ' + 1, Index = index++ + addIndex, Count = 1 }); } else if (ListStringElementNode.Characters.Contains(ch)) { ret.Add(new ListStringElementNode(ch, index++ + addIndex)); } else if (ScliptingUtil.GetInstructionInfo(ch, out listStringType, out backwards)) { ret.Add(new ListStringElementNode(listStringType, backwards, index++ + addIndex)); } else if (ScliptingUtil.GetInstructionInfo(ch, out instruction, out type)) { switch (type) { case NodeType.SingularNode: ret.Add(new SingularNode { ThisInstruction = instruction, Index = index++ + addIndex, Count = 1 }); break; case NodeType.FunctionExecutionNode: ret.Add(new ExecuteFunction { Instruction = instruction, Index = index++ + addIndex, Count = 1 }); break; case NodeType.BlockHead: int? conditionEndIndex; int? elseIndex; bool elsePops; int endIndex; findMatchingEnd(source, index, addIndex, out conditionEndIndex, out elseIndex, out elsePops, out endIndex); var primaryBlock = Parse(source.Substring(index + 1, (conditionEndIndex ?? elseIndex ?? endIndex) - index - 1), index + 1 + addIndex); List <Node> conditionBlock = null; if (conditionEndIndex != null) { conditionBlock = primaryBlock; primaryBlock = Parse(source.Substring(conditionEndIndex.Value + 1, (elseIndex ?? endIndex) - conditionEndIndex.Value - 1), conditionEndIndex.Value + 1 + addIndex); } var elseBlock = elseIndex == null ? null : Parse(source.Substring(elseIndex.Value + 1, endIndex - elseIndex.Value - 1), elseIndex.Value + 1 + addIndex); var blockInstr = BlockNode.Create(ch, instruction, index, addIndex, conditionEndIndex, elseIndex, elsePops); blockInstr.PrimaryBlock = primaryBlock; blockInstr.ConditionBlock = conditionBlock; blockInstr.ConditionEndIndex = (conditionEndIndex ?? 0) + addIndex; blockInstr.ElseBlock = elseBlock; blockInstr.ElseBlockPops = elsePops; blockInstr.Index = index + addIndex; blockInstr.Count = endIndex - index + 1; blockInstr.ElseIndex = (elseIndex ?? 0) + addIndex; ret.Add(blockInstr); index = endIndex + 1; break; case NodeType.BlockElse: case NodeType.BlockEnd: throw new CompileException("Else or end instruction encountered without a matching block head instruction.", index + addIndex, 1); default: throw new CompileException("Unrecognised instruction: “{0}”.".Fmt(ch), index + addIndex, 1); } } else { throw new CompileException("Unrecognised instruction: “{0}”.".Fmt(ch), index + addIndex, 1); } } return(ret); }