Beispiel #1
0
 private static EBNF 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");
         }
         tokens.RemoveFirst();
         GobbleUpComments(tokens, ref p.FollowingWhitespace, ref p.FollowingComment, ref p.FollowingNewline);
         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 EBNF {
             Kind = EBNFKind.Terminal, s = t
         };
         if (t.StartsWith("<") && t.EndsWith(">"))
         {
             p.Kind = EBNFKind.ExtendedTerminal; p.s = t.Substring(1, t.Length - 2);
             if (p.s.Contains("?"))
             {
                 throw new Exception("A special-terminal may not contain a question-mark '?'");
             }
             if (p.s == "")
             {
                 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, ref p.FollowingWhitespace, ref p.FollowingComment, ref p.FollowingNewline);
         return(p);
     }
     else
     {
         var t = tokens.First.Value; tokens.RemoveFirst();
         var p = new EBNF {
             Kind = EBNFKind.Reference, s = t
         };
         GobbleUpComments(tokens, ref p.FollowingWhitespace, ref p.FollowingComment, ref p.FollowingNewline);
         return(p);
     }
 }
Beispiel #2
0
    private static EBNF 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 EBNF {
                    Kind = EBNFKind.OneOrMoreOf, Children = new[] { p }.ToList()
                };
                GobbleUpComments(tokens, ref p.FollowingWhitespace, ref p.FollowingComment, ref p.FollowingNewline);
            }
            else if (tokens.First.Value == "*")
            {
                tokens.RemoveFirst();
                p = new EBNF {
                    Kind = EBNFKind.ZeroOrMoreOf, Children = new[] { p }.ToList()
                };
                GobbleUpComments(tokens, ref p.FollowingWhitespace, ref p.FollowingComment, ref p.FollowingNewline);
            }
            else if (tokens.First.Value == "?")
            {
                tokens.RemoveFirst();
                p = new EBNF {
                    Kind = EBNFKind.ZeroOrOneOf, Children = new[] { p }.ToList()
                };
                GobbleUpComments(tokens, ref p.FollowingWhitespace, ref p.FollowingComment, ref p.FollowingNewline);
            }
            else
            {
                break;
            }
        }
        return(p);
    }
Beispiel #3
0
    public static string ToString(EBNF ebnf)
    {
        var  r           = "";
        EBNF prevElement = null;

        switch (ebnf.Kind)
        {
        case EBNFKind.Terminal:
            r = $"'{ebnf.s.Replace("\\", "\\\\").Replace("'", "\\'")}'";
            break;

        case EBNFKind.ExtendedTerminal:
            r = $"'<{ebnf.s.Replace("\\", "\\\\").Replace("'", "\\'")}>'";
            break;

        case EBNFKind.Reference:
            r = ebnf.s;
            break;

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

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

        case EBNFKind.Sequence:
            foreach (var c in ebnf.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(ebnf.FollowingComment))
        {
            r += " //" + ebnf.FollowingComment;
        }
        if (ebnf.FollowingNewline)
        {
            r += "\r\n\t";
        }
        return(r);
    }
Beispiel #4
0
    public static IEnumerable <ColorizedWord> ColorizeAntlr(EBNF ebnf)
    {
        var  lastWasTab  = false;
        EBNF prevElement = null;

        switch (ebnf.Kind)
        {
        case EBNFKind.Terminal:
            yield return(Col("'" + ebnf.s.Replace("\\", "\\\\").Replace("'", "\\'").Replace("\\\"", "\"") + "'", "Terminal"));

            break;

        case EBNFKind.ExtendedTerminal:
            yield return(Col(ebnf.s, "ExtendedTerminal"));

            break;

        case EBNFKind.Reference:
            yield return(Col(ebnf.s, "Production"));

            break;

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

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

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

        case EBNFKind.Choice:
            foreach (var c in ebnf.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 ebnf.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(ebnf.FollowingWhitespace))
        {
            yield return(Col(ebnf.FollowingWhitespace, "Comment"));
        }
        if (!string.IsNullOrEmpty(ebnf.FollowingComment))
        {
            yield return(Col(" //" + ebnf.FollowingComment, "Comment"));
        }
        if (ebnf.FollowingNewline)
        {
            yield return(null); yield return(Col("\t", "PlainText"));
        }
    }