public static IArgument Function(CharSource source, ref char chr, Dictionary <string, IFunction> funcs) { // Arrive here having seen '(' if (!source.AdvanceWhiteSpace(out chr)) { throw new FinalCharacterException("Expected a function name"); } var name = Arguments.Single(source, ref chr, funcs); if (!(name is NameArgument nameArg)) { throw new InvalidArgumentException($"Function name type error: Type = {name.GetType().Name}, Value = {name.ToString()}"); } if (!funcs.TryGetValue(nameArg.Value, out var func)) { throw new InvalidArgumentException($"Function does not exist: \"{nameArg.Value}\""); } // Get next character: if (!source.SkipWhiteSpace(ref chr)) { throw new FinalCharacterException("Expected closing ')'"); } var funcArg = new FunctionArgument() { Call = new FunctionCall(0) // Line number doesn't really matter, as this isn't a whole statement { Function = func } }; if (chr == ':') { // Arguments to go with it if (!source.AdvanceWhiteSpace(out chr)) { throw new FinalCharacterException("Expected argument list"); } funcArg.Call.Arguments = Arguments.Multiple(source, ref chr, funcs); // Get closing bracket if (!source.SkipWhiteSpace(ref chr)) { throw new FinalCharacterException("Expected closing ')'"); } else if (chr != ')') { throw new InvalidCharacterException($"Expected closing ')': found '{chr}'"); } } else if (chr != ')') { throw new InvalidCharacterException($"Expected closing ')' or arguments (':'): found '{chr}'"); } source.Advance(out chr); return(funcArg); }
private static string[] AssignTargets(CharSource source, ref char chr, Dictionary <string, IFunction> funcs) { // Seen '=' if (!source.Advance(out chr)) { throw new FinalCharacterException("Expected assignment token, \"=>\""); } else if (chr != '>') { throw new InvalidCharacterException($"Expected assignment token, \"=>\": found \"={chr}\""); } if (!source.AdvanceWhiteSpace(out chr)) { throw new FinalCharacterException("Expected assignment"); } var right = Arguments.Multiple(source, ref chr, funcs).Evaluate(); if (!right.All(t => t is NameArgument)) { throw new InvalidArgumentException($"Assigned types must be names"); } var names = right.Select(t => (t as NameArgument).Value).ToArray(); return(names); }
private static Statement CallArguments(CharSource source, ref char chr, Dictionary <string, IFunction> funcs, IFunction func, int line) { // Arrive on ':' if (!source.AdvanceWhiteSpace(out chr)) { throw new FinalCharacterException("Expected function arguments"); } var args = Arguments.Multiple(source, ref chr, funcs); var fcall = new FunctionCall(line) { Function = func, Arguments = args }; return(chr == '=' ? Assign(source, ref chr, funcs, fcall, line) : fcall); }
public static IArgument Number(CharSource source, ref char chr) { var integral = source.ReadInt(ref chr); if (chr == '.') { if (!source.Advance(out chr)) { throw new FinalCharacterException("Expected fractional value after '.'"); } else if (!char.IsDigit(chr)) { throw new InvalidCharacterException($"Expected fractional value after '.': found '{chr}'"); } var fractional = source.ReadFractional(ref chr); var mantissa = integral >= 0 ? integral + fractional : integral - fractional; if (char.ToLower(chr) == 'e') { if (!source.AdvanceWhiteSpace(out chr)) { throw new FinalCharacterException("Expected exponent after 'e'"); } else if (!CharSource.IsNumberStart(chr)) { throw new InvalidCharacterException($"Expected exponent after 'e': found '{chr}'"); } var exponent = source.ReadInt(ref chr); mantissa *= Math.Pow(10, exponent); } return(new DoubleLiteral() { Value = mantissa }); } return(new IntegerLiteral() { Value = integral }); }
public static IArgument Executable(CharSource source, ref char chr, Dictionary <string, IFunction> funcs) { // Having seen '<' if (!source.AdvanceWhiteSpace(out chr)) { throw new FinalCharacterException("Expected statements, or closing '>'"); } var exec = new ExecutableArgument(); // Statement reading takes us to the first character of the next potential while (true) { if (chr == '>') { source.Advance(out chr); return(exec); } var statement = Statement(source, ref chr, funcs); exec.Value.Add(statement); } }