Commit d067b7d7 authored by js9's avatar js9

improved debugging output and grammar state summary output

cleanup up shift-reduce conflict code, both for correctness and error reporting
added backslashes as an allowable symbol in the scanner
added backslashes as the equivalent of forward slashes, but ONLY in paths
added support for using a backslash as an escaping mechanism
  -- you can escape *anything* except a foward or backward slash and it
     will treat it as a character, so you can now have variable names
     with any special character in them, such as "a (meters)" via
     "a\ \(meters\)".  IOW, this lets you avoid having to use the <>
     variable quoting if you don't need to specify a host, cycle, etc.



git-svn-id: http://visit.ilight.com/svn/visit/trunk/src@4653 18c085ea-50e0-402c-830e-de6fd14e8384
parent ebb86229
......@@ -64,6 +64,10 @@
// I made the symbols be static in the ExprGrammar class so there are no
// conflicts with Python 2.5.
//
// Jeremy Meredith, Wed Jul 23 13:29:06 EDT 2008
// Added a backslash symbol. We use it both for escaping and as
// a path separator. Added two rules here for the latter use.
//
Dictionary D;
......@@ -74,6 +78,7 @@ Symbol ExprGrammar::T_Plus (D, '+');
Symbol ExprGrammar::T_Mult (D, '*');
Symbol ExprGrammar::T_Minus (D, '-');
Symbol ExprGrammar::T_Slash (D, '/');
Symbol ExprGrammar::T_BackSlash (D, '\\');
Symbol ExprGrammar::T_Exp (D, '^');
Symbol ExprGrammar::T_Mod (D, '%');
Symbol ExprGrammar::T_LBracket (D, '[');
......@@ -196,6 +201,8 @@ ExprGrammar::ExprGrammar() : Grammar(D)
// MultiSlash
AddRule(Rule(0, MultiSlash) >> MultiSlash + T_Slash);
AddRule(Rule(1, MultiSlash) >> T_Slash);
AddRule(Rule(2, MultiSlash) >> MultiSlash + T_BackSlash);
AddRule(Rule(3, MultiSlash) >> T_BackSlash);
// Variable
AddRule(Rule(0, Variable) >> T_Ident );
......
......@@ -59,6 +59,10 @@
// I made the symbols be static in the ExprGrammar class so there are no
// conflicts with Python 2.5.
//
// Jeremy Meredith, Wed Jul 23 13:29:06 EDT 2008
// Added a backslash symbol. We use it both for escaping and as
// a path separator.
//
// ****************************************************************************
class EXPR_API ExprGrammar : public Grammar
{
......@@ -74,6 +78,7 @@ class EXPR_API ExprGrammar : public Grammar
static Symbol T_Mult;
static Symbol T_Minus;
static Symbol T_Slash;
static Symbol T_BackSlash;
static Symbol T_Exp;
static Symbol T_Mod;
static Symbol T_LBracket;
......
This diff is collapsed.
......@@ -149,6 +149,9 @@ ExprParser::ExprParser(ExprNodeFactory *f) : Parser(), factory(f)
// Changed C-stype commented-out code block for case 14 to conditionally
// compiled code block.
//
// Jeremy Meredith, Wed Jul 23 11:20:17 EDT 2008
// Allow backslashes in paths for better windows support.
//
// ****************************************************************************
ParseTreeNode*
ExprParser::ApplyRule(const Symbol &sym,
......@@ -395,6 +398,12 @@ ExprParser::ApplyRule(const Symbol &sym,
case 1:
node = new DummyNode(p);
break;
case 2:
node = new DummyNode(p);
break;
case 3:
node = new DummyNode(p);
break;
}
} else if (sym == ExprGrammar::Variable)
{
......
......@@ -52,7 +52,7 @@ using std::string;
// ----------------------------------------------------------------------------
// Scanner modifications:
// Jeremy Meredith, Mon Jul 28 14:36:21 PDT 2003
// Allow dots in tokens that started with were clearly scanned as
// Allow dots in tokens that were starting to be clearly scanned as
// identifiers already. For example, "alpha.1" will scan as a single
// identifier now, without the need for the "<>" notation.
//
......@@ -119,20 +119,30 @@ static const bool StateAcceptance[13] = {
// Mark C. Miller, Mon Apr 14 15:41:21 PDT 2008
// Added support for '&' binary, bitwise, and expression
//
// Jeremy Meredith, Wed Jul 23 13:13:42 EDT 2008
// Allow backslashes. Add quoting support.
//
// ****************************************************************************
int
ExprScanner::GetCharType(const char c)
ExprScanner::GetCharType(const char c, bool escaped) const
{
ScanState s = scanstate.back();
int type = Err;
if (c)
if (escaped)
{
if (c == '\\' || c == '/')
type = Sym;
else if (c)
type = Alp;
}
else if (c)
{
if (c == '\"')
type = Quo;
else if (c == '+' || c == '-')
type = Sgn;
else if (strchr("*/+-[]{}()<>=,^%@:#&", c))
else if (strchr("*/+-[]{}()<>=,^%@:#&\\", c))
type = Sym;
else if (c == 'e' || c == 'E')
type = Eee;
......@@ -291,6 +301,10 @@ ExprScanner::UpdateScanState(const std::string &parsed)
// Programmer: Jeremy Meredith
// Creation: April 5, 2002
//
// Modifications:
// Jeremy Meredith, Wed Jul 23 13:12:22 EDT 2008
// Add support for using a backslash as an escaping mechanism.
//
// ****************************************************************************
Token*
ExprScanner::ScanOneToken()
......@@ -304,12 +318,21 @@ ExprScanner::ScanOneToken()
if (pos < text.length())
lookahead = text[pos];
// If it was a backslash, just use quoting
bool backslashEscape = lookahead == '\\';
if (backslashEscape)
{
lookahead = 0;
if (pos+1 < text.length())
lookahead = text[pos+1];
}
// Nothing left to parse, and no unfinished token to accept
if (state == 0 && lookahead == 0)
return new EndOfInput(pos);
// Get the character type, the next state, and an accept token
int type = GetCharType(lookahead);
int type = GetCharType(lookahead, backslashEscape);
int next = (type == Err) ? -1 : StateTransition[state][type];
bool accept = StateAcceptance[state];
......@@ -345,6 +368,8 @@ ExprScanner::ScanOneToken()
}
// Push the lookahead and keep going
if (backslashEscape) // skip the backslash too if we got one
pos++;
pos++;
workstring += lookahead;
state = next;
......
......@@ -69,6 +69,9 @@ using std::deque;
// Major refactoring caused this class to be renamed to ExprScanner
// and Token to ExprToken.
//
// Jeremy Meredith, Wed Jul 23 13:37:20 EDT 2008
// Allow the character type to take into account a backslash-escape.
//
// ****************************************************************************
class EXPR_API ExprScanner : public Scanner
{
......@@ -111,7 +114,7 @@ class EXPR_API ExprScanner : public Scanner
Token *ScanOneToken();
private:
int GetCharType(const char c);
int GetCharType(const char c, bool escaped) const;
Token *GetAcceptToken(const Pos&,const std::string&, int);
void UpdateScanState(const std::string &parsed);
......
......@@ -109,13 +109,17 @@ Grammar::SetPrinter(ostream *o)
// Programmer: Jeremy Meredith
// Creation: April 5, 2002
//
// Modifications:
// Jeremy Meredith, Wed Jul 23 13:15:57 EDT 2008
// Add the rule number when printing for easier cross-reference.
//
// ****************************************************************************
void
Grammar::Print(ostream &o)
{
o << endl << TermBold << TermBrown << "- - - ------------- rules ------------- - - -\n" << TermReset;
for (size_t i=0; i<rules.size(); i++)
o << *(rules[i]) << endl;
o << i <<":" << *(rules[i]) << endl;
o << endl << TermBold << TermBrown << "- - - ------------- states ------------- - - -\n" << TermReset;
for (size_t i=0; i<sets.size(); i++)
{
......@@ -269,6 +273,17 @@ Grammar::GetDictionary()
// Programmer: Jeremy Meredith
// Creation: April 5, 2002
//
// Modifications:
// Jeremy Meredith, Wed Jul 23 13:23:14 EDT 2008
// Cleaned up the logic in the shift-reduce conflict resolution.
// Using the last terminal in the reduce rule to find precedence
// is a nice convenience, and it makes sense, but it was coded such
// that there was an assumption that there *was* a terminal in
// the reduce rule. In fact, it's fine not to have one, it just
// means we can only use a precedence attached to the rule itself.
// Also, by cleaning it up, I was able to add extra info to the
// error messages.
//
// ****************************************************************************
bool
Grammar::Configure()
......@@ -349,42 +364,61 @@ Grammar::Configure()
if (!ssym || !reduce.set[i])
continue;
// We know there's only one reduce rule
const Rule *reducerule = rules[sets[j].GetReduceRules(ssym)[0]];
const Symbol *rsym = reducerule->GetRHS().GetLastTerminal();
bool same = (ssym == rsym);
int sprec = prec.count(ssym) ? prec[ssym] : -1;
int rprec = reducerule->GetPrec();
if (rprec == -1)
rprec = prec.count(rsym) ? prec[rsym] : -1;
bool haveprec = (sprec >= 0 && rprec >= 0);
bool haveassoc = assoc.count(ssym);
// Try to resolve using precedence or associativity
if (!same && haveprec && sprec!=rprec)
// Check precedence against reduce rule first
if (haveprec && sprec!=rprec)
{
if (sprec < rprec)
{
sets[j].RemoveShiftTransition(ssym);
(*out) << TermGreen << "SR conflict in state " << j << " for " << *ssym << " and rule "<<reducerule->GetIndex()<<" resolved by higher precedence of "<< *ssym << TermReset << endl;
}
else
{
sets[j].RemoveReduceRule(ssym);
(*out) << TermGreen << "SR conflict in state " << j << " for " << *ssym << " and " << *rsym << " resolved by precedence" << TermReset << endl;
(*out) << TermGreen << "SR conflict in state " << j << " for " << *ssym << " and rule "<<reducerule->GetIndex()<<" resolved by higher precedence of rule " << TermReset << endl;
}
continue;
}
else if (haveassoc && (same || (haveprec && sprec==rprec)))
// Okay, no dice. Try using the last terminal in the rule
const Symbol *rsym = reducerule->GetRHS().GetLastTerminal();
rprec = prec.count(rsym) ? prec[rsym] : -1;
haveprec = (sprec >= 0 && rprec >= 0);
// Try associativity first.
bool same = (ssym == rsym);
if (assoc.count(ssym) && (same || (haveprec && sprec==rprec)))
{
if (assoc[ssym] != Right)
sets[j].RemoveShiftTransition(ssym);
if (assoc[ssym] != Left)
sets[j].RemoveReduceRule(ssym);
(*out) << TermGreen << "SR conflict in state " << j << " for " << *ssym << " and " << *rsym << " resolved by " << (assoc[ssym] == Left ? "left" : "right") << " assoc "<< TermReset << endl;
(*out) << TermGreen << "SR conflict in state " << j << " for " << *ssym << " and rule " << reducerule->GetIndex() << " resolved by " << (assoc[ssym] == Left ? "left" : "right") << " assoc "<< TermReset << endl;
continue;
}
else
// Nope, so now try using it for precedence.
if (haveprec && sprec!=rprec)
{
// failed to resolve... set the error flag
sets[j].SetConflict(true);
okay = false;
(*out) << TermRed << "SR conflict in state " << j << " for " << *ssym << " and " << *rsym << TermReset << endl;
if (sprec < rprec)
sets[j].RemoveShiftTransition(ssym);
else
sets[j].RemoveReduceRule(ssym);
(*out) << TermGreen << "SR conflict in state " << j << " for " << *ssym << " and "<<*rsym<<" resolved by higher precedence of "<<(sprec < rprec ? *ssym : *rsym) << TermReset << endl;
continue;
}
// failed to resolve... set the error flag
sets[j].SetConflict(true);
okay = false;
(*out) << TermRed << "SR conflict in state " << j << " for " << *ssym << " and rule " << reducerule->GetIndex() << TermReset << endl;
}
}
......@@ -431,6 +465,10 @@ Grammar::Configure()
// Jeremy Meredith, Tue Jun 5 13:29:33 EDT 2007
// Added copyright notice. Added parentheses to function definition.
//
// Jeremy Meredith, Wed Jul 23 13:25:32 EDT 2008
// Since we now have backslash as a symbol, escape it properly
// (with an extra backslash).
//
// ****************************************************************************
void
......@@ -516,7 +554,9 @@ Grammar::WriteStateInitialization(const string &name, ostream &o)
if (s->IsNonTerminal())
o << "\"" << s->GetDisplayString().c_str() << "\"";
else
if (tt < 256)
if (tt == '\\')
o << "'\\\\'";
else if (tt < 256)
o << "'" << char(tt) << "'";
else
o << tt;
......@@ -557,7 +597,9 @@ Grammar::WriteStateInitialization(const string &name, ostream &o)
if (s->IsNonTerminal())
o << "\"" << s->GetDisplayString().c_str() << "\"";
else
if (tt < 256)
if (tt == '\\')
o << "'\\\\'";
else if (tt < 256)
o << "'" << char(tt) << "'";
else
o << tt;
......
......@@ -53,6 +53,8 @@
// Creation: November 11, 2004
//
// Modifications:
// Jeremy Meredith, Wed Jul 23 13:15:15 EDT 2008
// Separate the parent printout from this one if necessary.
//
// ****************************************************************************
......@@ -62,7 +64,8 @@ ParseTreeNode::Print(ostream &o, std::string s)
static int indent = 0;
for (int i=0; i<indent; i++)
o << " ";
o << s.c_str();
if (!s.empty())
o << s.c_str() << ": ";
indent++;
PrintNode(o);
indent--;
......
......@@ -132,12 +132,16 @@ Parser::Shift(Token *t, int s)
// applying the reduction. This fixes a number of memory leaks.
// I also ensured that pos was well populated in all cases.
//
// Jeremy Meredith, Wed Jul 23 13:26:26 EDT 2008
// Add the rule index to the debug info.
//
// ****************************************************************************
void
Parser::Reduce(int r)
{
#ifdef MOREDEBUG
cerr << "Reducing using rule " << *(G->GetRule(r)) << endl;
cerr << "Reducing using rule " << G->GetRule(r)->GetIndex() << ": "
<< *(G->GetRule(r)) << endl;
#endif
const Rule *rule = G->GetRule(r);
const Symbol *lhs = rule->GetLHS();
......@@ -205,12 +209,18 @@ Parser::Reduce(int r)
// Programmer: Jeremy Meredith
// Creation: April 5, 2002
//
// Modifications:
// Jeremy Meredith, Wed Jul 23 13:26:44 EDT 2008
// Uncomment the state debug info, but only print in MOREDEBUG.
//
// ****************************************************************************
void
Parser::PrintState(ostream &o)
{
#ifdef DEBUG
//o << "state= "; for (size_t i=0; i<states.size(); i++) o << states[i] << " "; o << endl;
#ifdef MOREDEBUG
o << "state= "; for (size_t i=0; i<states.size(); i++) o << states[i] << " "; o << endl;
#endif
o << "stack= "; for (size_t i=0; i<elems.size(); i++) o << *(elems[i].sym) << " "; o << endl;
#endif
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment