mirror of
https://github.com/GothenburgBitFactory/timewarrior.git
synced 2025-07-07 20:06:39 +02:00
Grammar: Code cleanup
This commit is contained in:
parent
6c581fb8c2
commit
83d7134d64
2 changed files with 27 additions and 17 deletions
|
@ -38,14 +38,12 @@ Grammar::Grammar ()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void Grammar::loadFromFile (File& file)
|
void Grammar::loadFromFile (File& file)
|
||||||
{
|
{
|
||||||
if (file.exists ())
|
if (! file.exists ())
|
||||||
{
|
throw format ("Grammar file '{1}' not found.", file._data);
|
||||||
std::string contents;
|
|
||||||
file.read (contents);
|
std::string contents;
|
||||||
loadFromString (contents);
|
file.read (contents);
|
||||||
}
|
loadFromString (contents);
|
||||||
else
|
|
||||||
throw format ("Grammar file '{1}' not found.", static_cast<std::string> (file));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -70,8 +68,8 @@ void Grammar::loadFromFile (File& file)
|
||||||
void Grammar::loadFromString (const std::string& input)
|
void Grammar::loadFromString (const std::string& input)
|
||||||
{
|
{
|
||||||
std::string rule_name = "";
|
std::string rule_name = "";
|
||||||
int token_count = 0;
|
|
||||||
|
|
||||||
|
// This is a state machine. Read each line.
|
||||||
for (auto& line : split (input, '\n'))
|
for (auto& line : split (input, '\n'))
|
||||||
{
|
{
|
||||||
// Skip whole-line comments.
|
// Skip whole-line comments.
|
||||||
|
@ -83,15 +81,14 @@ void Grammar::loadFromString (const std::string& input)
|
||||||
if (hash != std::string::npos)
|
if (hash != std::string::npos)
|
||||||
line.resize (hash);
|
line.resize (hash);
|
||||||
|
|
||||||
line = Lexer::trim (line);
|
|
||||||
|
|
||||||
// Skip blank lines with no semantics.
|
// Skip blank lines with no semantics.
|
||||||
|
line = Lexer::trim (line);
|
||||||
if (line == "" and rule_name == "")
|
if (line == "" and rule_name == "")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (line != "")
|
if (line != "")
|
||||||
{
|
{
|
||||||
token_count = 0;
|
int token_count = 0;
|
||||||
|
|
||||||
Lexer l (line);
|
Lexer l (line);
|
||||||
Lexer::Type type;
|
Lexer::Type type;
|
||||||
|
@ -102,7 +99,10 @@ void Grammar::loadFromString (const std::string& input)
|
||||||
|
|
||||||
if (token.back () == ':')
|
if (token.back () == ':')
|
||||||
{
|
{
|
||||||
|
// Capture the Rule_name.
|
||||||
rule_name = token.substr (0, token.size () - 1);
|
rule_name = token.substr (0, token.size () - 1);
|
||||||
|
|
||||||
|
// If this is the first Rule, capture it as a starting point.
|
||||||
if (_start == "")
|
if (_start == "")
|
||||||
_start = rule_name;
|
_start = rule_name;
|
||||||
|
|
||||||
|
@ -111,22 +111,30 @@ void Grammar::loadFromString (const std::string& input)
|
||||||
}
|
}
|
||||||
else if (token.front () == ':')
|
else if (token.front () == ':')
|
||||||
{
|
{
|
||||||
// Decorate the most recent token, of the most recent production,
|
// Decorate the most recent token, of the most recent Production,
|
||||||
// of the current rule.
|
// of the current Rule.
|
||||||
_rules[rule_name].back ().back ().decorate (token);
|
_rules[rule_name].back ().back ().decorate (token);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// If no Production was added yet, add one.
|
||||||
if (token_count <= 1)
|
if (token_count <= 1)
|
||||||
_rules[rule_name].push_back (Grammar::Production ());
|
_rules[rule_name].push_back (Grammar::Production ());
|
||||||
|
|
||||||
|
// Add the new Token to the most recent Production, of the current
|
||||||
|
// Rule.
|
||||||
_rules[rule_name].back ().push_back (Grammar::Token (token));
|
_rules[rule_name].back ().push_back (Grammar::Token (token));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A blank line in the input ends the current rule definition.
|
||||||
else
|
else
|
||||||
rule_name = "";
|
rule_name = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate the parsed grammar.
|
||||||
|
validate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -135,6 +143,7 @@ std::string Grammar::dump () const
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
for (auto& rule : _rules)
|
for (auto& rule : _rules)
|
||||||
{
|
{
|
||||||
|
// Indicate the start Rule.
|
||||||
if (rule.first == _start)
|
if (rule.first == _start)
|
||||||
out << "▶ ";
|
out << "▶ ";
|
||||||
|
|
||||||
|
@ -145,9 +154,10 @@ std::string Grammar::dump () const
|
||||||
out << " ";
|
out << " ";
|
||||||
for (auto& term : production)
|
for (auto& term : production)
|
||||||
{
|
{
|
||||||
out << term._token << " ";
|
out << term._token;
|
||||||
if (term._decoration != "")
|
if (term._decoration != "")
|
||||||
out << "(" << term._decoration << ") ";
|
out << term._decoration;
|
||||||
|
out << " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
out << "\n";
|
out << "\n";
|
||||||
|
|
|
@ -48,7 +48,7 @@ int main (int argc, const char** argv)
|
||||||
|
|
||||||
// TODO Load CLI grammar.
|
// TODO Load CLI grammar.
|
||||||
// TODO Load from string, else file on config override.
|
// TODO Load from string, else file on config override.
|
||||||
// TODO Migrate from loading a grammar from file, to a string.
|
// TODO Migrate from loading a grammar from file, to a default string.
|
||||||
File file ("./grammar.cfg");
|
File file ("./grammar.cfg");
|
||||||
Grammar grammar;
|
Grammar grammar;
|
||||||
grammar.loadFromFile (file);
|
grammar.loadFromFile (file);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue