2022-10-25 01:00:01 +03:00
|
|
|
|
let Hemex = require("@saqut/hemex");
|
|
|
|
|
const File = require("./File");
|
|
|
|
|
/**
|
|
|
|
|
* @param {File} file
|
|
|
|
|
*/
|
|
|
|
|
function ParseEngine(file)
|
|
|
|
|
{
|
|
|
|
|
let content = [];
|
|
|
|
|
let buffer = [];
|
2022-10-25 01:10:27 +03:00
|
|
|
|
let requiredImports = [];
|
2022-10-25 01:00:01 +03:00
|
|
|
|
let hmx = new Hemex();
|
|
|
|
|
hmx.setText(file.content);
|
|
|
|
|
function flushBuffer()
|
|
|
|
|
{
|
|
|
|
|
if(buffer.length)
|
|
|
|
|
{
|
|
|
|
|
content.push({
|
|
|
|
|
type:'text',
|
|
|
|
|
value: buffer.join('')
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
buffer=[];
|
|
|
|
|
}
|
|
|
|
|
hmx.addLexer({
|
|
|
|
|
name: "scope"
|
|
|
|
|
},()=>{
|
|
|
|
|
hmx.while(()=>{
|
|
|
|
|
if(hmx.include('{{'))
|
|
|
|
|
{
|
|
|
|
|
let doubleBrackContent = hmx.gather('double-brack');
|
|
|
|
|
flushBuffer();
|
|
|
|
|
content.push({
|
|
|
|
|
type:'js-value',
|
|
|
|
|
value: doubleBrackContent
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
if(hmx.include('@{'))
|
|
|
|
|
{
|
|
|
|
|
let jsBlockContent = hmx.gather('js-block');
|
|
|
|
|
flushBuffer();
|
|
|
|
|
content.push({
|
|
|
|
|
type:'js-block',
|
|
|
|
|
value: jsBlockContent
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
if(hmx.include('@if('))
|
|
|
|
|
{
|
|
|
|
|
let jsStatement = hmx.gather('js-if-block');
|
|
|
|
|
flushBuffer();
|
|
|
|
|
content.push({
|
|
|
|
|
type:'js-if-block',
|
|
|
|
|
value: jsStatement
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
if(hmx.include('@endif', true))
|
|
|
|
|
{
|
|
|
|
|
flushBuffer();
|
|
|
|
|
content.push({
|
|
|
|
|
type:'js-end-block'
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
if(hmx.include('@for('))
|
|
|
|
|
{
|
|
|
|
|
let jsStatement = hmx.gather('js-for-block');
|
|
|
|
|
flushBuffer();
|
|
|
|
|
content.push({
|
|
|
|
|
type:'js-for-block',
|
|
|
|
|
value: jsStatement
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
if(hmx.include('@import(', true))
|
|
|
|
|
{
|
|
|
|
|
let importedThing = hmx.gather('import');
|
|
|
|
|
flushBuffer();
|
|
|
|
|
content.push({
|
|
|
|
|
type:'import',
|
|
|
|
|
value: importedThing
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
if(hmx.include('@endfor', true))
|
|
|
|
|
{
|
|
|
|
|
flushBuffer();
|
|
|
|
|
content.push({
|
|
|
|
|
type:'js-end-block'
|
|
|
|
|
});
|
|
|
|
|
return true;
|
|
|
|
|
};
|
|
|
|
|
buffer.push(hmx.getChar());
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
flushBuffer();
|
|
|
|
|
});
|
|
|
|
|
hmx.addLexer({
|
|
|
|
|
name: "js-block"
|
|
|
|
|
},() => {
|
|
|
|
|
hmx.beginPosition();
|
|
|
|
|
if(hmx.include('@{'))
|
|
|
|
|
{
|
|
|
|
|
hmx.toChar(+2);
|
|
|
|
|
};
|
|
|
|
|
let script = hmx.gather('readjscontent','}');
|
|
|
|
|
if(hmx.include('}'))
|
|
|
|
|
{
|
|
|
|
|
hmx.toChar(+1);
|
|
|
|
|
};
|
|
|
|
|
hmx.acceptPosition();
|
|
|
|
|
return script;
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
hmx.addLexer({
|
|
|
|
|
name: "double-brack"
|
|
|
|
|
},()=>{
|
|
|
|
|
hmx.beginPosition();
|
|
|
|
|
if(hmx.include('{{'))
|
|
|
|
|
{
|
|
|
|
|
hmx.toChar(+2);
|
|
|
|
|
};
|
|
|
|
|
let jsContent = hmx.gather('readjscontent', '}}');
|
|
|
|
|
if(hmx.include('}}'))
|
|
|
|
|
{
|
|
|
|
|
hmx.toChar(+2);
|
|
|
|
|
};
|
|
|
|
|
hmx.acceptPosition();
|
|
|
|
|
return jsContent;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
hmx.addLexer({
|
|
|
|
|
name: "import"
|
|
|
|
|
},()=>{
|
|
|
|
|
hmx.beginPosition();
|
|
|
|
|
if(hmx.include('@import('))
|
|
|
|
|
{
|
|
|
|
|
hmx.toChar(+8);
|
|
|
|
|
};
|
|
|
|
|
let jsContent = hmx.gather('readjscontent',')');
|
|
|
|
|
if(hmx.include(')'))
|
|
|
|
|
{
|
|
|
|
|
hmx.toChar(+1);
|
|
|
|
|
};
|
|
|
|
|
hmx.acceptPosition();
|
|
|
|
|
return jsContent;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
hmx.addLexer({
|
|
|
|
|
name: "js-if-block"
|
|
|
|
|
},()=>{
|
|
|
|
|
hmx.beginPosition();
|
|
|
|
|
if(hmx.include('@if('))
|
|
|
|
|
{
|
|
|
|
|
hmx.toChar(+4);
|
|
|
|
|
};
|
|
|
|
|
let jsContent = hmx.gather('readjscontent', ')');
|
|
|
|
|
if(hmx.include(')'))
|
|
|
|
|
{
|
|
|
|
|
hmx.toChar(+2);
|
|
|
|
|
};
|
|
|
|
|
hmx.acceptPosition();
|
|
|
|
|
return jsContent;
|
|
|
|
|
});
|
|
|
|
|
hmx.addLexer({
|
|
|
|
|
name: "js-for-block"
|
|
|
|
|
},()=>{
|
|
|
|
|
hmx.beginPosition();
|
|
|
|
|
if(hmx.include('@for('))
|
|
|
|
|
{
|
|
|
|
|
hmx.toChar(+5);
|
|
|
|
|
};
|
|
|
|
|
let jsContent = hmx.gather('readjscontent', ')');
|
|
|
|
|
if(hmx.include(')'))
|
|
|
|
|
{
|
|
|
|
|
hmx.toChar(+1);
|
|
|
|
|
};
|
|
|
|
|
hmx.acceptPosition();
|
|
|
|
|
return jsContent;
|
|
|
|
|
});
|
|
|
|
|
hmx.addLexer({
|
|
|
|
|
name: "readjscontent"
|
|
|
|
|
},(hmx, content)=>{
|
|
|
|
|
hmx.beginPosition();
|
|
|
|
|
let scopeLevel = 0;
|
|
|
|
|
hmx.while(()=>{
|
|
|
|
|
if(scopeLevel == 0)
|
|
|
|
|
{
|
|
|
|
|
if(content == null)
|
|
|
|
|
{
|
|
|
|
|
if(hmx.isWhiteSpace())
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}else if(hmx.include(content))
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
switch(hmx.getChar())
|
|
|
|
|
{
|
|
|
|
|
case '{':{
|
|
|
|
|
scopeLevel++;
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
case '(':{
|
|
|
|
|
scopeLevel++;
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
case '}':{
|
|
|
|
|
scopeLevel = Math.max(scopeLevel - 1, 0);
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
case ')':{
|
|
|
|
|
scopeLevel = Math.max(scopeLevel - 1, 0);
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
case '/':{
|
|
|
|
|
if(hmx.include('//'))
|
|
|
|
|
throw new Error("Çift parantezlerde yorum satırı kullanılamaz")
|
|
|
|
|
else hmx.gather('skip-regex-content');
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
case '\'':
|
|
|
|
|
case '"':
|
|
|
|
|
case '`':{
|
|
|
|
|
hmx.gather('skip-string-content',hmx.getChar());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
default:{
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
let jscontent = hmx.getPositionRange();
|
|
|
|
|
hmx.acceptPosition();
|
|
|
|
|
return jscontent;
|
|
|
|
|
});
|
|
|
|
|
hmx.addLexer({
|
|
|
|
|
name: "skip-string-content"
|
|
|
|
|
},(hmx, char)=>{
|
|
|
|
|
hmx.beginPosition();
|
|
|
|
|
if(hmx.isChar(char))
|
|
|
|
|
{
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
}
|
|
|
|
|
hmx.while(()=>{
|
|
|
|
|
switch(hmx.getChar())
|
|
|
|
|
{
|
|
|
|
|
case '\\':{
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
case char:{
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
default:{
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
hmx.acceptPosition();
|
|
|
|
|
});
|
|
|
|
|
hmx.addLexer({
|
|
|
|
|
name: "skip-regex-content"
|
|
|
|
|
},()=>{
|
|
|
|
|
hmx.beginPosition();
|
|
|
|
|
if(hmx.isChar('/'))
|
|
|
|
|
{
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
};
|
|
|
|
|
hmx.while(()=>{
|
|
|
|
|
switch(hmx.getChar())
|
|
|
|
|
{
|
|
|
|
|
case '\\':{
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
case '/':{
|
|
|
|
|
hmx.nextChar();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
default:{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
hmx.acceptPosition();
|
|
|
|
|
});
|
|
|
|
|
hmx.gather('scope');
|
|
|
|
|
function useAST(content)
|
|
|
|
|
{
|
|
|
|
|
let jsContent = [];
|
|
|
|
|
for (const {
|
|
|
|
|
type,
|
|
|
|
|
value
|
|
|
|
|
} of content) switch(type)
|
|
|
|
|
{
|
|
|
|
|
case "js-value":{
|
|
|
|
|
jsContent.push(`output.push(${value});\n`);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "js-block":{
|
|
|
|
|
jsContent.push(`\n${value}\n`);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "text":{
|
|
|
|
|
jsContent.push(`output.push(${JSON.stringify(value)});\n`);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "import":{
|
2022-10-25 01:10:27 +03:00
|
|
|
|
requiredImports.push(value);
|
|
|
|
|
jsContent.push(`_external(${value});\n`);
|
2022-10-25 01:00:01 +03:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "js-if-block":{
|
|
|
|
|
jsContent.push(`if(${value}){\n`);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "js-for-block":{
|
|
|
|
|
jsContent.push(`for(${value}){\n`);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "js-endif-block":{
|
|
|
|
|
jsContent.push(`if(${value}){\n`);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case "js-end-block":{
|
|
|
|
|
jsContent.push(`\n};\n`);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return jsContent.join('');
|
|
|
|
|
}
|
2022-10-25 01:10:27 +03:00
|
|
|
|
return {
|
|
|
|
|
ast:useAST(content),
|
|
|
|
|
requiredImports
|
|
|
|
|
};
|
2022-10-25 01:00:01 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
module.exports = ParseEngine;
|