Represents a full set of grammar rules.
Beispiel #1
0
        /// <summary>
        /// Compiles a PEG grammar into a program.
        /// </summary>
        /// <param name="grammar">The grammar to compile.</param>
        /// <returns>A <see cref="CompileResult"/> containing the errors, warnings, and results of compilation.</returns>
        public static CompileResult Compile(Grammar grammar)
        {
            var result = new CompileResult(grammar);

            var passes = PassTypes.Select(t => (CompilePass)Activator.CreateInstance(t)).ToList();
            while (true)
            {
                var existingErrors = new HashSet<string>(result.Errors.Where(e => !e.IsWarning).Select(e => e.ErrorNumber));
                var pendingErrors = new HashSet<string>(passes.SelectMany(p => p.ErrorsProduced));

                var nextPasses = passes
                    .Where(p => !p.BlockedByErrors.Any(e => existingErrors.Contains(e)))
                    .Where(p => !p.BlockedByErrors.Any(e => pendingErrors.Contains(e)))
                    .ToList();

                if (nextPasses.Count == 0)
                {
                    break;
                }

                foreach (var pass in nextPasses)
                {
                    pass.Run(grammar, result);
                    passes.Remove(pass);
                }
            }

            return result;
        }
 /// <summary>
 /// Detects which expressions in a <see cref="Grammar"/> are left-adjacent.
 /// </summary>
 /// <param name="grammar">The <see cref="Grammar"/> to inspect.</param>
 /// <returns>A <see cref="ILookup{Rule, Expression}"/> containing the left-adjacent rules.</returns>
 public static ILookup<Rule, Expression> Detect(Grammar grammar)
 {
     var leftAdjacent = new Dictionary<Rule, List<Expression>>();
     var zeroWidth = ZeroWidthEvaluator.Evaluate(grammar);
     new LeftRecursionExpressionTreeWalker(zeroWidth, leftAdjacent).WalkGrammar(grammar);
     return leftAdjacent.SelectMany(i => i.Value, (i, v) => new { i.Key, Value = v }).ToLookup(i => i.Key, i => i.Value);
 }
 public override void WalkGrammar(Grammar grammar)
 {
     if (!grammar.Settings.Any(s => s.Key.Name == "resources"))
     {
         base.WalkGrammar(grammar);
     }
 }
 public virtual void WalkGrammar(Grammar grammar)
 {
     foreach (var rule in grammar.Rules)
     {
         this.WalkRule(rule);
     }
 }
            public override void WalkGrammar(Grammar grammar)
            {
                var rules = grammar.Rules.ToDictionary(r => r.Identifier.Name, r => r);

                var startRule = grammar.Settings.Where(s => s.Key.Name == "start").Select(s => s.Value.ToString()).SingleOrDefault() ?? grammar.Rules[0].Identifier.Name;
                this.usedRules.Add(startRule);
                this.rulesToVisit.Enqueue(startRule);

                var publicRules = grammar.Rules.Where(r => r.Flags.Any(f => f.Name == "public" || f.Name == "export"));
                foreach (var rule in publicRules)
                {
                    if (this.usedRules.Add(rule.Identifier.Name))
                    {
                        this.rulesToVisit.Enqueue(rule.Identifier.Name);
                    }
                }

                while (this.rulesToVisit.Count > 0)
                {
                    var ruleName = this.rulesToVisit.Dequeue();
                    this.WalkRule(rules[ruleName]);
                }

                var unusedRules = new HashSet<string>(grammar.Rules.Select(r => r.Identifier.Name));
                unusedRules.ExceptWith(this.usedRules);

                foreach (var ruleName in unusedRules)
                {
                    var rule = rules[ruleName];
                    this.result.AddCompilerError(rule.Identifier.Start, () => Resources.PEG0017_WARNING_UnusedRule, rule.Identifier.Name);
                }
            }
        public override void Run(Grammar grammar, CompileResult result)
        {
            var seenSettings = new HashSet<string>();

            foreach (var setting in grammar.Settings)
            {
                var cursor = setting.Key.Start;

                bool singleAllowed;
                if (KnownSettings.TryGetValue(setting.Key.Name, out singleAllowed))
                {
                    if (singleAllowed && !seenSettings.Add(setting.Key.Name))
                    {
                        result.AddCompilerError(cursor, () => Resources.PEG0005_ERROR_SettingAlreadySpecified, setting.Key.Name);
                    }
                }
                else
                {
                    result.AddCompilerError(cursor, () => Resources.PEG0006_WARNING_SettingUnknown, setting.Key.Name);
                }

                string pattern;
                if (ValuePatterns.TryGetValue(setting.Key.Name, out pattern))
                {
                    if (!Regex.IsMatch(setting.Value.ToString(), pattern))
                    {
                        result.AddCompilerError(cursor, () => Resources.PEG0012_ERROR_SettingValueInvalid, setting.Value, setting.Key.Name);
                    }
                }
            }
        }
 public override void Run(Grammar grammar, CompileResult result)
 {
     if (grammar.Rules.Count == 0)
     {
         var cursor = grammar.End;
         result.AddCompilerError(cursor, () => Resources.PEG0001_ERROR_NoRulesDefined);
     }
 }
Beispiel #8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CompileResult"/> class.
 /// </summary>
 /// <param name="grammar">The grammar to which this <see cref="CompileResult"/> pertains.</param>
 public CompileResult(Grammar grammar)
 {
     this.grammar = grammar;
     this.expressionTypes = new Lazy<Dictionary<Expression, object>>(() => ResultTypeFinder.Find(this.grammar));
     this.leftAdjacentExpressions = new Lazy<ILookup<Rule, Expression>>(() => LeftAdjacencyDetector.Detect(this.grammar));
     this.leftRecursiveRules = new Lazy<HashSet<Rule>>(() => LeftRecursionDetector.Detect(this.LeftAdjacentExpressions));
     this.mutuallyRecursiveRules = new Lazy<HashSet<Rule>>(() => MutualRecursionDetector.Detect(this.LeftAdjacentExpressions));
     this.Errors = new List<CompilerError>();
 }
        public override void Run(Grammar grammar, CompileResult result)
        {
            var types = result.ExpressionTypes;

            foreach (var rule in grammar.Rules)
            {
                if (!types.ContainsKey(rule.Expression))
                {
                    result.AddCompilerError(rule.Identifier.Start, () => Resources.PEG0019_ERROR_UnknownType, rule.Identifier.Name);
                }
            }
        }
        /// <summary>
        /// Evaluates the expressions in a Pegasus <see cref="Grammar"/> to determine which of them contain assertions.
        /// </summary>
        /// <param name="grammar">The <see cref="Grammar"/> to evaluate.</param>
        /// <returns>A <see cref="Dictionary{TKey, TValue}"/> detailing the whether each expression in the grammar contains assertions.</returns>
        public static Dictionary<Expression, bool> Evaluate(Grammar grammar)
        {
            var containsAssertions = new Dictionary<Expression, bool?>();
            var walker = new ContainsAssertionsWalker(grammar, containsAssertions);

            do
            {
                walker.WalkGrammar(grammar);
            }
            while (walker.Changed);

            return containsAssertions.ToDictionary(x => x.Key, x => x.Value ?? false);
        }
Beispiel #11
0
        /// <summary>
        /// Finds the known result types of all expressions in the <see cref="Grammar"/>.
        /// </summary>
        /// <param name="grammar">The <see cref="Grammar"/> to inspect.</param>
        /// <returns>A <see cref="Dictionary{TKey, TValue}"/> of expressions and their types.</returns>
        public static Dictionary<Expression, object> Find(Grammar grammar)
        {
            var types = new Dictionary<Expression, object>();
            var walker = new ResultTypeTreeWalker(grammar, types);

            do
            {
                walker.WalkGrammar(grammar);
            }
            while (walker.Changed);

            return types;
        }
        public override void Run(Grammar grammar, CompileResult result)
        {
            var knownRules = new HashSet<string>();

            foreach (var rule in grammar.Rules)
            {
                if (!knownRules.Add(rule.Identifier.Name))
                {
                    var cursor = rule.Identifier.Start;
                    result.AddCompilerError(cursor, () => Resources.PEG0002_ERROR_RuleAlreadyDefined, rule.Identifier.Name);
                }
            }
        }
Beispiel #13
0
        public override void Run(Grammar grammar, CompileResult result)
        {
            if (result.Errors.Any(e => !e.IsWarning))
            {
                return;
            }

            using (var stringWriter = new StringWriter(CultureInfo.InvariantCulture))
            {
                new CodeGenerator(stringWriter, result.ExpressionTypes, result.LeftRecursiveRules).WalkGrammar(grammar);
                result.Code = stringWriter.ToString();
            }
        }
        /// <summary>
        /// Evaluates the expressions in a Pegasus <see cref="Grammar"/> to determine which of them are zero-width.
        /// </summary>
        /// <param name="grammar">The <see cref="Grammar"/> to evaluate.</param>
        /// <returns>A <see cref="Dictionary{TKey, TValue}"/> detailing the whether each expression in the grammar is zero-width.</returns>
        public static Dictionary<Expression, bool> Evaluate(Grammar grammar)
        {
            var zeroWidth = new Dictionary<Expression, bool?>();
            var walker = new ZeroWidthWalker(grammar, zeroWidth);

            do
            {
                walker.WalkGrammar(grammar);
            }
            while (walker.Changed);

            return zeroWidth.ToDictionary(x => x.Key, x => x.Value ?? false);
        }
 public override void Run(Grammar grammar, CompileResult result)
 {
     foreach (var rule in grammar.Rules)
     {
         foreach (var flag in rule.Flags)
         {
             if (!KnownFlags.Contains(flag.Name))
             {
                 var cursor = flag.Start;
                 result.AddCompilerError(cursor, () => Resources.PEG0013_WARNING_FlagUnknown, flag.Name);
             }
         }
     }
 }
        public override void Run(Grammar grammar, CompileResult result)
        {
            foreach (var rule in result.LeftRecursiveRules)
            {
                if (!rule.Flags.Any(f => f.Name == "memoize"))
                {
                    result.AddCompilerError(rule.Identifier.Start, () => Resources.PEG0020_ERROR_UnmemoizedLeftRecursion, rule.Identifier.Name);
                }
            }

            foreach (var rule in result.MutuallyRecursiveRules)
            {
                result.AddCompilerError(rule.Identifier.Start, () => Resources.PEG0023_ERROR_AmbiguousLeftRecursionDetected, rule.Identifier.Name);
            }
        }
        public override void Run(Grammar grammar, CompileResult result)
        {
            var knownRules = new HashSet<string>(grammar.Rules.Select(r => r.Identifier.Name));

            foreach (var setting in grammar.Settings)
            {
                if (setting.Key.Name == "start")
                {
                    var name = setting.Value.ToString().Trim();
                    if (!knownRules.Contains(name))
                    {
                        result.AddCompilerError(setting.Key.Start, () => Resources.PEG0003_ERROR_RuleDoesNotExist, name);
                    }
                }
            }
        }
 public override void Run(Grammar grammar, CompileResult result)
 {
     foreach (var rule in grammar.Rules)
     {
         if (char.IsLower(rule.Identifier.Name[0]))
         {
             if (rule.Flags.Any(f => f.Name == "public"))
             {
                 result.AddCompilerError(rule.Identifier.Start, () => Resources.PEG0025_WARNING_LowercasePublicRule, rule.Identifier.Name);
             }
             else if (rule.Flags.Any(f => f.Name == "export"))
             {
                 result.AddCompilerError(rule.Identifier.Start, () => Resources.PEG0025_WARNING_LowercaseExportedRule, rule.Identifier.Name);
             }
         }
     }
 }
 public override void Run(Grammar grammar, CompileResult result)
 {
     var containsAssertions = ContainsAssertionsEvaluator.Evaluate(grammar);
     var zeroWidth = ZeroWidthEvaluator.Evaluate(grammar);
     new ZeroWidthRepetitionTreeWalker(containsAssertions, zeroWidth, result).WalkGrammar(grammar);
 }
 public override void Run(Grammar grammar, CompileResult result)
 {
     new InvalidQuantifierTreeWalker(result).WalkGrammar(grammar);
 }
Beispiel #21
0
 public abstract void Run(Grammar grammar, CompileResult result);
Beispiel #22
0
 public override void WalkGrammar(Grammar grammar)
 {
     this.changed = false;
     base.WalkGrammar(grammar);
 }
 public override void Run(Grammar grammar, CompileResult result) => new MissingRuleExpressionTreeWalker(result).WalkGrammar(grammar);
 public override void Run(Grammar grammar, CompileResult result)
 {
     new UnusedRulesExpressionTreeWalker(result).WalkGrammar(grammar);
 }
Beispiel #25
0
 public ResultTypeTreeWalker(Grammar grammar, Dictionary<Expression, object> types)
 {
     this.rules = grammar.Rules.ToDictionary(r => r.Identifier.Name);
     this.types = types;
 }
 public ContainsAssertionsWalker(Grammar grammar, Dictionary<Expression, bool?> containsAssertions)
 {
     this.rules = grammar.Rules.ToDictionary(r => r.Identifier.Name);
     this.containsAssertions = containsAssertions;
 }
Beispiel #27
0
 private void WalkGrammar(Grammar grammar, TextWriter writer, string indentation)
 {
     var temp = this.currentIndentation;
     this.currentIndentation = indentation;
     base.WalkGrammar(grammar);
     this.currentIndentation = temp;
 }
 public override void Run(Grammar grammar, CompileResult result) => new CodeSyntaxTreeWalker(result).WalkGrammar(grammar);
 public override void Run(Grammar grammar, CompileResult result) => new ConflictingNamesTreeWalker(result).WalkGrammar(grammar);
Beispiel #30
0
 public override void WalkGrammar(Grammar grammar) => this.RenderGrammar(grammar, this.writer, this.currentIndentation);