Exemple #1
0
        public static IArgument String(CharSource source, ref char chr)
        {
            var str = new StringBuilder();

            while (source.Advance(out chr, true))
            {
                if (chr == '\\')
                {
                    str.Append(chr);
                    if (!source.Advance(out chr, true))
                    {
                        throw new FinalCharacterException("Expected escaped character after '\\'");
                    }
                    str.Append(chr);
                }
                else if (chr == '"')
                {
                    // If this fails (i.e. the quote is the last character), future calls to skip space will fail
                    source.Advance(out chr);
                    return(new StringLiteral()
                    {
                        Value = Regex.Unescape(str.ToString())
                    });
                }
                else
                {
                    str.Append(chr);
                }
            }
            throw new FinalCharacterException("Expected closing '\"'");
        }
Exemple #2
0
        public static IArgument TypeName(CharSource source, ref char chr)
        {
            // Arrive on seeing '/', get collections of names separated by '.'
            if (!source.Advance(out chr))
            {
                throw new FinalCharacterException("Expected type name");
            }

            var str = new StringBuilder();

            while (true)
            {
                str.Append(source.ReadName(ref chr));
                if (chr != '.')
                {
                    return(new TypeNameLiteral()
                    {
                        Value = str.ToString()
                    });
                }
                str.Append('.');
                // We now expect more
                if (!source.Advance(out chr))
                {
                    throw new FinalCharacterException("Expected further type name");
                }
                if (!CharSource.IsNameStart(chr))
                {
                    throw new InvalidCharacterException("Expected name start character: found " + chr);
                }
            }
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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
            });
        }
Exemple #6
0
        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);
            }
        }
Exemple #7
0
        public static ArgumentList Multiple(CharSource source, ref char chr, Dictionary <string, IFunction> funcs)
        {
            var args = new ArgumentList();

            // Typically get here having seen nothing or the first character already
            // Running out of text here is not an error, unless specified as more to come
            while (source.SkipWhiteSpace(ref chr))
            {
                var arg = Single(source, ref chr, funcs);
                args.Add(arg);
                if (!source.SkipWhiteSpace(ref chr))
                {
                    return(args);
                }
                else if (chr != ',')
                {
                    return(args);
                }
                source.Advance(out chr);
            }
            // No need to throw here, as if more expected single argument parsing will catch
            return(args);
        }