예제 #1
0
 public int DefineTerminal(string name, bool isExplicit, int token, string pattern = null)
 {
     if (terminals.ContainsKey(name))
     {
         throw GrammarDefineException.DuplicateTerminalDefinition(name);
     }
     terminals.Add(name, new Terminal
     {
         Id       = id,
         Token    = token,
         Pattern  = pattern,
         Explicit = isExplicit,
     });
     return(id++);
 }
예제 #2
0
        public IGrammarParser Build()
        {
            var nameToToken       = new Dictionary <string, LLnToken>();
            var nonTerminalTokens = new List <NonTerminalPair>(roots.Count + nonTerminals.Count);

            foreach (var kv in terminals)
            {
                nameToToken.Add(
                    kv.Key,
                    new TerminalToken(
                        kv.Value.Id,
                        kv.Value.Explicit,
                        kv.Key,
                        kv.Value.Token,
                        kv.Value.Pattern
                        )
                    );
            }

            foreach (var kv in nonTerminals)
            {
                var token = new NonTerminalToken(kv.Key, kv.Value.Count);
                nameToToken.Add(kv.Key, token);
                nonTerminalTokens.Add(new NonTerminalPair
                {
                    Token = token,
                    Paths = kv.Value,
                });
            }

            foreach (var pair in nonTerminalTokens)
            {
                var token = pair.Token;
                foreach (var path in pair.Paths)
                {
                    var len    = path.Path.Length;
                    var tokens = new LLnToken[len];
                    for (int i = 0; i < len; i++)
                    {
                        if (!nameToToken.TryGetValue(path.Path[i], out var refToken))
                        {
                            throw GrammarDefineException.NonTerminalRefTokenNotFound(token.Name, path.Path[i]);
                        }
                        tokens[i] = refToken;
                    }

                    token.AddPath(path.Id, path.Explicit, tokens);
                }
            }

            var rootToken = new RootToken(roots.Count);

            foreach (var path in roots)
            {
                var len    = path.Path.Length;
                var tokens = new LLnToken[len + 1];
                for (int i = 0; i < len; i++)
                {
                    if (!nameToToken.TryGetValue(path.Path[i], out var refToken))
                    {
                        throw GrammarDefineException.NonTerminalRefTokenNotFound(rootToken.Name, path.Path[i]);
                    }
                    tokens[i] = refToken;
                }

                tokens[len] = EOFToken.Instance;

                rootToken.AddPath(path.Id, false, tokens);
            }

            var parser = new LLnParser(rootToken);

            return(parser);
        }