This repository has been archived on 2024-02-17. You can view files and clone it, but cannot push or open issues or pull requests.
nodejs-razor/Processor/Parse.js

347 lines
8.9 KiB
JavaScript
Raw Normal View History

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 = [];
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;