using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace RuriLib.LS { /// /// Parses a block from LoliScript code. /// public static class BlockParser { /// /// The allowed block identifiers. /// public enum BlockName { /// The BYPASSCF block. BYPASSCF, /// The CAPTCHA block. CAPTCHA, /// The FUNCTION block. FUNCTION, /// The KEYCHECK block. KEYCHECK, /// The PARSE block. PARSE, /// The RECAPTCHA block. RECAPTCHA, /// The REQUEST block. REQUEST, /// The TCP block. TCP, /// The UTILITY block. UTILITY, /// The BROWSERACTION block. BROWSERACTION, /// The ELEMENTACTION block. ELEMENTACTION, /// The EXECUTEJS block. EXECUTEJS, /// The NAVIGATE block. NAVIGATE } /// /// Tests if a line is parsable as a block. /// /// The data line to test /// Whether the line contains a block or not. public static bool IsBlock(string line) { return Enum.GetNames(typeof(BlockName)) .Select(n => n.ToUpper()) .Contains(GetBlockType(line).ToUpper()); } /// /// Gets the block type from a block line. /// /// The block line /// The type of the block public static string GetBlockType(string line) { var groups = Regex.Match(line, @"^!?(#[^ ]* )?([^ ]*)").Groups; return groups[2].Value; } /// /// Parses a block line as a block object. /// /// The block line /// The parsed block object public static BlockBase Parse(string line) { // Trim the line var input = line.Trim(); // Return an exception if the line is empty if (input == "") throw new ArgumentNullException(); // Parse if disabled or not var disabled = input.StartsWith("!"); if (disabled) input = input.Substring(1).Trim(); var label = LineParser.ParseToken(ref input, TokenType.Label, false); // Parse the identifier var identifier = ""; try { identifier = LineParser.ParseToken(ref input, TokenType.Parameter, true); } catch { throw new ArgumentException("Missing identifier"); } BlockBase block = null; switch ((BlockName)Enum.Parse(typeof(BlockName), identifier, true)) { case BlockName.FUNCTION: block = (new BlockFunction()).FromLS(input); break; case BlockName.KEYCHECK: block = (new BlockKeycheck()).FromLS(input); break; case BlockName.RECAPTCHA: block = (new BlockRecaptcha()).FromLS(input); break; case BlockName.REQUEST: block = (new BlockRequest()).FromLS(input); break; case BlockName.PARSE: block = (new BlockParse()).FromLS(input); break; case BlockName.CAPTCHA: block = (new BlockImageCaptcha()).FromLS(input); break; case BlockName.BYPASSCF: block = (new BlockBypassCF()).FromLS(input); break; case BlockName.UTILITY: block = (new BlockUtility()).FromLS(input); break; case BlockName.TCP: block = (new BlockTCP()).FromLS(input); break; case BlockName.NAVIGATE: block = (new SBlockNavigate()).FromLS(input); break; case BlockName.BROWSERACTION: block = (new SBlockBrowserAction()).FromLS(input); break; case BlockName.ELEMENTACTION: block = (new SBlockElementAction()).FromLS(input); break; case BlockName.EXECUTEJS: block = (new SBlockExecuteJS()).FromLS(input); break; default: throw new ArgumentException($"Invalid identifier '{identifier}'"); } // Set disabled if (block != null) block.Disabled = disabled; // Set the label if (block != null && label != "") block.Label = label.Replace("#", ""); return block; } } }