1 // =================================
  2 // Copyright (c) 2020 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <sngcpp/ast/SourceFile.hpp>
  7 #include <sngcpp/ast/Visitor.hpp>
  8 #include <sngcpp/ast/Writer.hpp>
  9 #include <sngcpp/ast/Reader.hpp>
 10 #include <soulng/util/Unicode.hpp>
 11 #include <soulng/util/Sha1.hpp>
 12 
 13 namespace sngcpp { namespace ast {
 14 
 15 using namespace soulng::unicode;
 16 using namespace soulng::util;
 17 
 18 SourceFileNode::SourceFileNode() : Node(NodeType::sourceFileNode)sourceFileIndex(-1)processed()
 19 {
 20 }
 21 
 22 SourceFileNode::SourceFileNode(const Span& span_const std::string& sourceFilePath_const std::string& relativeSourceFilePath_const std::u32string& projectName_) :
 23     Node(NodeType::sourceFileNodespan_)globalNs(new NamespaceNode(span_))sourceFilePath(sourceFilePath_)relativeSourceFilePath(relativeSourceFilePath_)projectName(projectName_)
 24     sourceFileIndex(-1)processed(false)
 25 {
 26     std::string fileName = relativeSourceFilePath;
 27     for (char& c : fileName)
 28     {
 29         if (c == '/' || c == '\\' || c == ':')
 30         {
 31             c = '_';
 32         }
 33     }
 34     fileName.append(1'_').append(GetSha1MessageDigest(sourceFilePath));
 35     fileName.append(".html");
 36     id = U"file/" + ToUtf32(fileName);
 37 }
 38 
 39 void SourceFileNode::AddUsingDirectiveOrDeclaration(Node* usingDirectivesAndDeclaration)
 40 {
 41     usingDirectivesAndDeclarations.push_back(usingDirectivesAndDeclaration);
 42 }
 43 
 44 void SourceFileNode::Accept(Visitor& visitor)
 45 {
 46     visitor.Visit(*this);
 47 }
 48 
 49 void SourceFileNode::Write(Writer& writer)
 50 {
 51     Node::Write(writer);
 52     writer.GetBinaryWriter().Write(sourceFilePath);
 53     writer.GetBinaryWriter().Write(relativeSourceFilePath);
 54     writer.GetBinaryWriter().Write(projectName);
 55     writer.GetBinaryWriter().Write(htmlSourceFilePath);
 56     writer.GetBinaryWriter().Write(id);
 57     globalNs->Write(writer);
 58     int32_t n = lineStarts.size();
 59     writer.GetBinaryWriter().Write(n);
 60     for (int32_t i = 0; i < n; ++i)
 61     {
 62         writer.GetBinaryWriter().Write(int32_t(lineStarts[i]));
 63     }
 64     int32_t numHeaderfiles = headerFilePaths.size();
 65     writer.GetBinaryWriter().Write(numHeaderfiles);
 66     for (int32_t i = 0; i < numHeaderfiles; ++i)
 67     {
 68         writer.GetBinaryWriter().Write(headerFilePaths[i]);
 69     }
 70     writer.GetBinaryWriter().Write(text);
 71 }
 72 
 73 void SourceFileNode::Read(Reader& reader)
 74 {
 75     Node::Read(reader);
 76     sourceFilePath = reader.GetBinaryReader().ReadUtf8String();
 77     relativeSourceFilePath = reader.GetBinaryReader().ReadUtf8String();
 78     projectName = reader.GetBinaryReader().ReadUtf32String();
 79     htmlSourceFilePath = reader.GetBinaryReader().ReadUtf8String();
 80     id = reader.GetBinaryReader().ReadUtf32String();
 81     globalNs.reset(reader.ReadNamespaceNode());
 82     int32_t n = reader.GetBinaryReader().ReadInt();
 83     for (int32_t i = 0; i < n; ++i)
 84     {
 85         lineStarts.push_back(reader.GetBinaryReader().ReadInt());
 86     }
 87     int32_t numHeaderfiles = reader.GetBinaryReader().ReadInt();
 88     for (int32_t i = 0; i < numHeaderfiles; ++i)
 89     {
 90         headerFilePaths.push_back(reader.GetBinaryReader().ReadUtf8String());
 91     }
 92     text = reader.GetBinaryReader().ReadUtf32String();
 93 }
 94 
 95 void SourceFileNode::ComputeLineStarts()
 96 {
 97     int index = 0;
 98     bool startOfLine = true;
 99     for (char32_t c : text)
100     {
101         if (startOfLine)
102         {
103             lineStarts.push_back(index);
104             startOfLine = false;
105         }
106         if (c == U'\n')
107         {
108             startOfLine = true;
109         }
110         ++index;
111     }
112 }
113 
114 SourceFileSequenceNode::SourceFileSequenceNode() : BinaryNode(NodeType::sourceFileSequenceNode)
115 {
116 }
117 
118 SourceFileSequenceNode::SourceFileSequenceNode(const Span& span_Node* left_Node* right_) : BinaryNode(NodeType::sourceFileSequenceNodespan_left_right_)
119 {
120 }
121 
122 void SourceFileSequenceNode::Accept(Visitor& visitor)
123 {
124     visitor.Visit(*this);
125 }
126 
127 class SourceFileResolverVisitor public Visitor
128 {
129 public:
130     SourceFileResolverVisitor(std::std::vector<SourceFileNode*>&sourceFiles_):sourceFiles(sourceFiles_)
131     {
132     }
133     void Visit(SourceFileNode& sourceFileNode) override
134     {
135         sourceFiles.push_back(&sourceFileNode);
136     }
137     void Visit(SourceFileSequenceNode& sourceFileSequenceNode) override
138     {
139         sourceFileSequenceNode.Left()->Accept(*this);
140         sourceFileSequenceNode.Right()->Accept(*this);
141     }
142 private:
143     std::std::vector<SourceFileNode*>&sourceFiles;
144 };
145 
146 void ResolveSourceFiles(Node* aststd::std::vector<SourceFileNode*>&sourceFiles)
147 {
148     SourceFileResolverVisitor resolver(sourceFiles);
149     ast->Accept(resolver);
150 }
151 
152 } } // namespace sngcpp::ast