public Grammar(IEnumerable <Rule> rules, NonTerminalSymbol target) { if (rules == null) { throw new ArgumentNullException(nameof(rules)); } if (target == null) { throw new ArgumentNullException(nameof(target)); } if (rules.AnyNull()) { throw new ArgumentException("At least one rule is null."); } Rules = Normalize(rules).AsReadOnly(); Alphabet = Rules.SelectMany(rule => rule.Alphabet).ToSortedSet().AsReadOnly(); Target = target; ISet <NonTerminalSymbol> nonTerminals = Rules.SelectMany(rule => rule.NonTerminals).ToSortedSet(); nonTerminals.Add(Target); NonTerminals = nonTerminals.AsReadOnly(); Symbols = NonTerminals.OfType <Symbol>().Intersect(Alphabet).ToSortedSet().AsReadOnly(); }
public Rule(IEnumerable <Chain> chains, NonTerminalSymbol target) { if (chains == null) { throw new ArgumentNullException(nameof(chains)); } if (target == null) { throw new ArgumentNullException(nameof(target)); } Chains = chains.ToSortedSet().AsReadOnly(); if (!Chains.Any()) { throw new ArgumentException("Rule must contain at least one chain."); } if (Chains.AnyNull()) { throw new ArgumentException("At least one null chain was found."); } Alphabet = Chains.SelectMany(chain => chain.Alphabet).ToSortedSet().AsReadOnly(); Target = target; ISet <NonTerminalSymbol> nonTerminals = Chains.SelectMany(chain => chain.NonTerminals).ToSortedSet(); nonTerminals.Add(Target); NonTerminals = nonTerminals.AsReadOnly(); }
public MakeStateMachineGrammarPostReport(NonTerminalSymbol target, Chain chain, IEnumerable <Rule> previousRules, IEnumerable <Rule> newRules, IEnumerable <Rule> nextRules, bool converted) { if (target == null) { throw new ArgumentNullException(nameof(target)); } if (chain == null) { throw new ArgumentNullException(nameof(chain)); } if (previousRules == null) { throw new ArgumentNullException(nameof(previousRules)); } if (newRules == null) { throw new ArgumentNullException(nameof(newRules)); } if (nextRules == null) { throw new ArgumentNullException(nameof(nextRules)); } Target = target; Chain = chain; PreviousRules = previousRules.ToSortedSet().AsReadOnly(); NextRules = nextRules.ToSortedSet().AsReadOnly(); NewRules = newRules.ToSortedSet().AsReadOnly(); Converted = converted; }
public SymbolTuple(NonTerminalSymbol target, TerminalSymbol terminalSymbol, NonTerminalSymbol nonTerminalSymbol) { if (target == null) { throw new ArgumentNullException(nameof(target)); } Target = target; NonTerminalSymbol = nonTerminalSymbol; TerminalSymbol = terminalSymbol; }
public bool IsLangEmpty(Action <BeginPostReport <NonTerminalSymbol> > onBegin = null, Action <IterationPostReport <NonTerminalSymbol> > onIterate = null) { int i = 0; ISet <NonTerminalSymbol> newNonTerminalSet = new HashSet <NonTerminalSymbol>(); if (onBegin != null) { onBegin(new BeginPostReport <NonTerminalSymbol>(i, newNonTerminalSet)); } bool isAddedSomething; do { i++; isAddedSomething = false; ISet <NonTerminalSymbol> nextNonTerminalSet = newNonTerminalSet; newNonTerminalSet = new HashSet <NonTerminalSymbol>(); foreach (Rule rule in Rules) { foreach (Chain chain in rule.Chains) { bool isOurChain = true; foreach (Symbol symbol in chain) { NonTerminalSymbol nonTerminalSymbol = symbol.As <NonTerminalSymbol>(); if (nonTerminalSymbol != null && !nextNonTerminalSet.Contains(nonTerminalSymbol)) { isOurChain = false; break; } } if (isOurChain) { if (!newNonTerminalSet.Contains(rule.Target) && !nextNonTerminalSet.Contains(rule.Target)) { newNonTerminalSet.Add(rule.Target); isAddedSomething = true; } break; } } } ISet <NonTerminalSymbol> previousNonTerminalSet = nextNonTerminalSet.ToHashSet(); nextNonTerminalSet.UnionWith(newNonTerminalSet); if (onIterate != null) { onIterate(new IterationPostReport <NonTerminalSymbol>(i, previousNonTerminalSet, newNonTerminalSet, nextNonTerminalSet, !isAddedSomething)); } newNonTerminalSet = nextNonTerminalSet; } while (isAddedSomething); return(!newNonTerminalSet.Contains(Target)); }
private static bool TerminalOrSetContains(Symbol symbol, ISet <NonTerminalSymbol> nonTerminalSet) { NonTerminalSymbol nonTerminalSymbol = symbol.As <NonTerminalSymbol>(); return(nonTerminalSymbol == null || nonTerminalSet.Contains(nonTerminalSymbol)); }
public bool RemoveUnreachableSymbols(out Grammar grammar, Action <BeginPostReport <Symbol> > onBegin = null, Action <IterationPostReport <Symbol> > onIterate = null) { int i = 0; ISet <Symbol> newSymbolSet = new HashSet <Symbol>(); newSymbolSet.Add(Target); if (onBegin != null) { onBegin(new BeginPostReport <Symbol>(i, newSymbolSet)); } IDictionary <NonTerminalSymbol, Rule> targetRuleMap = Rules.ToDictionary(r => r.Target); bool isAddedSomething; do { i++; isAddedSomething = false; ISet <Symbol> nextSymbolSet = newSymbolSet; newSymbolSet = new HashSet <Symbol>(); foreach (Symbol symbol in nextSymbolSet) { NonTerminalSymbol nonTerminalSymbol = symbol.As <NonTerminalSymbol>(); if (nonTerminalSymbol != null && targetRuleMap.ContainsKey(nonTerminalSymbol)) { foreach (Chain chain in targetRuleMap[nonTerminalSymbol].Chains) { foreach (Symbol chainSymbol in chain.Sequence) { if (!nextSymbolSet.Contains(chainSymbol) && !newSymbolSet.Contains(chainSymbol)) { isAddedSomething = true; newSymbolSet.Add(chainSymbol); } } } } } ISet <Symbol> previousSymbolSet = nextSymbolSet.ToHashSet(); nextSymbolSet.UnionWith(newSymbolSet); if (onIterate != null) { onIterate(new IterationPostReport <Symbol>(i, previousSymbolSet, newSymbolSet, nextSymbolSet, !isAddedSomething)); } newSymbolSet = nextSymbolSet; } while (isAddedSomething); IEnumerable <Rule> newRules = Rules.Where(r => newSymbolSet.Contains(r.Target)); if (newRules.Count() < Rules.Count) { grammar = new Grammar(newRules, Target); return(true); } grammar = this; return(false); }
public bool RemoveEmptyRules(out Grammar grammar, Action <BeginPostReport <NonTerminalSymbol> > onBegin = null, Action <IterationPostReport <NonTerminalSymbol> > onIterate = null) { int i = 0; ISet <NonTerminalSymbol> newSymbolSet = Rules.Where(r => r.Chains.Any(c => !c.Any())).Select(r => r.Target).ToHashSet(); if (onBegin != null) { onBegin(new BeginPostReport <NonTerminalSymbol>(i, newSymbolSet)); } bool isAddedSomething; do { i++; isAddedSomething = false; ISet <NonTerminalSymbol> nextSymbolSet = newSymbolSet; newSymbolSet = new HashSet <NonTerminalSymbol>(); foreach (Rule rule in Rules) { foreach (Chain chain in rule.Chains) { bool isAllSymbolsInNext = true; foreach (Symbol symbol in chain.Sequence) { NonTerminalSymbol nonTerminal = symbol.As <NonTerminalSymbol>(); if (nonTerminal == null || !nextSymbolSet.Contains(nonTerminal)) { isAllSymbolsInNext = false; break; } } if (isAllSymbolsInNext) { if (!newSymbolSet.Contains(rule.Target) && !nextSymbolSet.Contains(rule.Target)) { newSymbolSet.Add(rule.Target); isAddedSomething = true; } } } } ISet <NonTerminalSymbol> previousSymbolSet = nextSymbolSet.ToHashSet(); nextSymbolSet.UnionWith(newSymbolSet); if (onIterate != null) { onIterate(new IterationPostReport <NonTerminalSymbol>(i, previousSymbolSet, newSymbolSet, nextSymbolSet, !isAddedSomething)); } newSymbolSet = nextSymbolSet; } while (isAddedSomething); ISet <Rule> newRules = new HashSet <Rule>(); foreach (Rule rule in Rules) { newRules.Add(new Rule(rule.Chains.SelectMany(c => ForkByEmpty(c, newSymbolSet).Where(chain => chain != Chain.Empty)), rule.Target)); } IDictionary <NonTerminalSymbol, Rule> targetRuleMap = Rules.ToDictionary(r => r.Target); NonTerminalSymbol newTarget = Target; if (newSymbolSet.Contains(Target)) { Chain targetChain = new Chain(EnumerateHelper.Sequence(Target)); newTarget = GetNewNonTerminal(NonTerminals); Rule rule = new Rule(EnumerateHelper.Sequence(targetChain, Chain.Empty), newTarget); newRules.Add(rule); } newRules = Normalize(newRules); if (!newRules.SetEquals(Rules)) { grammar = new Grammar(newRules, newTarget); return(true); } grammar = this; return(false); }
public bool RemoveChainRules(out Grammar grammar, Action <ChainRulesBeginPostReport> onBegin = null, Action <ChainRulesIterationPostReport> onIterate = null, Action <ChainRulesEndPostReport> onEnd = null) { IDictionary <NonTerminalSymbol, ISet <NonTerminalSymbol> > newSymbolSetMap = NonTerminals.ToDictionary(s => s, s => new HashSet <NonTerminalSymbol>(s.AsSequence()).Of <ISet <NonTerminalSymbol> >()); IDictionary <NonTerminalSymbol, ChainRulesEndTuple> unchangeableSymbolSetMap = new Dictionary <NonTerminalSymbol, ChainRulesEndTuple>(); IDictionary <NonTerminalSymbol, Rule> targetRuleMap = Rules.ToDictionary(r => r.Target); if (onBegin != null) { onBegin(new ChainRulesBeginPostReport(0, newSymbolSetMap)); } int i = 0; do { i++; IDictionary <NonTerminalSymbol, ISet <NonTerminalSymbol> > nextSymbolSetMap = newSymbolSetMap; newSymbolSetMap = nextSymbolSetMap.Keys.ToDictionary(s => s, s => new HashSet <NonTerminalSymbol>().Of <ISet <NonTerminalSymbol> >()); foreach (KeyValuePair <NonTerminalSymbol, ISet <NonTerminalSymbol> > nextSymbolSet in nextSymbolSetMap) { foreach (NonTerminalSymbol nonTerminalSymbol in nextSymbolSet.Value) { if (targetRuleMap.ContainsKey(nonTerminalSymbol)) { Rule rule = targetRuleMap[nonTerminalSymbol]; foreach (Chain chain in rule.Chains.Where(c => c.Sequence.Count == 1)) { NonTerminalSymbol symbol = chain.Sequence.First().As <NonTerminalSymbol>(); ISet <NonTerminalSymbol> newSymbolSet = newSymbolSetMap[nextSymbolSet.Key]; if (symbol != null && !newSymbolSet.Contains(symbol) && !nextSymbolSet.Value.Contains(symbol)) { newSymbolSet.Add(symbol); } } } } } IDictionary <NonTerminalSymbol, ISet <NonTerminalSymbol> > previousSymbolSetMap = nextSymbolSetMap.ToDictionary(kv => kv.Key, kv => kv.Value.ToHashSet().Of <ISet <NonTerminalSymbol> >()); IDictionary <NonTerminalSymbol, ChainRulesIterationTuple> symbolMap = new Dictionary <NonTerminalSymbol, ChainRulesIterationTuple>(); foreach (KeyValuePair <NonTerminalSymbol, ISet <NonTerminalSymbol> > symbolSet in previousSymbolSetMap) { ISet <NonTerminalSymbol> newSymbolSet = newSymbolSetMap[symbolSet.Key]; ISet <NonTerminalSymbol> nonTerminalSet = nextSymbolSetMap[symbolSet.Key]; if (newSymbolSet.Count == 0) { unchangeableSymbolSetMap[symbolSet.Key] = new ChainRulesEndTuple(nonTerminalSet, nonTerminalSet.Where(m => m != symbolSet.Key), i); symbolMap.Add(symbolSet.Key, new ChainRulesIterationTuple(true, symbolSet.Value, newSymbolSet, nonTerminalSet)); nextSymbolSetMap.Remove(symbolSet.Key); } else { ISet <NonTerminalSymbol> nextSymbolSet = nonTerminalSet; nextSymbolSet.UnionWith(newSymbolSet); symbolMap.Add(symbolSet.Key, new ChainRulesIterationTuple(false, symbolSet.Value, newSymbolSet, nextSymbolSet)); } } if (onIterate != null) { onIterate(new ChainRulesIterationPostReport(i, symbolMap, symbolMap.All(kv => kv.Value.IsLastIteration))); } newSymbolSetMap = symbolMap.Where(kv => !kv.Value.IsLastIteration).ToDictionary(kv => kv.Key, kv => kv.Value.Next.ToHashSet().Of <ISet <NonTerminalSymbol> >()); } while (newSymbolSetMap.Count > 0); ISet <Rule> newRules = new HashSet <Rule>(); foreach (Rule rule in Rules) { ISet <Chain> newChains = new HashSet <Chain>(); foreach (Chain chain in rule.Chains) { if (chain.Sequence.Count != 1 || chain.Sequence.FirstOrDefault().As <NonTerminalSymbol>() == null) { newChains.Add(chain); } } if (newChains.Any()) { newRules.Add(new Rule(newChains, rule.Target)); } } if (onEnd != null) { onEnd(new ChainRulesEndPostReport(unchangeableSymbolSetMap)); } ISet <Rule> additionalRules = new HashSet <Rule>(); foreach (Rule rule in newRules) { foreach (KeyValuePair <NonTerminalSymbol, ChainRulesEndTuple> symbolSet in unchangeableSymbolSetMap) { if (symbolSet.Value.FinalNonTerminals.Contains(rule.Target)) { additionalRules.Add(new Rule(rule.Chains, symbolSet.Key)); } } } newRules = Normalize(newRules.Concat(additionalRules)); if (!newRules.SetEquals(Rules)) { grammar = new Grammar(newRules, Target); return(true); } grammar = this; return(false); }
public Grammar MakeStateMachineGrammar(GrammarType grammarType, Action <IReadOnlySet <Rule> > onBegin = null, Action <MakeStateMachineGrammarPostReport> onIterate = null) { ISet <Rule> newRules = new HashSet <Rule>(); if (onBegin != null) { onBegin(newRules.AsReadOnly()); } ISet <NonTerminalSymbol> newNonTerminals = new HashSet <NonTerminalSymbol>(NonTerminals); foreach (Rule rule in Rules) { foreach (Chain chain in rule.Chains) { ISet <Rule> newChainRules = new HashSet <Rule>(); int state = 0; NonTerminalSymbol nonTerminalSymbol = null; Symbol otherSymbol = null; Chain newChain; foreach (Symbol symbol in Enumerate(chain, grammarType)) { switch (state) { case 0: nonTerminalSymbol = symbol.As <NonTerminalSymbol>(); otherSymbol = symbol; if (nonTerminalSymbol != null) { state = 1; } else { state = 2; } break; case 1: otherSymbol = symbol; state = 3; break; case 2: newChain = new Chain(otherSymbol.AsSequence()); newNonTerminals.Add(nonTerminalSymbol = GetNewNonTerminal(newNonTerminals)); newChainRules.Add(new Rule(newChain.AsSequence(), nonTerminalSymbol)); otherSymbol = symbol; state = 3; break; default: newChain = new Chain(Enumerate(grammarType, nonTerminalSymbol, otherSymbol)); newNonTerminals.Add(nonTerminalSymbol = GetNewNonTerminal(newNonTerminals)); newChainRules.Add(new Rule(newChain.AsSequence(), nonTerminalSymbol)); otherSymbol = symbol; break; } } switch (state) { case 0: newChain = Chain.Empty; break; case 1: case 2: newChain = new Chain(otherSymbol.AsSequence()); break; default: newChain = new Chain(Enumerate(grammarType, nonTerminalSymbol, otherSymbol)); break; } newChainRules.Add(new Rule(newChain.AsSequence(), rule.Target)); newChainRules = Normalize(newChainRules); ISet <Rule> previousRules = newRules.ToHashSet(); newRules.AddRange(newChainRules); if (onIterate != null) { onIterate(new MakeStateMachineGrammarPostReport(rule.Target, chain, previousRules, newChainRules, newRules, newChainRules.Count > 1)); } } } return(new Grammar(newRules, Target)); }
public StateMachine MakeStateMachine(GrammarType grammarType) { ISet <Transition> transitions = new HashSet <Transition>(); ISet <Label> finalStates = new HashSet <Label>(); NonTerminalSymbol additionalState = GetNewNonTerminal(NonTerminals); switch (grammarType) { case GrammarType.Left: finalStates.Add(Target.Label); break; case GrammarType.Right: finalStates.Add(additionalState.Label); break; default: throw new NotSupportedException(string.Format(GrammarIsNotSupportedMessage, grammarType)); } foreach (Rule rule in Rules) { foreach (Chain chain in rule.Chains) { SymbolTuple symbolTuple = GetSymbolTuple(grammarType, chain, rule.Target, additionalState); if (symbolTuple.NonTerminalSymbol == null && symbolTuple.NonTerminalSymbol == null) { switch (grammarType) { case GrammarType.Left: finalStates.Add(additionalState.Label); break; case GrammarType.Right: finalStates.Add(Target.Label); break; default: throw new NotSupportedException(string.Format(GrammarIsNotSupportedMessage, grammarType)); } } else { Label currentState; Label nextState; switch (grammarType) { case GrammarType.Left: currentState = symbolTuple.NonTerminalSymbol.Label; nextState = symbolTuple.Target.Label; break; case GrammarType.Right: currentState = symbolTuple.Target.Label; nextState = symbolTuple.NonTerminalSymbol.Label; break; default: throw new NotSupportedException(string.Format(GrammarIsNotSupportedMessage, grammarType)); } transitions.Add(new Transition(currentState, symbolTuple.TerminalSymbol.Symbol, nextState)); } } } StateMachine stateMachine; switch (grammarType) { case GrammarType.Left: stateMachine = new StateMachine(additionalState.Label, finalStates, transitions); break; case GrammarType.Right: stateMachine = new StateMachine(Target.Label, finalStates, transitions); break; default: throw new NotSupportedException(string.Format(GrammarIsNotSupportedMessage, grammarType)); } return(stateMachine); }
private SymbolTuple GetSymbolTuple(GrammarType grammarType, Chain chain, NonTerminalSymbol ruleTarget, NonTerminalSymbol finalTarget = null) { int state = 0; Symbol otherSymbol = null; NonTerminalSymbol nonTerminalSymbol = null; TerminalSymbol terminalSymbol = null; foreach (Symbol symbol in Enumerate(chain, grammarType)) { switch (state) { case 0: otherSymbol = symbol; state = 1; break; case 1: nonTerminalSymbol = otherSymbol.As <NonTerminalSymbol>(); if (nonTerminalSymbol == null) { throw new InvalidOperationException("Expected non terminal symbol."); } terminalSymbol = symbol.As <TerminalSymbol>(); if (terminalSymbol == null) { throw new InvalidOperationException("Expected terminal symbol."); } state = 2; break; default: throw new InvalidOperationException("Expected 2 or less symbols."); } } switch (state) { case 0: if (ruleTarget != Target && finalTarget != null) { throw new InvalidOperationException("Expected that rule target equals to grammar target."); } return(new SymbolTuple(ruleTarget, null, null)); case 1: nonTerminalSymbol = finalTarget != null ? finalTarget : otherSymbol.As <NonTerminalSymbol>(); terminalSymbol = otherSymbol.As <TerminalSymbol>(); if (terminalSymbol == null && nonTerminalSymbol == null) { throw new InvalidOperationException(string.Format("The symbol type is not supported symbol type: {0}.", otherSymbol)); } if (finalTarget != null && terminalSymbol == null) { throw new InvalidOperationException("One symbol chain must contain terminal symbol."); } goto case 2; case 2: default: return(new SymbolTuple(ruleTarget, terminalSymbol, nonTerminalSymbol)); } }