UNPKG

byond-parser

Version:
132 lines (130 loc) 3.73 kB
'use strict'; module.exports = function pre_parse(text, file) { text = text.replace(/\r\n/g, '\n'); // LF line endings only you sick fucks text = text.replace(/\r/g, '\n'); if(!text) return []; if(!text.endsWith("\n")) text += "\n"; let syntax_stack = []; let lines = []; let line = {text: ""}; let indent_level = 0; let has_nonwhitespace = false; let linenum = 1; let colnum = 0; for(let i = 0; i < text.length; i++) { colnum++; let pc = text[i-1]; let c = text[i]; let nc = text[i+1]; let curr_syntax = syntax_stack[syntax_stack.length-1]; let instring = (curr_syntax == '""' || curr_syntax == '{""}' || (curr_syntax && curr_syntax[0] == '@')); let incomment = (curr_syntax == '//' || curr_syntax == '/**/'); if(curr_syntax && curr_syntax[0] == '@') { if(curr_syntax[1] != '(' && curr_syntax[1] == c) { line.text += '"'; syntax_stack.pop(); } else if(c == '\\' || c == '[' || c == '"') { line.text += '\\' + c; } else { line.text += c; } continue; } if(c == '\\' && nc != '\n' && instring) { line.text += c; line.text += nc; i++; continue; } else if(c == '\n' || (c == '\\' && nc == '\n')) { linenum++; colnum = 0; indent_level = 0; has_nonwhitespace = false; if(incomment) { if(curr_syntax == '//') syntax_stack.pop(); } line.text = line.text.trimRight(); if(!incomment && c == '\\') { line.text += " "; i++; } else if(!syntax_stack.length) { lines.push(line); line = {text: ""}; } else if(curr_syntax == '{""}') { line.text += "\\n"; } else { if(syntax_stack.includes('""') || (curr_syntax && curr_syntax[0] == '@')) { if(pc != '\n') throw new Error(`${file}:${linenum}:${colnum} - Line break inside string`); } else { line.text += " "; } } continue; } else if(incomment) { if(c == '*' && nc == '/' && curr_syntax == '/**/') { syntax_stack.pop(); i++; } continue; } else if(!instring && !incomment && c == '/' && nc == '/') { syntax_stack.push('//'); i++; continue; } else if(!instring && !incomment && c == '/' && nc == '*') { syntax_stack.push('/**/'); i++; continue; } else if(c == '[') syntax_stack.push('[]'); else if(curr_syntax == '[]' && c == ']') syntax_stack.pop(); else if(!instring && c == '"') syntax_stack.push('""'); else if(curr_syntax == '""' && c == '"') syntax_stack.pop(); else if(!instring && c == '(') syntax_stack.push('()'); else if(curr_syntax == '()' && c == ')') syntax_stack.pop(); else if(c == '{' && nc == '"' && !instring) { syntax_stack.push('{""}'); i++; line.text += '"'; continue; } else if(c == '"' && nc == '}' && curr_syntax == '{""}') { syntax_stack.pop(); i++; line.text += '"'; continue; } else if(c == '"' && curr_syntax == '{""}') { line.text += '\\"'; continue; } else if(!instring && !incomment && c == '@' && nc != '(') { syntax_stack.push('@' + nc); i++; line.text += '"'; continue; } if((c != ' ' && c != '\t') || has_nonwhitespace) line.text += c; if(c != ' ' && c != '\t' && !has_nonwhitespace) { has_nonwhitespace = true; if(line.indent_level == null) { line.line = linenum; line.col = colnum; line.file = file; line.indent_level = indent_level; } } else if(!has_nonwhitespace) { indent_level++; } } lines.push(line); if(syntax_stack.length) { throw new Error(`Syntax stack not empty in file ${file}! ${JSON.stringify(syntax_stack)}. Remaining text in buffer: "${line.text}"`); } return lines; };