public Grammar AddLanguage(string filename) { var currentScopes = new List<Scope>(); Rule rule = null; foreach (var line in File.ReadAllLines(filename)) { try { var tokens = GetTokens(line).ToArray(); if (tokens.Length == 0) continue; if (tokens[0].First == GrammarToken.Pattern) { if (tokens.Length != 3 || tokens[1].First != GrammarToken.Arrow || tokens[2].First != GrammarToken.ScopeName) throw new InvalidDataException("Expected `pattern -> scopename`"); if (currentScopes.Count == 0) throw new InvalidDataException("Rule without context"); rule = new Rule(tokens[0].Second, tokens[2].Second); foreach (var scope in currentScopes) scope.AddRule(rule); } if (tokens[0].First == GrammarToken.Keyword) { if (tokens[0].Second == "in") { if (tokens.Length != 2 || tokens[1].First != GrammarToken.ScopeName) throw new InvalidDataException("Expected `scopename` to follow `in`"); currentScopes = tokens[1].Second.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(x => scopes[x.Trim()]).ToList(); } else if (tokens[0].Second == "enter:") { if (rule == null) throw new InvalidDataException("`enter` action without rule"); rule.SetAction(RuleAction.Push, tokens[1].Second); } else if (tokens[0].Second == "leave:") { if (rule == null) throw new InvalidDataException("`leave` action without rule"); rule.SetAction(tokens[1].Second == "after" ? RuleAction.PopAfter : RuleAction.PopBefore); } else { var capnum = tokens[0].Second.Substring(0, tokens[0].Second.Length - 1); int n; if (!int.TryParse(capnum, out n)) throw new InvalidDataException("Unrecognized option: {0}".F(tokens[0].Second)); rule.SetCaptureScope(n, tokens[1].Second); } } } catch (Exception e) { errors.Add(Pair.New(filename, e.Message)); } } return this; }
public void AddRule(Rule r) { rules.Add(r); }