347 lines
8.9 KiB
JavaScript
347 lines
8.9 KiB
JavaScript
|
let Hemex = require("@saqut/hemex");
|
|||
|
const File = require("./File");
|
|||
|
/**
|
|||
|
* @param {File} file
|
|||
|
*/
|
|||
|
function ParseEngine(file)
|
|||
|
{
|
|||
|
let content = [];
|
|||
|
let buffer = [];
|
|||
|
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":{
|
|||
|
jsContent.push(`output.push(${JSON.stringify(`<!-- imported ${value}--->`)});\n`);
|
|||
|
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('');
|
|||
|
}
|
|||
|
return useAST(content);
|
|||
|
};
|
|||
|
|
|||
|
module.exports = ParseEngine;
|