1 // =================================
  2 // Copyright (c) 2020 Seppo Laakko
  3 // Distributed under the MIT license
  4 // =================================
  5 
  6 #include <sng2html/sng2html/LexerFile.hpp>
  7 #include <sng2html/sng2html/RegExLexer.hpp>
  8 #include <sng2html/sng2html/RegExParser.hpp>
  9 #include <soulng/cppcode/Expression.hpp>
 10 #include <soulng/cppcode/Visitor.hpp>
 11 #include <soulng/util/CodeFormatter.hpp>
 12 #include <soulng/util/Path.hpp>
 13 #include <soulng/util/Unicode.hpp>
 14 #include <fstream>
 15 #include <iostream>
 16 
 17 namespace sng2html { namespace sng2html {
 18 
 19 const char* LexerGeneratorVersionStr()
 20 {
 21     return "3.0.0";
 22 }
 23 
 24 using namespace soulng::util;
 25 using namespace soulng::unicode;
 26 
 27 Declaration::Declaration(const std::u32string& name_) : name(name_)
 28 {
 29 }
 30 
 31 Declaration::~Declaration()
 32 {
 33 }
 34 
 35 ClassMap::ClassMap(const std::u32string& name_) : Declaration(name_)
 36 {
 37 }
 38 
 39 Prefix::Prefix(const std::u32string& prefix_) : Declaration(prefix_)
 40 {
 41 }
 42 
 43 IncludeDeclaration::IncludeDeclaration(const std::u32string& header_) : Declaration(U"include")header(header_)
 44 {
 45 }
 46 
 47 Token::Token() : name()info()
 48 {
 49 }
 50 
 51 Token::Token(const std::u32string& name_const std::string& info_) : name(name_)info(info_)
 52 {
 53 }
 54 
 55 Tokens::Tokens(const std::u32string& name_) : Declaration(name_)
 56 {
 57 }
 58 
 59 void Tokens::Add(const Token& token)
 60 {
 61     tokens.push_back(token);
 62 }
 63 
 64 Keyword::Keyword(const std::u32string& kw_const std::u32string& token_) : kw(kw_)token(token_)
 65 {
 66 }
 67 
 68 Keywords::Keywords(const std::u32string& name_) : Declaration(name_)
 69 {
 70 }
 71 
 72 void Keywords::Add(Keyword* keyword)
 73 {
 74     keywords.push_back(std::unique_ptr<Keyword>(keyword));
 75     keywordMap[keyword->token] = keyword->kw;
 76 }
 77 
 78 std::u32string Keywords::GetKeyword(const std::u32string& tokenId) const
 79 {
 80     auto it = keywordMap.find(tokenId);
 81     if (it != keywordMap.cend())
 82     {
 83         return it->second;
 84     }
 85     else
 86     {
 87         return std::u32string();
 88     }
 89 }
 90 
 91 void Keywords::AddToLexerFile(LexerFile& lexerFile)
 92 {
 93     lexerFile.SetKeywords(this);
 94 }
 95 
 96 Expression::Expression(int index_const std::u32string& id_const std::u32string& value_int line_) : index(index_)id(id_)value(value_)line(line_)
 97 {
 98 }
 99 
100 void Expression::Parse(LexerContext& lexerContext)
101 {
102     RegExLexer lexer(value""0);
103     regEx = RegExParser::Parse(lexer&lexerContext);
104 }
105 
106 Expressions::Expressions() : Declaration(U"expressions")
107 {
108 }
109 
110 void Expressions::AddToLexerFile(LexerFile& lexerFile)
111 {
112     lexerFile.SetExpressions(this);
113 }
114 
115 void Expressions::Add(Expression* expression)
116 {
117     expressions.push_back(std::unique_ptr<Expression>(expression));
118     exprMap[expression->Id()] = expression->Index();
119 }
120 
121 Expression* Expressions::Get(const std::u32string& id) const
122 {
123     auto it = exprMap.find(id);
124     if (it != exprMap.cend())
125     {
126         int index = it->second;
127         return expressions[index].get();
128     }
129     else
130     {
131         throw std::runtime_error("expression '" + ToUtf8(id) + "' not found");
132     }
133 }
134 
135 void Expressions::Parse(LexerContext& lexerContext)
136 {
137     for (auto& expr : expressions)
138     {
139         expr->Parse(lexerContext);
140     }
141     Expression* idStart = new Expression(expressions.size()U"idstart"std::u32string()0);
142     idStart->SetRegEx(new SymbolExpr(lexerContext.MakeIdStart()));
143     Add(idStart);
144     Expression* idCont = new Expression(expressions.size()U"idcont"std::u32string()0);
145     idCont->SetRegEx(new SymbolExpr(lexerContext.MakeIdCont()));
146     Add(idCont);
147 }
148 
149 LexerVariable::LexerVariable(soulng::cppcode::TypeId* type_const std::u32string& name_) : type(type_)name(name_)
150 {
151 }
152 
153 class TokenIdResolverVisitor public soulng::cppcode::Visitor
154 {
155 public:
156     void Visit(soulng::cppcode::ReturnStatement& object) override;
157     const std::u32string& TokenId() const { return tokenId; }
158 private:
159     std::u32string tokenId;
160 };
161 
162 void TokenIdResolverVisitor::Visit(soulng::cppcode::ReturnStatement& object)
163 {
164     if (tokenId.empty())
165     {
166         if (object.GetExpression())
167         {
168             tokenId = object.GetExpression()->Name();
169         }
170     }
171 }
172 
173 LexerStatement::LexerStatement(const std::u32string& expr_soulng::cppcode::CompoundStatement* stmt_int action_int line_) :
174     index(-1)expr(expr_)stmt(stmt_)retract(true)action(action_)line(line_)
175 {
176     TokenIdResolverVisitor visitor;
177     stmt->Accept(visitor);
178     tokenId = visitor.TokenId();
179 }
180 
181 void LexerStatement::Parse(LexerContext& lexerContext)
182 {
183     RegExLexer lexer(expr""0);
184     regEx = RegExParser::Parse(lexer&lexerContext);
185 }
186 
187 Lexer::Lexer(const std::u32string& api_const std::u32string& name_) : Declaration(name_)api(api_)
188 {
189 }
190 
191 void Lexer::AddStatement(LexerStatement* stmt)
192 {
193     stmt->SetIndex(statements.size());
194     statements.push_back(std::unique_ptr<LexerStatement>(stmt));
195     lexerStatementMap[stmt->TokenId()] = stmt;
196 }
197 
198 LexerStatement* Lexer::GetStatement(const std::u32string& tokenId) const
199 {
200     auto it = lexerStatementMap.find(tokenId);
201     if (it != lexerStatementMap.cend())
202     {
203         return it->second;
204     }
205     else
206     {
207         return nullptr;
208     }
209 }
210 
211 void Lexer::AddVariable(LexerVariable* variable)
212 {
213     variables.push_back(std::unique_ptr<LexerVariable>(variable));
214 }
215 
216 void Lexer::AddAction(Action* action)
217 {
218     actions.Add(action);
219 }
220 
221 void Lexer::AddToLexerFile(LexerFile& lexerFile)
222 {
223     lexerFile.SetLexer(this);
224 }
225 
226 void Lexer::Parse(LexerContext& lexerContext)
227 {
228     for (auto& statement : statements)
229     {
230         statement->Parse(lexerContext);
231     }
232 }
233 
234 Action::Action(int id_soulng::cppcode::CompoundStatement* stmt_) : id(id_)stmt(stmt_)
235 {
236 }
237 
238 Actions::Actions() : Declaration(U"actions")
239 {
240 }
241 
242 void Actions::Add(Action* action)
243 {
244     actions.push_back(std::unique_ptr<Action>(action));
245     actionMap[action->Id()] = action;
246 }
247 
248 Action* Actions::Get(int id) const
249 {
250     auto it = actionMap.find(id);
251     if (it != actionMap.cend())
252     {
253         return it->second;
254     }
255     else
256     {
257         return nullptr;
258     }
259 }
260 
261 LexerFile::LexerFile() : keywords(nullptr)lexer(nullptr)expressions(nullptr)
262 {
263 }
264 
265 void LexerFile::Accept(Visitor& visitor)
266 {
267     visitor.Visit(*this);
268 }
269 
270 void LexerFile::Add(Declaration* declaration)
271 {
272     declarations.push_back(std::unique_ptr<Declaration>(declaration));
273     declaration->AddToLexerFile(*this);
274 }
275 
276 void LexerFile::Parse(LexerContext& lexerContext)
277 {
278     expressions->Parse(lexerContext);
279     lexer->Parse(lexerContext);
280 }
281 
282 } } // namespace sng2html::sng2html
283