352 lines
9.0 KiB
JavaScript
352 lines
9.0 KiB
JavaScript
let Hemex = require("@saqut/hemex");
|
||
const File = require("./File");
|
||
/**
|
||
* @param {File} file
|
||
*/
|
||
function ParseEngine(file)
|
||
{
|
||
let content = [];
|
||
let buffer = [];
|
||
let requiredImports = [];
|
||
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":{
|
||
requiredImports.push(value);
|
||
jsContent.push(`_external(${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 {
|
||
ast:useAST(content),
|
||
requiredImports
|
||
};
|
||
};
|
||
|
||
module.exports = ParseEngine; |