Exemple #1
0
        private static void ReadDefinition(ParseResult definition, NamedParserCollection rules)
        {
            Debug.Assert(definition.Parser == Parser.Definition);

            var name = definition[0].Value;

            rules.PushNamespace(name);

            var branch         = definition.FirstOrDefault(x => x.Parser == Parser.Branch);
            var statementBlock = definition.FirstOrDefault(x => x.Parser == Parser.StatementBlock);

            if (statementBlock != null)
            {
                ReadStatementBlock(statementBlock, rules);
            }

            Parser parser = null;

            if (branch != null)
            {
                parser = ReadBranch(branch, rules);
            }

            rules.PopNamespace();

            if (parser != null)
            {
                rules.Add(name, parser);
            }
        }
Exemple #2
0
 public void WriteGrammar(string fullClassName, NamedParserCollection grammar, string rootParserName, string filePath)
 {
     using (var writer = File.CreateText(filePath))
     {
         WriteGrammar(fullClassName, grammar, rootParserName, writer);
     }
 }
Exemple #3
0
        private static Parser ReadConcat(ParseResult concat, NamedParserCollection rules)
        {
            Debug.Assert(concat.Parser == Parser.Concat);

            return(concat.InnerCount == 1
                ? ReadModifier(concat[0], rules)
                : new ConcatParser(concat.Select(x => ReadModifier(x, rules))));
        }
Exemple #4
0
        private static Parser ReadBranch(ParseResult branch, NamedParserCollection rules)
        {
            Debug.Assert(branch.Parser == Parser.Branch);

            return(branch.InnerCount == 1
                ? ReadConcat(branch[0], rules)
                : new BranchParser(branch.Select(x => ReadConcat(x, rules))));
        }
Exemple #5
0
        private static Parser ReadRegex(ParseResult regex, NamedParserCollection rules)
        {
            var pattern = regex[0];
            var options = regex[1];

            var builder = new StringBuilder(pattern.Length);
            var escaped = false;

            for (var i = 0; i < pattern.Length; ++i)
            {
                var c = pattern.Value[i];
                if (escaped)
                {
                    escaped = false;
                    switch (c)
                    {
                    case '/':
                        builder.Append('/');
                        break;

                    default:
                        builder.Append("\\" + c);
                        break;
                    }
                }
                else if (c == '\\')
                {
                    escaped = true;
                }
                else
                {
                    builder.Append(c);
                }
            }

            var parsedOptions = RegexParser.Compiled ? RegexOptions.Compiled : RegexOptions.None;

            for (var i = 0; i < options.Length; ++i)
            {
                switch (options.Value[i])
                {
                case 'i':
                    parsedOptions |= RegexOptions.IgnoreCase;
                    break;
                }
            }

            return(new Regex(builder.ToString(), parsedOptions));
        }
Exemple #6
0
        private static Parser ReadString(ParseResult str, NamedParserCollection rules)
        {
            var value = str[0];

            if (value.Length == 0)
            {
                return(EmptyParser.Instance);
            }

            var builder = new StringBuilder(value.Length);
            var escaped = false;

            for (var i = 0; i < value.Length; ++i)
            {
                var c = value.Value[i];
                if (escaped)
                {
                    escaped = false;
                    switch (c)
                    {
                    case 'r':
                        builder.Append('\r');
                        break;

                    case 'n':
                        builder.Append('\n');
                        break;

                    case 't':
                        builder.Append('\t');
                        break;

                    default:
                        builder.Append(c);
                        break;
                    }
                }
                else if (c == '\\')
                {
                    escaped = true;
                }
                else
                {
                    builder.Append(c);
                }
            }

            return(builder.ToString());
        }
Exemple #7
0
 private static void ReadStatementBlock(ParseResult statementBlock, NamedParserCollection rules)
 {
     foreach (var statement in statementBlock)
     {
         var value = statement[0];
         if (value.Parser == Parser.Definition)
         {
             ReadDefinition(value, rules);
         }
         else if (value.Parser == Parser.SpecialBlock)
         {
             ReadSpecialBlock(value, rules);
         }
     }
 }
Exemple #8
0
        public static NamedParserCollection FromString(string str)
        {
            var result = Parser.Parse(str);

            if (!result.Success)
            {
                throw new GrammarParseException(result);
            }

            var rules = new NamedParserCollection();

            ReadStatementBlock(result[0], rules);

            return(rules);
        }
Exemple #9
0
        private static Parser ReadModifier(ParseResult modifier, NamedParserCollection rules)
        {
            Debug.Assert(modifier.Parser == Parser.Modifier);

            var prefix  = modifier.FirstOrDefault(x => x.Parser == Parser.ModifierPrefix);
            var term    = ReadTerm(modifier.First(x => x.Parser == Parser.Term), rules);
            var postfix = modifier.FirstOrDefault(x => x.Parser == Parser.ModifierPostfix);

            if (prefix != null)
            {
                switch (prefix.Value)
                {
                case "$":
                    term = term.Strict;
                    break;

                case "!":
                    term = term.Not;
                    break;

                default:
                    throw new Exception($"Unrecognised modifier '{prefix.Value}'.");
                }
            }

            if (postfix != null)
            {
                switch (postfix.Value)
                {
                case "?":
                    term = term.Optional;
                    break;

                case "+":
                    term = term.Repeated;
                    break;

                case "*":
                    term = term.Repeated.Optional;
                    break;

                default:
                    throw new Exception($"Unrecognised modifier '{postfix.Value}'.");
                }
            }

            return(term);
        }
Exemple #10
0
        private static void ReadSpecialBlock(ParseResult specialBlock, NamedParserCollection rules)
        {
            var header = specialBlock[0];
            var block  = specialBlock[1];
            var stack  = new Stack <IDisposable>();

            while (header != null)
            {
                var item = header[0];

                if (item.InnerCount == 1)
                {
                    var ignore = ReadBranch(item[0], rules);
                    stack.Push(Parse.Parser.AllowWhitespace(ignore));
                }
                else
                {
                    switch (item.Value)
                    {
                    case "noignore":
                        stack.Push(Parse.Parser.ForbidWhitespace());
                        break;

                    case "collapse":
                        stack.Push(Parse.Parser.EnableCollapseIfSingleElement());
                        break;

                    default:
                        throw new NotImplementedException(item.Value);
                    }
                }

                header = header.InnerCount == 1 ? null : header[1];
            }

            ReadStatementBlock(block, rules);

            while (stack.Count > 0)
            {
                stack.Pop().Dispose();
            }
        }
Exemple #11
0
        private static Parser ReadTerm(ParseResult term, NamedParserCollection rules)
        {
            Debug.Assert(term.Parser == Parser.Term);

            var value = term[0];

            if (value.Parser == Parser.String)
            {
                return(ReadString(value, rules));
            }
            if (value.Parser == Parser.Regex)
            {
                return(ReadRegex(value, rules));
            }
            if (value.Parser == Parser.NonTerminal)
            {
                return(ReadNonTerminal(value, rules));
            }
            if (value.Parser == Parser.Branch)
            {
                return(ReadBranch(value, rules));
            }
            throw new NotImplementedException();
        }
Exemple #12
0
        private static Parser ReadNonTerminal(ParseResult nonTerminal, NamedParserCollection rules)
        {
            var name = nonTerminal.Value;

            return(rules.Get(name));
        }
Exemple #13
0
        public void WriteGrammar(string fullClassName, NamedParserCollection grammar, string rootParserName, TextWriter dest)
        {
            var writer = new CodeWriter(dest, Options);

            var splitName  = fullClassName.Split('.');
            var @namespace = splitName.Length > 1
                ? string.Join(".", splitName.Take(splitName.Length - 1).ToArray())
                : null;
            var className = splitName[splitName.Length - 1];

            writer.WriteLine($"namespace {@namespace}");
            using (writer.Block())
            {
                writer.Write($"public class {className} : ");
                writer.Write(typeof(CustomParser));
                writer.WriteLine();
                using (writer.Block())
                {
                    foreach (var name in grammar.ParserNames)
                    {
                        writer.Write("public ");
                        writer.Write(typeof(NamedParser));
                        writer.WriteLine($" {NormalizeParserName(name)};");
                    }

                    writer.WriteLine();

                    writer.Write("protected override ");
                    writer.Write(typeof(Parser));
                    writer.WriteLine(" OnDefine()");
                    using (writer.Block())
                    {
                        writer.Write($"var {RegexOptionsVariable} = ");
                        writer.Write(typeof(RegexParser));
                        writer.WriteLine($".{nameof( RegexParser.Compiled )}");
                        writer.Indent();
                        writer.Write("? ");
                        writer.Write(typeof(RegexOptions));
                        writer.WriteLine($".{nameof( RegexOptions.Compiled )}");
                        writer.Write(": ");
                        writer.Write(typeof(RegexOptions));
                        writer.WriteLine($".{nameof( RegexOptions.None )};");
                        writer.Unindent();

                        foreach (var whitespaceGroup in grammar.ParserNames.GroupBy(x => grammar[x].WhitespaceParser))
                        {
                            writer.WriteLine();

                            CodeWriter.IBlock whitespaceBlock = null;
                            if (whitespaceGroup.Key != null)
                            {
                                writer.Write("using (");
                                writer.Write(typeof(Parser));
                                writer.Write($".{nameof( Parser.AllowWhitespace )}(");
                                WriteParser(writer, whitespaceGroup.Key);
                                writer.WriteLine("))");
                                whitespaceBlock = writer.Block();
                            }

                            foreach (var collapseGroup in whitespaceGroup.GroupBy(x => grammar[x].CollapseIfSingleElement))
                            {
                                CodeWriter.IBlock collapseBlock = null;
                                if (collapseGroup.Key)
                                {
                                    writer.WriteLine();
                                    writer.Write("using (");
                                    writer.Write(typeof(Parser));
                                    writer.WriteLine($".{nameof( Parser.EnableCollapseIfSingleElement )}())");
                                    collapseBlock = writer.Block();
                                }

                                foreach (var parserName in collapseGroup)
                                {
                                    writer.Write($"this[{NormalizeParserName(parserName)}] = ");
                                    WriteParser(writer, grammar[parserName].ResolvedParser);
                                    writer.WriteLine(";");
                                }

                                collapseBlock?.End();
                            }

                            whitespaceBlock?.End();
                        }

                        writer.WriteLine($"return {rootParserName};");
                    }
                }
            }

            dest.Flush();
        }