private static int readVarArgOnlyCmd(CmdType cmd, string scmd, ref List <Token> ts, ref List <byte> bytes, ref List <string> vars, int i, ref int argCount) { argCount = 0; while (!isKeyWordOrProcName(ts[i]) && !Syntax.IsTokenHasOperator(ts[i], Syntax.OP_END)) { if (Syntax.IsEnumOperator(ts[i]) || ts[i].Type == TknType.NewLine) { i++; continue; } if (ts[i].Type != TknType.Word) { new CompileException(inFile(ref ts, i), inLine(ref ts, i), ErrCode.InvalidArgument, $"'{ts[i].Text}' for {scmd}"); } if (!vars.Contains(ts[i].Text)) { new CompileException(inFile(ref ts, i), inLine(ref ts, i), ErrCode.UndefinedVariable, ts[i].Text); } bytes.AddCmd(cmd, (uint)getVarID(ref vars, ts[i].Text)); argCount++; i++; } return(i); }
private static int seekOperator(ref List <Token> ts, int i, string op) { while (!Syntax.IsTokenHasOperator(ts[i], op)) { i++; } return(i); }
/// <summary> Proc, if, while... bodies! </summary> private static int readNextBody(ref List <Token> ts, ref List <byte> bytes, ref List <string> vars, int i) { i++; while (!Syntax.IsTokenHasOperator(ts[i], "}")) { i = readNextExpr(ref ts, ref bytes, ref vars, i); } return(i); }
private static int readOutput(CmdType cmd_v, CmdType cmd_i, string scmd, ref List <Token> ts, ref List <byte> bytes, ref List <string> vars, int i) { List <byte> content = new List <byte>(); while (!isKeyWordOrProcName(ts[i]) && !Syntax.IsTokenHasOperator(ts[i], Syntax.OP_END)) { if (Syntax.IsEnumOperator(ts[i])) { i++; continue; } switch (ts[i].Type) { case TknType.Char: content.Add((byte)ts[i].Text[0]); break; case TknType.String: for (int j = 0; j < ts[i].Text.Length; j++) { content.Add((byte)ts[i].Text[j]); } break; case TknType.Number: content.Add(toByte(ts[i].Text, inFile(ref ts, i), inLine(ref ts, i))); break; case TknType.Word: for (int q = 0; q < content.Count; q += 3) { bytes.AddCmd(CmdType.OUT_3C, content.AtOrNull(q), content.AtOrNull(q + 1), content.AtOrNull(q + 2)); } content.Clear(); // if (!vars.Contains(ts[i].Text)) { new CompileException(inFile(ref ts, i), inLine(ref ts, i), ErrCode.UndefinedVariable, ts[i].Text); } bytes.AddCmd(CmdType.OUT_B, (uint)getVarID(ref vars, ts[i].Text)); break; default: break; } i++; } for (int q = 0; q < content.Count; q += 3) { bytes.AddCmd(CmdType.OUT_3C, content.AtOrNull(q), content.AtOrNull(q + 1), content.AtOrNull(q + 2)); } content.Clear(); return(i); }
private static int readWhile(ref List <Token> ts, ref List <byte> bytes, ref List <string> vars, int i) { //while [var | has | pop | const] { ... } //ARGUMENT: Token arg = ts[i]; switch (arg.Type) { case TknType.Number: bytes.AddCmd(CmdType.WHILE_C, toByte(arg.Text, inFile(ref ts, i), inLine(ref ts, i))); break; case TknType.Char: bytes.AddCmd(CmdType.WHILE_C, (byte)arg.Text[0]); break; case TknType.Word: switch (arg.Text) { case Syntax.OP_HAS: bytes.AddCmd(CmdType.WHL_HAS); break; case Syntax.KW_POP: bytes.AddCmd(CmdType.WHL_POP); break; default: if (!vars.Contains(arg.Text)) { new CompileException(inFile(ref ts, i), inLine(ref ts, i), ErrCode.UndefinedVariable, arg.Text); } bytes.AddCmd(CmdType.WHILE_B, (uint)getVarID(ref vars, arg.Text)); break; } break; default: new CompileException(inFile(ref ts, i), inLine(ref ts, i), ErrCode.InvalidArgument, $"'{arg.Text}' for while"); break; } //SEEK BODY ('{'): i++; while (!Syntax.IsTokenHasOperator(ts[i], Syntax.OP_BEGIN)) { if (ts[i].Type != TknType.NewLine) { new CompileException(inFile(ref ts, i), inLine(ref ts, i), ErrCode.UndefinedBody, "while"); } i++; } //READ BODY: i = readNextBody(ref ts, ref bytes, ref vars, i) + 1; //END: bytes.AddCmd(CmdType.WHL_END); return(i); }
private static int readCmd(CmdType cmd_v, CmdType cmd_i, string scmd, ref List <Token> ts, ref List <byte> bytes, ref List <string> vars, int i) { while (!isKeyWordOrProcName(ts[i]) && !Syntax.IsTokenHasOperator(ts[i], Syntax.OP_END)) { if (Syntax.IsEnumOperator(ts[i])) { i++; continue; } switch (ts[i].Type) { case TknType.Char: bytes.AddCmd(cmd_v, (byte)ts[i].Text[0]); break; case TknType.String: for (int j = 0; j < ts[i].Text.Length; j++) { bytes.AddCmd(cmd_v, (byte)ts[i].Text[j]); } break; case TknType.Number: bytes.AddCmd(cmd_v, toByte(ts[i].Text, inFile(ref ts, i), inLine(ref ts, i))); break; case TknType.Word: if (!vars.Contains(ts[i].Text)) { new CompileException(inFile(ref ts, i), inLine(ref ts, i), ErrCode.UndefinedVariable, ts[i].Text); } bytes.AddCmd(cmd_i, (uint)getVarID(ref vars, ts[i].Text)); break; default: break; } i++; } return(i); }
/// <summary> Proc calls or keywords </summary> private static int readNextExpr(ref List <Token> ts, ref List <byte> bytes, ref List <string> vars, int i) { int argCount = 0; //[cmd] [ [ops | null] args | null] //Need command or newline: if (ts[i].Type == TknType.NewLine || Syntax.IsEnumOperator(ts[i])) { return(i + 1); } if (ts[i].Type != TknType.Word) { new CompileException(inFile(ref ts, i), inLine(ref ts, i), ErrCode.UndefinedCommand, ts[i].Text); } // string cmd = ts[i].Text; i++; //to args if (IsProcessName(cmd)) { //push args: while (!isKeyWordOrProcName(ts[i]) && !Syntax.IsTokenHasOperator(ts[i], Syntax.OP_END)) { bytes.AddRange(pushArg(ts[i], ref vars, inFile(ref ts, i), inLine(ref ts, i))); i++; } //call proc: bytes.AddCmd(CmdType.RUN_ID, (uint)getProcID(cmd)); } else { switch (cmd) { //new var case Syntax.KW_BYTE: while (!isKeyWordOrProcName(ts[i])) { if (Syntax.IsEnumOperator(ts[i]) || ts[i].Type == TknType.NewLine) { i++; continue; } if (ts[i].Type != TknType.Word) { new CompileException(inFile(ref ts, i), inLine(ref ts, i), ErrCode.InvalidArgument, $"'{ts[i].Text}' for {cmd}"); } if (!vars.Contains(ts[i].Text)) { vars.Add(ts[i].Text); } bytes.AddCmd(CmdType.BYTE_I, (uint)getVarID(ref vars, ts[i].Text)); i++; } break; //var or value case Syntax.KW_ADD: i = readCmd(CmdType.ADD_V, CmdType.ADD_I, cmd, ref ts, ref bytes, ref vars, i); break; case Syntax.KW_DIVIDE: i = readCmd(CmdType.DIV_V, CmdType.DIV_I, cmd, ref ts, ref bytes, ref vars, i); break; case Syntax.KW_IS: i = readCmd(CmdType.IS_V, CmdType.IS_I, cmd, ref ts, ref bytes, ref vars, i); break; case Syntax.KW_MODULE: i = readCmd(CmdType.MOD_C, CmdType.MOD_B, cmd, ref ts, ref bytes, ref vars, i); break; case Syntax.KW_MULTIPLY: i = readCmd(CmdType.MUL_V, CmdType.MUL_I, cmd, ref ts, ref bytes, ref vars, i); break; case Syntax.KW_PUSH: i = readCmd(CmdType.PUSH_V, CmdType.PUSH_I, cmd, ref ts, ref bytes, ref vars, i); break; case Syntax.KW_SUBTRACT: i = readCmd(CmdType.SUB_V, CmdType.SUB_I, cmd, ref ts, ref bytes, ref vars, i); break; //roots case Syntax.KW_IF: i = readIf(ref ts, ref bytes, ref vars, i); break; case Syntax.KW_WHILE: i = readWhile(ref ts, ref bytes, ref vars, i); break; //var only case Syntax.KW_THIS: i = readVarArgOnlyCmd(CmdType.THIS_I, cmd, ref ts, ref bytes, ref vars, i, ref argCount); break; case Syntax.KW_POP: i = readVarArgOnlyCmd(CmdType.POP_I, cmd, ref ts, ref bytes, ref vars, i, ref argCount); if (argCount == 0) { bytes.AddCmd(CmdType.POP); } break; case Syntax.KW_PEEK: i = readVarArgOnlyCmd(CmdType.PEEK_B, cmd, ref ts, ref bytes, ref vars, i, ref argCount); break; case Syntax.KW_DECREMENT: i = readVarArgOnlyCmd(CmdType.DEC_B, cmd, ref ts, ref bytes, ref vars, i, ref argCount); break; case Syntax.KW_INCREMENT: i = readVarArgOnlyCmd(CmdType.INC_B, cmd, ref ts, ref bytes, ref vars, i, ref argCount); break; case Syntax.KW_NOT: i = readVarArgOnlyCmd(CmdType.NOT_B, cmd, ref ts, ref bytes, ref vars, i, ref argCount); break; case Syntax.KW_INPUT: i = readVarArgOnlyCmd(CmdType.INPUT_B, cmd, ref ts, ref bytes, ref vars, i, ref argCount); if (argCount == 0) { bytes.AddCmd(CmdType.INPUT); } break; //var or 3 value case Syntax.KW_OUTPUT: i = readOutput(CmdType.SUB_V, CmdType.SUB_I, cmd, ref ts, ref bytes, ref vars, i); break; //null case Syntax.KW_FLIP: bytes.AddCmd(CmdType.FLIP); break; case Syntax.KW_STOP: bytes.AddCmd(CmdType.PRC_STP); break; case Syntax.KW_OUTCLEAR: bytes.AddCmd(CmdType.CLR_OUT); break; case Syntax.KW_STACLEAR: bytes.AddCmd(CmdType.CLR_STK); break; case Syntax.KW_PUSH_THIS: bytes.AddCmd(CmdType.PUSH_T); break; case Syntax.KW_POP_THIS: bytes.AddCmd(CmdType.POP_T); break; // default: new CompileException(inFile(ref ts, i), inLine(ref ts, i), ErrCode.UndefinedCommand, cmd); break; } } Console.Write($"\r{(int)((float)i * 100.0 / ts.Count)}%"); return(i); }