public IParseTree <TToken, TRule> Parse(IList <Token <TToken> > tokens, ITextIndexHelper translator) { if (!this.configCompleted) { throw ParserConfigurationException.NotCompleted(); } var parseTree = this.rulesByType[this.rootType].TryParse(tokens, 0, this.rulesByType); if (parseTree.IsError || parseTree.NextTokenIndex != tokens.Count) { if (parseTree.MaxMatchedNextTokenIndex == tokens.Count) { throw new EndOfTokensException(); } if (parseTree.MaxMatchedNextTokenIndex < 0 || parseTree.MaxMatchedNextTokenIndex > tokens.Count) { throw new ApplicationException("An unexpected error was encountered."); } throw UnexpectedTokenException.For(tokens[parseTree.MaxMatchedNextTokenIndex], translator); } return(parseTree.TreeItems); }
public Parser <TToken, TRule> Rule( TRule type, params Action <IParserRuleConfigurator <TToken, TRule> >[] options) { if (this.configCompleted) { throw ParserConfigurationException.AlreadyCompleted(); } if (!this.rulesByType.TryGetValue(type, out var rule)) { rule = new RuleDefinition(type); this.rulesByType.Add(type, rule); } foreach (var option in options) { option(rule); } return(this); }
public Parser <TToken, TRule> WithRoot(TRule type) { if (this.configCompleted) { throw ParserConfigurationException.AlreadyCompleted(); } this.rootType = type; this.configCompleted = true; // Validate the configuration to ensure // no expected rules are missing var validated = new HashSet <TRule>(); var toValidate = new Stack <TRule>(); toValidate.Push(type); while (toValidate.Count != 0) { var checking = toValidate.Pop(); if (!this.rulesByType.TryGetValue(checking, out var checkingDefinition)) { throw ParserConfigurationException.RuleNotDefined(checking.ToString()); } validated.Add(checking); foreach (var dependency in checkingDefinition .DirectlyDependsOn() .Where(o => !validated.Contains(o)) .Distinct()) { toValidate.Push(dependency); } } return(this); }