/// <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); } }
/// <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); }
/// <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); } } }
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); }
public abstract void Run(Grammar grammar, CompileResult result);
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); }
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; }
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);
public override void WalkGrammar(Grammar grammar) => this.RenderGrammar(grammar, this.writer, this.currentIndentation);