Compute the set of variables that can begin with each terminal symbol

This commit is contained in:
Max Brunsfeld 2016-02-12 23:39:11 -08:00
parent 5a34d74702
commit dee1f697c1
4 changed files with 158 additions and 0 deletions

View file

@ -0,0 +1,55 @@
#include "compiler/build_tables/symbols_by_first_symbol.h"
#include "compiler/syntax_grammar.h"
#include "compiler/rules/symbol.h"
namespace tree_sitter {
namespace build_tables {
using std::map;
using std::set;
using rules::Symbol;
map<Symbol, set<Symbol>> symbols_by_first_symbol(const SyntaxGrammar &grammar) {
map<Symbol, set<Symbol>> result;
size_t variable_index = -1;
for (const SyntaxVariable &variable : grammar.variables) {
variable_index++;
Symbol symbol(variable_index);
result[symbol].insert(symbol);
for (const Production &production : variable.productions)
if (!production.empty()) {
Symbol first_symbol = production[0].symbol;
result[first_symbol].insert(symbol);
result[first_symbol].insert(first_symbol);
}
}
bool done = false;
while (!done) {
done = true;
for (auto &entry : result) {
set<Symbol> new_symbols;
for (const Symbol &symbol : entry.second)
for (const Symbol &other_symbol : result[symbol])
new_symbols.insert(other_symbol);
for (const Symbol &new_symbol : new_symbols)
if (entry.second.insert(new_symbol).second)
done = false;
}
}
for (auto iter = result.begin(), end = result.end(); iter != end;) {
if (!iter->first.is_token) {
result.erase(iter++);
} else {
iter++;
}
}
return result;
}
} // namespace build_tables
} // namespace tree_sitter

View file

@ -0,0 +1,19 @@
#ifndef COMPILER_BUILD_TABLES_SYMBOLS_BY_FIRST_SYMBOL_H_
#define COMPILER_BUILD_TABLES_SYMBOLS_BY_FIRST_SYMBOL_H_
#include <map>
#include <set>
#include "compiler/rules/symbol.h"
namespace tree_sitter {
struct SyntaxGrammar;
namespace build_tables {
std::map<rules::Symbol, std::set<rules::Symbol>> symbols_by_first_symbol(const SyntaxGrammar &);
} // namespace build_tables
} // namespace tree_sitter
#endif // COMPILER_BUILD_TABLES_SYMBOLS_BY_FIRST_SYMBOL_H_