Example #1
0
        public override IMatched <Unit> Parse(ParseState state, Token[] tokens, ExpressionBuilder builder)
        {
            var type = AlternateStringType.Standard;

            switch (tokens[2].Text)
            {
            case "r":
                type = AlternateStringType.Raw;
                break;

            case "l":
                type = AlternateStringType.List;
                break;
            }

            state.Colorize(tokens, Color.Whitespace, Color.StringPart, Color.String);

            var stringBuilder = new StringBuilder();
            var escaped       = false;
            var start         = state.Index;
            var length        = 0;

            while (state.More)
            {
                var ch = state.CurrentSource[0];
                switch (ch)
                {
                case '"':
                    if (escaped)
                    {
                        stringBuilder.Append('"');
                        escaped = false;
                    }
                    else if (state.CurrentSource.Drop(1).StartsWith("\""))
                    {
                        escaped = true;
                    }
                    else
                    {
                        state.Move(1);
                        state.AddToken(start, length + 1, Color.String);
                        if (type == AlternateStringType.List)
                        {
                            builder.Add(new StringListSymbol(stringBuilder.ToString()));
                        }
                        else
                        {
                            builder.Add(new StringSymbol(stringBuilder.ToString()));
                        }

                        return(Unit.Matched());
                    }

                    break;

                default:
                    stringBuilder.Append(ch);
                    escaped = false;
                    break;
                }

                length++;
                state.Move(1);
            }

            return(failedMatch <Unit>(openString()));
        }
Example #2
0
        public override IMatched <Unit> Parse(ParseState state, Token[] tokens, ExpressionBuilder builder)
        {
            state.Colorize(tokens, Color.Whitespace, Color.Structure);

            var pattern    = new StringBuilder();
            var type       = RegexParsingType.Outside;
            var ignoreCase = false;
            var multiline  = false;
            var global     = false;
            var textOnly   = false;

            while (state.More)
            {
                var ch = state.CurrentSource[0];

                switch (type)
                {
                case RegexParsingType.Outside:
                    switch (ch)
                    {
                    case '\\':
                        state.AddToken(Color.Structure);
                        state.Move(1);
                        builder.Add(new RegexSymbol(pattern.ToString(), ignoreCase, multiline, global, textOnly));

                        return(Unit.Matched());

                    case '\'':
                        type = RegexParsingType.WaitingForSingleQuote;
                        pattern.Append(ch);
                        state.AddToken(Color.String);
                        break;

                    case '"':
                        type = RegexParsingType.WaitingForDoubleQuote;
                        pattern.Append(ch);
                        state.AddToken(Color.String);
                        break;

                    case ';':
                        type = RegexParsingType.AwaitingOption;
                        state.AddToken(Color.Structure);
                        break;

                    default:
                        pattern.Append(ch);
                        var color = Color.Operator;
                        switch (ch)
                        {
                        case '{':
                        case '}':
                        case '>':
                        case '<':
                        case '[':
                        case ']':
                        case ',':
                        case '|':
                        case '(':
                        case ')':
                            color = Color.Structure;
                            break;

                        default:
                            if (char.IsNumber(ch))
                            {
                                color = Color.Number;
                            }
                            else if (char.IsLetter(ch))
                            {
                                color = Color.Identifier;
                            }

                            break;
                        }

                        state.AddToken(color);
                        break;
                    }

                    break;

                case RegexParsingType.WaitingForSingleQuote:
                    switch (ch)
                    {
                    case '\'':
                        type = RegexParsingType.Outside;
                        break;

                    case '\\':
                        type = RegexParsingType.EscapedSingleQuote;
                        break;
                    }

                    pattern.Append(ch);
                    state.AddToken(Color.String);
                    break;

                case RegexParsingType.WaitingForDoubleQuote:
                    switch (ch)
                    {
                    case '"':
                        type = RegexParsingType.Outside;
                        break;

                    case '\\':
                        type = RegexParsingType.EscapedDoubleQuote;
                        break;
                    }

                    pattern.Append(ch);
                    state.AddToken(Color.String);
                    break;

                case RegexParsingType.EscapedSingleQuote:
                    type = RegexParsingType.WaitingForSingleQuote;
                    pattern.Append(ch);
                    state.AddToken(Color.String);
                    break;

                case RegexParsingType.EscapedDoubleQuote:
                    type = RegexParsingType.WaitingForDoubleQuote;
                    pattern.Append(ch);
                    state.AddToken(Color.String);
                    break;

                case RegexParsingType.AwaitingOption:
                    switch (ch)
                    {
                    case 'i':
                    case 'I':
                        ignoreCase = true;
                        break;

                    case 'm':
                    case 'M':
                        multiline = true;
                        break;

                    case 'g':
                    case 'G':
                        global = true;
                        break;

                    case 't':
                    case 'T':
                        textOnly = true;
                        break;

                    case '\\':
                        state.AddToken(Color.Structure);
                        state.Move(1);
                        builder.Add(new RegexSymbol(pattern.ToString(), ignoreCase, multiline, global, textOnly));
                        return(Unit.Matched());

                    default:
                        return($"Didn't understand option '{ch}'".FailedMatch <Unit>());
                    }

                    state.AddToken(Color.Symbol);
                    break;
                }

                state.Move(1);
            }

            return("Open regex".FailedMatch <Unit>());
        }
Example #3
0
        public override IMatched <Unit> Parse(ParseState state, Token[] tokens, ExpressionBuilder builder)
        {
            var prefix  = tokens[2].Text;
            var mutable = prefix == "m";
            var binary  = prefix == "b";
            var symbol  = prefix == "`";

            state.Colorize(tokens, Color.Whitespace, Color.StringPart, Color.String);

            var text    = new StringBuilder();
            var escaped = false;
            var index   = state.Index;
            var length  = 0;
            var hex     = false;
            var hexText = new StringBuilder();

            while (state.More)
            {
                var ch = state.CurrentSource[0];
                switch (ch)
                {
                case '"':
                    if (escaped)
                    {
                        text.Append('"');
                        escaped = false;
                        break;
                    }

                    if (hex)
                    {
                        if (fromHex(hexText.ToString()).If(out var matchedChar, out var anyException))
                        {
                            text.Append(matchedChar);
                        }
                        else if (anyException.If(out var exception))
                        {
                            return(failedMatch <Unit>(exception));
                        }
                        else
                        {
                            return(failedMatch <Unit>(badHex(hexText.ToString())));
                        }
                    }

                    state.Move(1);
                    state.AddToken(index, length + 1, Color.String);
                    if (mutable)
                    {
                        builder.Add(new MutStringSymbol(text.ToString()));
                        return(Unit.Matched());
                    }
                    else if (binary)
                    {
                        builder.Add(new ByteArraySymbol(text.ToString()));
                        return(Unit.Matched());
                    }
                    else if (symbol)
                    {
                        builder.Add(new SymbolSymbol(text.ToString()));
                        return(Unit.Matched());
                    }
                    else
                    {
                        builder.Add(new StringSymbol(text.ToString()));
                        return(Unit.Matched());
                    }

                case '\\':
                    if (escaped)
                    {
                        text.Append('\\');
                        escaped = false;
                        break;
                    }

                    escaped = true;
                    break;

                case 'n':
                    if (escaped)
                    {
                        text.Append('\n');
                        escaped = false;
                        break;
                    }

                    text.Append('n');
                    break;

                case 'r':
                    if (escaped)
                    {
                        text.Append('\r');
                        escaped = false;
                        break;
                    }

                    text.Append('r');
                    break;

                case 't':
                    if (escaped)
                    {
                        text.Append('\t');
                        escaped = false;
                        break;
                    }

                    text.Append('t');
                    break;

                case 'u':
                    if (escaped)
                    {
                        hex = true;
                        hexText.Clear();
                        escaped = false;
                        break;
                    }

                    text.Append('u');
                    break;

                case '{':
                    if (escaped)
                    {
                        hex = true;
                        hexText.Clear();
                        escaped = false;
                        break;
                    }

                    text.Append('{');
                    break;

                default:
                    if (hex)
                    {
                        if (ch.Between('0').And('9') || ch.Between('a').And('f') && hexText.Length < 6)
                        {
                            hexText.Append(ch);
                        }
                        else
                        {
                            hex = false;
                            if (fromHex(hexText.ToString()).ValueOrCast <Unit>(out var matchedChar, out var asUnit))
                            {
                                text.Append(matchedChar);
                            }
                            else if (asUnit.IsFailedMatch)
                            {
                                return(asUnit);
                            }

                            if (ch == 96)
                            {
                                text.Append(ch);
                            }
                        }
                    }
                    else
                    {
                        text.Append(ch);
                    }

                    escaped = false;
                    break;
                }

                length++;
                state.Move(1);
            }

            return(failedMatch <Unit>(openString()));
        }
        public override IMatched <Unit> Parse(ParseState state, Token[] tokens, ExpressionBuilder builder)
        {
            var isFailure = tokens[2].Text == "f";

            state.Colorize(tokens, Color.Whitespace, Color.StringPart, Color.String);

            var firstString = none <string>();
            var expressions = new List <Expression>();
            var suffixes    = new List <string>();
            var text        = new StringBuilder();
            var escaped     = false;
            var index       = state.Index;
            var length      = 0;
            var hex         = false;
            var hexText     = new StringBuilder();

            while (state.More)
            {
                var ch = state.CurrentSource[0];
                switch (ch)
                {
                case '"':
                {
                    if (escaped)
                    {
                        text.Append('"');
                        escaped = false;
                        break;
                    }

                    if (hex)
                    {
                        if (fromHex(hexText.ToString()).If(out var matchedChar, out var anyException))
                        {
                            text.Append(matchedChar);
                        }
                        else if (anyException.If(out var exception))
                        {
                            return(failedMatch <Unit>(exception));
                        }
                        else
                        {
                            return(failedMatch <Unit>(badHex(hexText.ToString())));
                        }
                    }

                    state.Move(1);
                    state.AddToken(index, length + 1, Color.String);

                    var symbol = firstString.Map(prefix =>
                        {
                            suffixes.Add(text.ToString());
                            var expressionsArray = expressions.ToArray();
                            var suffixesArray    = suffixes.ToArray();
                            return((Symbol) new InterpolatedStringSymbol(prefix, expressionsArray, suffixesArray, isFailure));
                        }).DefaultTo(() => new StringSymbol(text.ToString(), isFailure));
                    builder.Add(symbol);

                    return(Unit.Matched());
                }

                case '(':
                {
                    if (escaped)
                    {
                        text.Append('(');
                        escaped = false;
                        break;
                    }

                    state.Move(1);
                    state.AddToken(index, length, Color.String);
                    state.AddToken(index + length, 1, Color.OpenParenthesis);

                    if (firstString.IsNone)
                    {
                        firstString = text.ToString().Some();
                    }
                    else
                    {
                        suffixes.Add(text.ToString());
                    }

                    text.Clear();

                    if (getExpression(state, "^ /')'", builder.Flags, Color.CloseParenthesis)
                        .If(out var expression, out var anyException))
                    {
                        expressions.Add(expression);
                        index  = state.Index;
                        length = 0;
                        continue;
                    }
                    else if (anyException.If(out var exception))
                    {
                        return(failedMatch <Unit>(exception));
                    }
                    else
                    {
                        return(failedMatch <Unit>(expectedExpression()));
                    }
                }

                case '\\':
                    if (escaped)
                    {
                        text.Append('\\');
                        escaped = false;
                        break;
                    }

                    escaped = true;
                    break;

                case 'n':
                    if (escaped)
                    {
                        text.Append('\n');
                        escaped = false;
                        break;
                    }

                    text.Append('n');
                    break;

                case 'r':
                    if (escaped)
                    {
                        text.Append('\r');
                        escaped = false;
                        break;
                    }

                    text.Append('r');
                    break;

                case 't':
                    if (escaped)
                    {
                        text.Append('\t');
                        escaped = false;
                        break;
                    }

                    text.Append('t');
                    break;

                case 'u':
                    if (escaped)
                    {
                        hex = true;
                        hexText.Clear();
                        escaped = false;
                        break;
                    }

                    text.Append('u');
                    break;

                default:
                {
                    if (escaped)
                    {
                        if (ch.Between('0').And('9') || ch.Between('a').And('f') && hexText.Length < 6)
                        {
                            hexText.Append(ch);
                        }
                        else
                        {
                            escaped = false;
                            if (fromHex(hexText.ToString()).If(out var charMatched, out var anyException))
                            {
                                hexText.Append(charMatched);
                                hexText.Append(ch);
                            }
                            else if (anyException.If(out var exception))
                            {
                                return(failedMatch <Unit>(exception));
                            }
                            else
                            {
                                return(failedMatch <Unit>(badHex(hexText.ToString())));
                            }
                        }
                    }
                    else
                    {
                        text.Append(ch);
                    }

                    escaped = false;
                }
                break;
                }

                length++;
                state.Move(1);
            }

            return(failedMatch <Unit>(openString()));
        }
        public override IMatched <Unit> Parse(ParseState state, Token[] tokens, ExpressionBuilder builder)
        {
            state.Colorize(tokens, Color.Whitespace, Color.String, Color.String);
            var text    = new StringBuilder();
            var escaped = false;
            var index   = state.Index;
            var length  = 0;
            var hex     = false;
            var hexText = new StringBuilder();

            while (state.More && !state.CurrentSource.IsMatch("^ (/r /n | /r | /n) [dquote]3"))
            {
                var ch = state.CurrentSource[0];
                switch (ch)
                {
                case '\\':
                    if (escaped)
                    {
                        text.Append('\\');
                        escaped = false;
                        break;
                    }

                    escaped = true;
                    break;

                case 'n':
                    if (escaped)
                    {
                        text.Append('\n');
                        escaped = false;
                        break;
                    }

                    text.Append('n');
                    break;

                case 'r':
                    if (escaped)
                    {
                        text.Append('\r');
                        escaped = false;
                        break;
                    }

                    text.Append('r');
                    break;

                case 't':
                    if (escaped)
                    {
                        text.Append('\t');
                        escaped = false;
                        break;
                    }

                    text.Append('t');
                    break;

                case 'u':
                    if (escaped)
                    {
                        hex = true;
                        hexText.Clear();
                        escaped = false;
                        break;
                    }

                    text.Append('u');
                    break;

                case '{':
                    if (escaped)
                    {
                        hex = true;
                        hexText.Clear();
                        escaped = false;
                        break;
                    }

                    text.Append('{');
                    break;

                default:
                    if (hex)
                    {
                        if (ch.Between('0').And('9') || ch.Between('a').And('f') && hexText.Length < 6)
                        {
                            hexText.Append(ch);
                        }
                        else
                        {
                            hex = false;
                            if (fromHex(hexText.ToString()).ValueOrCast <Unit>(out var matchedChar, out var asUnit))
                            {
                                text.Append(matchedChar);
                            }
                            else if (asUnit.IsFailedMatch)
                            {
                                return(asUnit);
                            }

                            if (ch == 96)
                            {
                                text.Append(ch);
                            }
                        }
                    }
                    else
                    {
                        text.Append(ch);
                    }

                    escaped = false;
                    break;
                }

                length++;
                state.Move(1);
            }

            if (state.Scan("^ /(/r /n | /r | /n) /([dquote]3)", Color.Whitespace, Color.String).If(out _, out var anyMatchException))
            {
                if (hex)
                {
                    if (fromHex(hexText.ToString()).If(out var matchedChar, out var anyException))
                    {
                        text.Append(matchedChar);
                    }
                    else if (anyException.If(out var exception))
                    {
                        return(failedMatch <Unit>(exception));
                    }
                    else
                    {
                        return(failedMatch <Unit>(badHex(hexText.ToString())));
                    }
                }

                state.Move(1);
                state.AddToken(index, length + 1, Color.String);
                builder.Add(new StringSymbol(text.ToString()));

                return(Unit.Matched());
            }
            else if (anyMatchException.If(out var exception))
            {
                return(failedMatch <Unit>(exception));
            }
            else
            {
                return(failedMatch <Unit>(openString()));
            }
        }