示例#1
0
        private static EbnfNode ParseAtom(LinkedList <string> tokens, ref string ExtraWhitespace, ref string ExtraComments)
        {
            if (tokens.First.Value == "(")
            {
                tokens.RemoveFirst();
                var p = ParseProduction(tokens, ref ExtraWhitespace, ref ExtraComments);
                if (tokens.Count == 0 || tokens.First.Value != ")")
                {
                    throw new Exception($"mismatched parentheses in {string.Join(", ", tokens)}");
                }

                tokens.RemoveFirst();
                GobbleUpComments(tokens, p);
                return(p);
            }
            else if (tokens.First.Value.StartsWith("'"))
            {
                var t = tokens.First.Value; tokens.RemoveFirst();
                t = t.Substring(1, t.Length - 2);
                var p = new EbnfNode {
                    Kind = EbnfKind.Terminal, Text = t
                };
                if (t.StartsWith("<") && t.EndsWith(">"))
                {
                    p.Kind = EbnfKind.ExtendedTerminal;
                    p.Text = t.Substring(1, t.Length - 2);
                    if (p.Text.Contains("?"))
                    {
                        throw new Exception("A special-terminal may not contain a question-mark '?'");
                    }
                    if (p.Text == "")
                    {
                        throw new Exception("A terminal may not be '<>'");
                    }
                }
                else
                {
                    if (t.Contains("'") && t.Contains("\""))
                    {
                        throw new Exception("A terminal must either contain no ' or no \"");
                    }
                }
                GobbleUpComments(tokens, p);
                return(p);
            }
            else
            {
                var t = tokens.First.Value; tokens.RemoveFirst();
                var p = new EbnfNode {
                    Kind = EbnfKind.Reference, Text = t
                };
                GobbleUpComments(tokens, p);
                return(p);
            }
        }
示例#2
0
        private static void GobbleUpComments(LinkedList <string> tokens, EbnfNode node)
        {
            string followingWhitespace = node.FollowingWhitespace;
            string followingComment    = node.FollowingComment;
            bool   followingNewline    = node.FollowingNewline;

            GobbleUpComments(tokens, ref followingWhitespace, ref followingComment, ref followingNewline);
            node.FollowingWhitespace = followingWhitespace;
            node.FollowingComment    = followingComment;
            node.FollowingNewline    = followingNewline;
        }
示例#3
0
        private static EbnfNode ParseUnary(LinkedList <string> tokens, ref string extraWhitespace, ref string extraComments)
        {
            var p = ParseAtom(tokens, ref extraWhitespace, ref extraComments);

            while (tokens.Any())
            {
                if (tokens.First.Value == "+")
                {
                    tokens.RemoveFirst();
                    p = new EbnfNode {
                        Kind = EbnfKind.OneOrMoreOf, Children = new[] { p }.ToList()
                    };
                    GobbleUpComments(tokens, p);
                }
                else if (tokens.First.Value == "*")
                {
                    tokens.RemoveFirst();
                    p = new EbnfNode {
                        Kind = EbnfKind.ZeroOrMoreOf, Children = new[] { p }.ToList()
                    };
                    GobbleUpComments(tokens, p);
                }
                else if (tokens.First.Value == "?")
                {
                    tokens.RemoveFirst();
                    p = new EbnfNode {
                        Kind = EbnfKind.ZeroOrOneOf, Children = new[] { p }.ToList()
                    };
                    GobbleUpComments(tokens, p);
                }
                else
                {
                    break;
                }
            }
            return(p);
        }
示例#4
0
        public static string ToString(EbnfNode node)
        {
            var      r           = "";
            EbnfNode prevElement = null;

            switch (node.Kind)
            {
            case EbnfKind.Terminal:
                r = $"'{node.Text.Replace("\\", "\\\\").Replace("'", "\\'")}'";
                break;

            case EbnfKind.ExtendedTerminal:
                r = $"'<{node.Text.Replace("\\", "\\\\").Replace("'", "\\'")}>'";
                break;

            case EbnfKind.Reference:
                r = node.Text;
                break;

            case EbnfKind.OneOrMoreOf:
            case EbnfKind.ZeroOrMoreOf:
            case EbnfKind.ZeroOrOneOf:
                var op = (node.Kind == EbnfKind.OneOrMoreOf ? "+" : (node.Kind == EbnfKind.ZeroOrMoreOf ? "*" : "?"));
                if (node.Children[0].Kind == EbnfKind.Choice || node.Children[0].Kind == EbnfKind.Sequence)
                {
                    r = $"( {ToString(node.Children[0])} ){op}";
                }
                else
                {
                    r = $"{ToString(node.Children[0])}{op}";
                }

                break;

            case EbnfKind.Choice:
                foreach (var c in node.Children)
                {
                    if (prevElement != null)
                    {
                        r += (r.Last() == '\t' ? "| " : " | ");
                    }

                    r          += ToString(c);
                    prevElement = c;
                }
                break;

            case EbnfKind.Sequence:
                foreach (var c in node.Children)
                {
                    if (prevElement != null)
                    {
                        r += (r == "" || r.Last() == '\t' ? "" : " ");
                    }

                    if (c.Kind == EbnfKind.Choice)
                    {
                        r += "( " + ToString(c) + " )";
                    }
                    else
                    {
                        r += ToString(c);
                    }

                    prevElement = c;
                }
                break;

            default:
                r = "???";
                break;
            }
            if (!string.IsNullOrEmpty(node.FollowingComment))
            {
                r += " //" + node.FollowingComment;
            }

            if (node.FollowingNewline)
            {
                r += "\r\n\t";
            }

            return(r);
        }
示例#5
0
        public static IEnumerable <ColorizedWord> ColorizeAntlr(EbnfNode node)
        {
            var      lastWasTab  = false;
            EbnfNode prevElement = null;

            switch (node.Kind)
            {
            case EbnfKind.Terminal:
                yield return(Col("'" + node.Text.Replace("\\", "\\\\").Replace("'", "\\'").Replace("\\\"", "\"") + "'", "Terminal"));

                break;

            case EbnfKind.ExtendedTerminal:
                yield return(Col(node.Text, "ExtendedTerminal"));

                break;

            case EbnfKind.Reference:
                yield return(Col(node.Text, "Production"));

                break;

            case EbnfKind.OneOrMoreOf:
            case EbnfKind.ZeroOrMoreOf:
            case EbnfKind.ZeroOrOneOf:
                var op = (node.Kind == EbnfKind.OneOrMoreOf ? "+" : (node.Kind == EbnfKind.ZeroOrMoreOf ? "*" : "?"));
                if (node.Children[0].Kind == EbnfKind.Choice || node.Children[0].Kind == EbnfKind.Sequence)
                {
                    yield return(Col("( ", "PlainText"));

                    foreach (var word in ColorizeAntlr(node.Children[0]))
                    {
                        yield return(word);
                    }

                    yield return(Col(" )", "PlainText"));

                    yield return(Col(op, "PlainText"));
                }
                else
                {
                    foreach (var word in ColorizeAntlr(node.Children[0]))
                    {
                        yield return(word);
                    }

                    yield return(Col(op, "PlainText"));
                }
                break;

            case EbnfKind.Choice:
                foreach (var c in node.Children)
                {
                    if (prevElement != null)
                    {
                        yield return(Col(lastWasTab ? "| " : "| ", "PlainText"));
                    }

                    foreach (var word in ColorizeAntlr(c))
                    {
                        yield return(word); lastWasTab = (word?.Text == "\t");
                    }
                    prevElement = c;
                }
                break;

            case EbnfKind.Sequence:
                foreach (var c in node.Children)
                {
                    if (lastWasTab)
                    {
                        yield return(Col("  ", "PlainText"));
                    }

                    if (c.Kind == EbnfKind.Choice)
                    {
                        yield return(Col("( ", "PlainText"));

                        foreach (var word in ColorizeAntlr(c))
                        {
                            yield return(word);
                        }

                        yield return(Col(" )", "PlainText"));

                        lastWasTab = false;
                    }
                    else
                    {
                        foreach (var word in ColorizeAntlr(c))
                        {
                            yield return(word); lastWasTab = (word?.Text == "\t");
                        }
                    }
                    prevElement = c;
                }
                break;

            default:
                throw new NotSupportedException("Unrecognized Ebnf");
            }
            if (!string.IsNullOrEmpty(node.FollowingWhitespace))
            {
                yield return(Col(node.FollowingWhitespace, "Comment"));
            }

            if (!string.IsNullOrEmpty(node.FollowingComment))
            {
                yield return(Col(" //" + node.FollowingComment, "Comment"));
            }

            if (node.FollowingNewline)
            {
                yield return(null); yield return(Col("\t", "PlainText"));
            }
        }