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); } } } }
/// <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; }
public override void Run(Grammar grammar, CompileResult result) { if (grammar.Rules.Count == 0) { var cursor = grammar.End; result.AddCompilerError(cursor, () => Resources.PEG0001_ERROR_NoRulesDefined); } }
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); } } }
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(); } }
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) { 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); } } } }
/// <summary> /// Parse and compile a PEG grammar from a string. /// </summary> /// <param name="subject">The PEG grammar to parse and compile.</param> /// <param name="fileName">The filename to use in errors.</param> /// <returns>A <see cref="CompileResult"/> containing the result of the compilation.</returns> public static CompileResult CompileString(string subject, string fileName = null) { Grammar grammar; try { grammar = new PegParser().Parse(subject ?? string.Empty, fileName); } catch (FormatException ex) { var cursor = ex.Data["cursor"] as Cursor; if (cursor != null && Regex.IsMatch(ex.Message, @"^PEG\d+:")) { var parts = ex.Message.Split(new[] { ':' }, 2); var result = new CompileResult(null); result.Errors.Add(new CompilerError(cursor.FileName ?? string.Empty, cursor.Line, cursor.Column, parts[0], parts[1])); return result; } throw; } return PegCompiler.Compile(grammar); }
public CodeSyntaxTreeWalker(CompileResult result) { this.result = result; }
public override void Run(Grammar grammar, CompileResult result) => new CodeSyntaxTreeWalker(result).WalkGrammar(grammar);
public ConflictingNamesTreeWalker(CompileResult result) { this.result = result; }
public override void Run(Grammar grammar, CompileResult result) => new ConflictingNamesTreeWalker(result).WalkGrammar(grammar);
public override void Run(Grammar grammar, CompileResult result) { new InvalidQuantifierTreeWalker(result).WalkGrammar(grammar); }
public UnusedRulesExpressionTreeWalker(CompileResult result) { this.result = result; }
public MissingRuleExpressionTreeWalker(Grammar grammar, CompileResult result) { this.knownRules = new HashSet<string>(grammar.Rules.Select(r => r.Identifier.Name)); this.result = result; }
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 InvalidQuantifierTreeWalker(CompileResult result) { this.result = result; }
public abstract void Run(Grammar grammar, CompileResult result);
public override void Run(Grammar grammar, CompileResult result) { new UnusedRulesExpressionTreeWalker(result).WalkGrammar(grammar); }
public override void Run(Grammar grammar, CompileResult result) => new MissingRuleExpressionTreeWalker(result).WalkGrammar(grammar);
public ZeroWidthRepetitionTreeWalker(Dictionary<Expression, bool> containsAssertions, Dictionary<Expression, bool> zeroWidth, CompileResult result) { this.containsAssertions = containsAssertions; this.result = result; this.zeroWidth = zeroWidth; }
public MissingRuleExpressionTreeWalker(CompileResult result) { this.result = result; }
public override void Run(Grammar grammar, CompileResult result) => new UnusedRulesExpressionTreeWalker(result).WalkGrammar(grammar);