Diff of /trunk/Soul/Soul.Parsing/Rule.cpp [000000] .. [r1]  Maximize  Restore

Switch to side-by-side view

--- a
+++ b/trunk/Soul/Soul.Parsing/Rule.cpp
@@ -0,0 +1,175 @@
+/*========================================================================
+    Copyright (c) 2011 Seppo Laakko
+    http://sourceforge.net/projects/soulparsing/
+ 
+    Distributed under the GNU General Public License, version 3 (GPLv3).
+    (See accompanying LICENSE.txt or http://www.gnu.org/licenses/gpl.html)
+
+========================================================================*/
+
+#include <Soul.Parsing/Rule.hpp>
+#include <Soul.Parsing/Visitor.hpp>
+#include <Soul.CppObjectModel/Visitor.hpp>
+#include <map>
+
+namespace Soul { namespace Parsing {
+
+RuleParser::RuleParser(const String& name_, const String& fullName_, bool external_): 
+    Parser("<" + name_ + ">"), 
+    name(name_), 
+    fullName(fullName_), 
+    external(external_),
+    definition(),
+    inheritedAttributes(),
+    localVariables(),
+    valueTypeName(),
+    actions(),
+    actionScope(name + ".actions", "Action"),
+    nonTerminals(),
+    nonTerminalScope(name + ".nonterminals", "NonTerminal")
+{
+}
+
+RuleParser::RuleParser(const String& name_, const String& fullName_, const ParserPtr& definition_): 
+    Parser("<" + name_ + ">"), 
+    name(name_), 
+    fullName(fullName_), 
+    external(false),
+    definition(definition_),
+    inheritedAttributes(),
+    localVariables(),
+    valueTypeName(),
+    actions(),
+    actionScope(name + ".actions", "Action"),
+    nonTerminals(),
+    nonTerminalScope(name + ".nonterminals", "NonTerminal")
+{
+}
+
+void RuleParser::AddAction(const ActionParserPtr& action)
+{
+    actionScope.Add(action);
+    actions.push_back(action);
+}
+
+ActionParserPtr RuleParser::GetAction(const String& actionName) const
+{
+    return actionScope.Get(actionName);
+}
+
+void RuleParser::AddNonTerminal(const NonTerminalParserPtr& nonTerminal)
+{
+    nonTerminalScope.Add(nonTerminal);
+    nonTerminals.push_back(nonTerminal);
+}
+
+NonTerminalParserPtr RuleParser::GetNonTerminal(const String& nonTerminalName) const
+{
+    return nonTerminalScope.Get(nonTerminalName);
+}
+
+using Soul::CppObjectModel::IdExpr;
+
+class CodeExpandingVisitor : public Soul::CppObjectModel::Visitor
+{
+public:
+    CodeExpandingVisitor(std::map<String, String>& expandMap_): expandMap(expandMap_) {}
+    virtual void Visit(IdExpr& expr)
+    {
+        std::map<String, String>::const_iterator i = expandMap.find(expr.Name());
+        if (i != expandMap.end())
+        {
+            expr.Name() = i->second;
+        }
+    }
+private:
+    std::map<String, String>& expandMap;
+};
+
+void RuleParser::ExpandCode()
+{
+    std::map<String, String> expandMap;
+    expandMap["value"] = "context->value";
+    int n = nonTerminals.size();
+    for (int i = 0; i < n; ++i)
+    {
+        NonTerminalParserPtr nonTerminal = nonTerminals[i];
+        expandMap[nonTerminal->Name()] = "context->" + nonTerminal->ValueFieldName();
+    }
+    n = inheritedAttributes.size();
+    for (int i = 0; i < n; ++i)
+    {
+        const AttrOrVariable& attr = inheritedAttributes[i];
+        expandMap[attr.Name()] = "context->" + attr.Name();
+    }
+    n = localVariables.size();
+    for (int i = 0; i < n; ++i)
+    {
+        const AttrOrVariable& var = localVariables[i];
+        expandMap[var.Name()] = "context->" + var.Name();
+    }
+    CodeExpandingVisitor visitor(expandMap);
+    n = actions.size();
+    for (int i = 0; i < n; ++i)
+    {
+        ActionParserPtr action = actions[i];
+        action->Code()->Accept(visitor);
+    }
+    n = nonTerminals.size();
+    for (int i = 0; i < n; ++i)
+    {
+        NonTerminalParserPtr nonTerminal = nonTerminals[i];
+        if (!nonTerminal->Arguments().empty())
+        {
+            int m = nonTerminal->Arguments().size();
+            for (int j = 0; j < m; ++j)
+            {
+                CppEntityPtr argument = nonTerminal->Arguments()[j];
+                argument->Accept(visitor);
+            }
+        }
+    }
+}
+
+Match RuleParser::Parse(Scanner& scanner, ObjectStack& stack)
+{
+    bool writeToLog = !scanner.Skipping() && scanner.Log();
+    if (writeToLog)
+    {
+        scanner.Log()->WriteBeginRule(name);
+        scanner.Log()->IncIndent();
+        scanner.Log()->WriteTry(scanner.RestOfLine());
+        scanner.Log()->IncIndent();
+    }
+    int startIndex = scanner.GetPosition().index;
+    Enter(stack);
+    Match match = definition ? definition->Parse(scanner, stack) : Match::Nothing();
+    Leave(stack, match.Hit());
+    if (writeToLog)
+    {
+        scanner.Log()->DecIndent();
+        if (match.Hit())
+        {
+            scanner.Log()->WriteSuccess(scanner.GetMatch(startIndex));
+        }
+        else
+        {
+            scanner.Log()->WriteFail();
+        }
+        scanner.Log()->DecIndent();
+        scanner.Log()->WriteEndRule(name);
+    }
+    return match;
+}
+
+void RuleParser::Accept(Visitor& visitor)
+{
+    visitor.BeginVisit(*this);
+    if (definition)
+    {
+        definition->Accept(visitor);
+    }
+    visitor.EndVisit(*this);
+}
+
+} } // namespace Soul.Parsing