コード例 #1
0
            private Rule Select(DiscriminatorInfo discriminator)
            {
                ++this.discriminatorIndex; // eats the current token
                var nextToken = this.DiscriminatorPeek();

                if (discriminator.SimpleDiscriminations.ContainsKey(nextToken))
                {
                    return(discriminator.SimpleDiscriminations[nextToken]);
                }

                if (discriminator.ComplexDiscriminations.ContainsKey(nextToken))
                {
                    var nestedDiscriminationInfo = discriminator.ComplexDiscriminations[nextToken];
                    return(nestedDiscriminationInfo.Item1[this.Select(nestedDiscriminationInfo.Item2)]);
                }

                throw new InvalidOperationException($"Expected one of the following tokens ({string.Join(", ", discriminator.SimpleDiscriminations.Keys.Concat(discriminator.ComplexDiscriminations.Keys))}), but found {nextToken}");
            }
コード例 #2
0
        private DiscriminatorInfo GetDiscriminator(Token token, IReadOnlyList <Rule> rules, string name)
        {
            var prefixDiscriminator = this.discriminatorUsages.FirstOrDefault(
                u => u.Token == token &&
                rules.All(r => u.Rules.Any(ur => r.Symbols.Take(ur.Symbols.Count).SequenceEqual(ur.Symbols)))
                );

            if (prefixDiscriminator != null)
            {
                return(prefixDiscriminator.Discriminator);
            }

            var discriminators = rules.Select(r => new { r, remainings = this.GetRemainings(r, token) })
                                 .ToArray();

            var cacheKey = new DiscriminatorInfoCacheKey(discriminators.Select(t => t.remainings));
            DiscriminatorInfo existing;

            if (this.discriminatorCache.TryGetValue(cacheKey, out existing))
            {
                this.discriminatorUsages.Add(new DiscriminatorUsage {
                    Discriminator = existing, Token = token, Rules = rules
                });
                return(existing);
            }

            var discriminatorSymbol = new NonTerminal(name);
            var result = new DiscriminatorInfo {
                Symbol = discriminatorSymbol
            };

            this.discriminatorCache.Add(cacheKey, result);
            this.discriminatorUsages.Add(new DiscriminatorUsage {
                Discriminator = result, Token = token, Rules = rules
            });

            var discriminatorRules = discriminators.SelectMany(t => t.remainings, (t, remaining) => new { origRule = t.r, newRule = new Rule(discriminatorSymbol, remaining) })
                                     .Select(t => new { t.origRule, t.newRule, next = this.NextOf(new Rule(t.origRule.Produced, t.newRule.Symbols)) })
                                     .ToArray();

            var allNexts           = discriminatorRules.SelectMany(t => t.next).Distinct().ToArray();
            var subDiscriminatorId = 0;

            foreach (var next in allNexts)
            {
                var matchingRules = discriminatorRules.Where(t => t.next.Contains(next)).ToArray();
                if (matchingRules.Length == 1)
                {
                    result.SimpleDiscriminations.Add(next, matchingRules.Single().origRule);
                }
                else
                {
                    //var prefixDiscriminator = this.discriminatorUsages.FirstOrDefault(
                    //    u => u.Token == next
                    //        && matchingRules.All(r => u.Rules.Any(ur => r.newRule.Symbols.Take(ur.Symbols.Count).SequenceEqual(ur.Symbols)))
                    //);
                    //if (prefixDiscriminator != null)
                    //{
                    //    result.ComplexDiscriminations.Add(
                    //        next,
                    //        Tuple.Create(
                    //            matchingRules.ToDictionary(t => t.newRule, t => t.origRule),  // wrong
                    //            prefixDiscriminator.Discriminator
                    //        )
                    //    );
                    //    continue;
                    //}

                    var subDiscriminator = this.GetDiscriminator(
                        next,
                        matchingRules.Select(t => t.newRule).ToArray(),
                        name: $"{name}/{subDiscriminatorId++}"
                        );
                    result.ComplexDiscriminations.Add(
                        next,
                        Tuple.Create(
                            matchingRules.ToDictionary(t => t.newRule, t => t.origRule),
                            subDiscriminator
                            )
                        );
                }
            }

            return(result);
        }