[DEV] add a basic js parser
This commit is contained in:
parent
c2955dee56
commit
4dc0c39470
128
eci/File.cpp
128
eci/File.cpp
@ -10,6 +10,7 @@
|
||||
#include <eci/debug.h>
|
||||
#include <etk/os/FSNode.h>
|
||||
#include <eci/lang/ParserCpp.h>
|
||||
#include <eci/lang/ParserJS.h>
|
||||
|
||||
|
||||
static std::string getValue(const std::string& _file, const std::shared_ptr<eci::LexerNode>& _it) {
|
||||
@ -60,64 +61,77 @@ eci::Variable getVariableWithType(const std::string& _value) {
|
||||
|
||||
eci::File::File(const std::string& _filename) {
|
||||
m_fileName = _filename;
|
||||
m_fileData = etk::FSNodeReadAllData(_filename);
|
||||
eci::ParserCpp tmpParser;
|
||||
tmpParser.parse(m_fileData);
|
||||
|
||||
// all we need all the time:
|
||||
std::vector<eci::Variable> returnList;
|
||||
std::vector<eci::Variable> argumentList;
|
||||
std::string name;
|
||||
std::string value;
|
||||
std::shared_ptr<eci::Class> lastClass;
|
||||
std::shared_ptr<eci::Function> lastFunction;
|
||||
std::shared_ptr<eci::Variable> lastVariable;
|
||||
enum eci::visibility lastVisibility = eci::visibilityPublic;
|
||||
|
||||
for (auto &it : tmpParser.m_result.m_list) {
|
||||
value = getValue(m_fileData, it);
|
||||
switch (it->getTockenId()) {
|
||||
case tokenCppVisibility:
|
||||
ECI_INFO("get visibility : " << value << "'" );
|
||||
if (value == "private") {
|
||||
lastVisibility = eci::visibilityPrivate;
|
||||
} else if (value == "public") {
|
||||
lastVisibility = eci::visibilityPublic;
|
||||
} else if (value == "protected") {
|
||||
lastVisibility = eci::visibilityProtected;
|
||||
//} else if (value == "inline") {
|
||||
|
||||
//} else if (value == "const") {
|
||||
|
||||
//} else if (value == "virtual") {
|
||||
|
||||
//} else if (value == "friend") {
|
||||
|
||||
//} else if (value == "extern") {
|
||||
|
||||
//} else if (value == "register") {
|
||||
|
||||
//} else if (value == "static") {
|
||||
|
||||
//} else if (value == "volatile") {
|
||||
|
||||
} else {
|
||||
ECI_ERROR("get visibility : " << value << "' << NOT parsed !!!!" );
|
||||
}
|
||||
break;
|
||||
case tokenCppType:
|
||||
ECI_INFO("get type : " << value << "'" );
|
||||
if (name == "") {
|
||||
returnList.push_back(getVariableWithType(value));
|
||||
} else {
|
||||
ECI_ERROR(" get type : " << value << "' after name !!!" );
|
||||
}
|
||||
break;
|
||||
case tokenCppString:
|
||||
ECI_INFO("get string : " << value << "'" );
|
||||
name = value;
|
||||
break;
|
||||
m_fileData = etk::FSNodeReadAllData(m_fileName);
|
||||
if ( etk::end_with(m_fileName, "cpp", false) == true
|
||||
|| etk::end_with(m_fileName, "cxx", false) == true
|
||||
|| etk::end_with(m_fileName, "c", false) == true
|
||||
|| etk::end_with(m_fileName, "hpp", false) == true
|
||||
|| etk::end_with(m_fileName, "hxx", false) == true
|
||||
|| etk::end_with(m_fileName, "h", false) == true) {
|
||||
eci::ParserCpp tmpParser;
|
||||
tmpParser.parse(m_fileData);
|
||||
|
||||
// all we need all the time:
|
||||
std::vector<eci::Variable> returnList;
|
||||
std::vector<eci::Variable> argumentList;
|
||||
std::string name;
|
||||
std::string value;
|
||||
std::shared_ptr<eci::Class> lastClass;
|
||||
std::shared_ptr<eci::Function> lastFunction;
|
||||
std::shared_ptr<eci::Variable> lastVariable;
|
||||
enum eci::visibility lastVisibility = eci::visibilityPublic;
|
||||
|
||||
for (auto &it : tmpParser.m_result.m_list) {
|
||||
value = getValue(m_fileData, it);
|
||||
switch (it->getTockenId()) {
|
||||
case tokenCppVisibility:
|
||||
ECI_INFO("get visibility : " << value << "'" );
|
||||
if (value == "private") {
|
||||
lastVisibility = eci::visibilityPrivate;
|
||||
} else if (value == "public") {
|
||||
lastVisibility = eci::visibilityPublic;
|
||||
} else if (value == "protected") {
|
||||
lastVisibility = eci::visibilityProtected;
|
||||
//} else if (value == "inline") {
|
||||
|
||||
//} else if (value == "const") {
|
||||
|
||||
//} else if (value == "virtual") {
|
||||
|
||||
//} else if (value == "friend") {
|
||||
|
||||
//} else if (value == "extern") {
|
||||
|
||||
//} else if (value == "register") {
|
||||
|
||||
//} else if (value == "static") {
|
||||
|
||||
//} else if (value == "volatile") {
|
||||
|
||||
} else {
|
||||
ECI_ERROR("get visibility : " << value << "' << NOT parsed !!!!" );
|
||||
}
|
||||
break;
|
||||
case tokenCppType:
|
||||
ECI_INFO("get type : " << value << "'" );
|
||||
if (name == "") {
|
||||
returnList.push_back(getVariableWithType(value));
|
||||
} else {
|
||||
ECI_ERROR(" get type : " << value << "' after name !!!" );
|
||||
}
|
||||
break;
|
||||
case tokenCppString:
|
||||
ECI_INFO("get string : " << value << "'" );
|
||||
name = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (etk::end_with(m_fileName, "js", false) == true) {
|
||||
eci::ParserJS tmpParser;
|
||||
tmpParser.parse(m_fileData);
|
||||
|
||||
} else {
|
||||
ECI_CRITICAL("Unknow file type ... '" << m_fileName << "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
102
eci/eci.cpp
102
eci/eci.cpp
@ -12,25 +12,95 @@
|
||||
#include <etk/os/FSNode.h>
|
||||
#include <eci/Interpreter.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
etk::log::setLevel(etk::log::logLevelDebug);
|
||||
//etk::log::setLevel(etk::log::logLevelInfo);
|
||||
ECI_INFO("Start Application interpeter languages");
|
||||
if (argc<=1) {
|
||||
ECI_CRITICAL("need the file to parse");
|
||||
return -1;
|
||||
}
|
||||
//eci::ParserCpp tmpParser;
|
||||
//std::string data = "/* plop */ \n int eee = 22; // error value \nint main(void) {\n return 0;\n}\n";//etk::FSNodeReadAllData(argv[1]);
|
||||
//std::string data = "alpha /* plop */ test";
|
||||
//std::string data = "pp \n // qdfqdfsdf \nde";
|
||||
//tmpParser.parse(data);
|
||||
//tmpParser.parse(etk::FSNodeReadAllData(argv[1]));
|
||||
|
||||
void run_interactive() {
|
||||
ECI_CRITICAL("TODO ... create interactive interface");
|
||||
}
|
||||
|
||||
bool run_test(const std::string& _filename) {
|
||||
eci::Interpreter::Interpreter virtualMachine;
|
||||
virtualMachine.addFile(argv[1]);
|
||||
virtualMachine.addFile(_filename);
|
||||
|
||||
virtualMachine.main();
|
||||
return false;
|
||||
}
|
||||
|
||||
void run_test(const std::vector<std::string>& _listFileToTest) {
|
||||
|
||||
int32_t test_num = 1;
|
||||
int32_t count = 0;
|
||||
int32_t passed = 0;
|
||||
for (auto &it : _listFileToTest) {
|
||||
enum etk::typeNode type = etk::FSNode(it).getNodeType();
|
||||
if (type == etk::FSN_FOLDER) {
|
||||
etk::FSNode node(it);
|
||||
std::vector<std::string> list;
|
||||
node.folderGetRecursiveFiles(list, false);
|
||||
for (auto &it2 : list) {
|
||||
if (run_test(it2)) {
|
||||
passed++;
|
||||
}
|
||||
count++;
|
||||
test_num++;
|
||||
}
|
||||
} else if (type == etk::FSN_FILE) {
|
||||
if (run_test(it)) {
|
||||
passed++;
|
||||
}
|
||||
count++;
|
||||
test_num++;
|
||||
}
|
||||
}
|
||||
ECI_INFO("Done. " << count << " tests, " << passed << " pass, " << count-passed << " fail");
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// the only one init for etk:
|
||||
std::vector<std::string> listFileToTest;
|
||||
for (int32_t iii=1; iii<argc ; ++iii) {
|
||||
std::string data = argv[iii];
|
||||
if (data == "-l0") {
|
||||
etk::log::setLevel(etk::log::logLevelNone);
|
||||
} else if (data == "-l1") {
|
||||
etk::log::setLevel(etk::log::logLevelCritical);
|
||||
} else if (data == "-l2") {
|
||||
etk::log::setLevel(etk::log::logLevelError);
|
||||
} else if (data == "-l3") {
|
||||
etk::log::setLevel(etk::log::logLevelWarning);
|
||||
} else if (data == "-l4") {
|
||||
etk::log::setLevel(etk::log::logLevelInfo);
|
||||
} else if (data == "-l5") {
|
||||
etk::log::setLevel(etk::log::logLevelDebug);
|
||||
} else if (data == "-l6") {
|
||||
etk::log::setLevel(etk::log::logLevelVerbose);
|
||||
} else if ( data == "-h"
|
||||
|| data == "--help") {
|
||||
etk::log::setLevel(etk::log::logLevelVerbose);
|
||||
ECI_INFO("Help : ");
|
||||
ECI_INFO(" ./xxx [options]");
|
||||
ECI_INFO(" -l0: debug None");
|
||||
ECI_INFO(" -l1: debug Critical");
|
||||
ECI_INFO(" -l2: debug Error");
|
||||
ECI_INFO(" -l3: debug Warning");
|
||||
ECI_INFO(" -l4: debug Info");
|
||||
ECI_INFO(" -l5: debug Debug");
|
||||
ECI_INFO(" -l6: debug Verbose");
|
||||
ECI_INFO(" -h/--help: this help");
|
||||
exit(0);
|
||||
} else {
|
||||
listFileToTest.push_back(data);
|
||||
}
|
||||
}
|
||||
etk::setArgZero(argv[0]);
|
||||
|
||||
etk::initDefaultFolder("exml_test");
|
||||
ECI_INFO("input elements : " << listFileToTest);
|
||||
// Cocal parse :
|
||||
if (listFileToTest.size() == 0) {
|
||||
run_interactive();
|
||||
} else {
|
||||
run_test(listFileToTest);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
76
eci/lang/ParserJS.cpp
Normal file
76
eci/lang/ParserJS.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#include <eci/lang/ParserJS.h>
|
||||
#include <eci/debug.h>
|
||||
|
||||
|
||||
eci::ParserJS::ParserJS() {
|
||||
m_lexer.append(tokenJSCommentMultiline, "/\\*(.|\\r|\\n)*?(\\*/|\\0)");
|
||||
m_lexer.append(tokenJSCommentSingleLine, "//.*");
|
||||
m_lexer.append(tokenJSStringDoubleQuote, "\"(.|\\\\[\\\\\"])*?\"");
|
||||
m_lexer.append(tokenJSStringSimpleQuote, "'\\?.'");
|
||||
m_lexer.append(tokenJSBraceIn, "\\{");
|
||||
m_lexer.append(tokenJSBraceOut, "\\}");
|
||||
m_lexer.append(tokenJSPtheseIn, "\\(");
|
||||
m_lexer.append(tokenJSPtheseOut, "\\)");
|
||||
m_lexer.append(tokenJSHookIn, "\\[");
|
||||
m_lexer.append(tokenJSHookOut, "\\]");
|
||||
m_lexer.append(tokenJSBranch, "\\b(return|if|else|while|do|for)\\b");
|
||||
m_lexer.append(tokenJSType, "\\b(bool|char(16_t|32_t)?|double|float|u?int(8|16|32|64|128)?(_t)?|long|short|signed|size_t|unsigned|void)\\b");
|
||||
m_lexer.append(tokenJSContener, "\\b(var|function)\\b");
|
||||
m_lexer.append(tokenJSNumericValue, "\\b(((0(x|X)[0-9a-fA-F]*)|(\\d+\\.?\\d*|\\.\\d+)((e|E)(\\+|\\-)?\\d+)?)(L|l|UL|ul|u|U|F|f)?)\\b");
|
||||
m_lexer.append(tokenJSBoolean, "\\b(true|false)\\b");
|
||||
m_lexer.append(tokenJSCondition, "===|!==|==|>=|<=|!=|<|>|&&|\\|\\|");
|
||||
m_lexer.append(tokenJSAssignation, "(\\+=|-=|\\*=|/=|=|\\*|/|--|-|\\+\\+|\\+|&)");
|
||||
m_lexer.append(tokenJSString, "\\w+");
|
||||
m_lexer.append(tokenJSSeparator, "(;|,)");
|
||||
m_lexer.appendSection(tokenJSSectionBrace, tokenJSBraceIn, tokenJSBraceOut);
|
||||
m_lexer.appendSection(tokenJSSectionPthese, tokenJSPtheseIn, tokenJSPtheseOut);
|
||||
m_lexer.appendSection(tokenJSSectionHook, tokenJSHookIn, tokenJSHookOut);
|
||||
}
|
||||
|
||||
eci::ParserJS::~ParserJS() {
|
||||
|
||||
}
|
||||
|
||||
static void printNode(const std::string& _data, const std::vector<std::shared_ptr<eci::LexerNode>>& _nodes, int32_t _level=0) {
|
||||
std::string offset;
|
||||
for (int32_t iii=0; iii<_level; ++iii) {
|
||||
offset += " ";
|
||||
}
|
||||
for (auto &it : _nodes) {
|
||||
if (it->isNodeContainer() == true) {
|
||||
std::shared_ptr<eci::LexerNodeContainer> sec = std::dynamic_pointer_cast<eci::LexerNodeContainer>(it);
|
||||
if (sec != nullptr) {
|
||||
ECI_INFO(offset << " " << it->getStartPos() << "->" << it->getStopPos() << " (container)");
|
||||
printNode(_data, sec->m_list, _level+1);
|
||||
}
|
||||
} else {
|
||||
ECI_INFO(offset << it->getStartPos() << "->" << it->getStopPos() << " data='" <<std::string(_data, it->getStartPos(), it->getStopPos()-it->getStartPos()) << "'" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool eci::ParserJS::parse(const std::string& _data) {
|
||||
m_result = m_lexer.interprete(_data);
|
||||
|
||||
// TODO: Agregate type
|
||||
// TODO: Agregate Action
|
||||
// TODO: Agregate Function
|
||||
|
||||
ECI_INFO("find :");
|
||||
printNode(_data, m_result.m_list);
|
||||
/*
|
||||
for (auto &it : m_result.m_list) {
|
||||
ECI_INFO(" start=" << it->getStartPos() << " stop=" << it->getStopPos() << " data='" <<std::string(_data, it->getStartPos(), it->getStopPos()-it->getStartPos()) << "'" );
|
||||
}
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
53
eci/lang/ParserJS.h
Normal file
53
eci/lang/ParserJS.h
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @author Edouard DUPIN
|
||||
*
|
||||
* @copyright 2014, Edouard DUPIN, all right reserved
|
||||
*
|
||||
* @license APACHE-2 (see license file)
|
||||
*/
|
||||
|
||||
#ifndef __ECI_PARSER_JS_H__
|
||||
#define __ECI_PARSER_JS_H__
|
||||
|
||||
#include <eci/Lexer.h>
|
||||
|
||||
namespace eci {
|
||||
|
||||
enum jsTokenList {
|
||||
tokenJSCommentMultiline,
|
||||
tokenJSCommentSingleLine,
|
||||
|
||||
tokenJSStringDoubleQuote,
|
||||
tokenJSStringSimpleQuote,
|
||||
tokenJSBraceIn,
|
||||
tokenJSBraceOut,
|
||||
tokenJSPtheseIn,
|
||||
tokenJSPtheseOut,
|
||||
tokenJSHookIn,
|
||||
tokenJSHookOut,
|
||||
tokenJSSectionBrace,
|
||||
tokenJSSectionPthese,
|
||||
tokenJSSectionHook,
|
||||
tokenJSBranch,
|
||||
tokenJSSystem,
|
||||
tokenJSType,
|
||||
tokenJSContener,
|
||||
tokenJSNumericValue,
|
||||
tokenJSBoolean,
|
||||
tokenJSCondition,
|
||||
tokenJSAssignation,
|
||||
tokenJSString,
|
||||
tokenJSSeparator,
|
||||
};
|
||||
class ParserJS {
|
||||
public:
|
||||
eci::Lexer m_lexer;
|
||||
eci::LexerResult m_result;
|
||||
public:
|
||||
ParserJS();
|
||||
~ParserJS();
|
||||
bool parse(const std::string& _data);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -26,7 +26,8 @@ def create(target):
|
||||
'eci/Type.cpp',
|
||||
'eci/Variable.cpp',
|
||||
'eci/Value.cpp',
|
||||
'eci/lang/ParserCpp.cpp'
|
||||
'eci/lang/ParserCpp.cpp',
|
||||
'eci/lang/ParserJS.cpp'
|
||||
])
|
||||
myModule.add_export_path(tools.get_current_path(__file__))
|
||||
myModule.add_module_depend('etk')
|
||||
|
Loading…
x
Reference in New Issue
Block a user