How to replace "" to " by using JSON.Parser from scratch - javascript

I read an article about JSON.Parser from scratch by Tan Li Hau.
https://lihautan.com/json-parser-with-javascript/
And I want to custom his JSON.Parser which can replace "" to " or """ to ". I mean if " keep more than 1 continuously, replace to " .
ex)
'{"n": ""aaa, should, ""}'
to
'{"n": "aaa, should, "}'
But for now, there is a syntax error of course.
I found the parseString() loops while " comes next. So I tried to update parseString() to replace "" to " if it's continuously. But it's not working. Also It's not supported more than 1 ".
So if you could give me some advise, it would be helpful.
function fakeParseJSON(str) {
let i = 0;
const value = parseValue();
expectEndOfInput();
return value;
function parseObject() {
if (str[i] === "{") {
i++;
skipWhitespace();
const result = {};
let initial = true;
// if it is not '}',
// we take the path of string -> whitespace -> ':' -> value -> ...
while (i < str.length && str[i] !== "}") {
if (!initial) {
eatComma();
skipWhitespace();
}
const key = parseString();
if (key === undefined) {
expectObjectKey();
}
skipWhitespace();
eatColon();
const value = parseValue();
result[key] = value;
initial = false;
}
expectNotEndOfInput("}");
// move to the next character of '}'
i++;
return result;
}
}
function parseArray() {
if (str[i] === "[") {
i++;
skipWhitespace();
const result = [];
let initial = true;
while (i < str.length && str[i] !== "]") {
if (!initial) {
eatComma();
}
const value = parseValue();
result.push(value);
initial = false;
}
expectNotEndOfInput("]");
// move to the next character of ']'
i++;
return result;
}
}
function parseValue() {
skipWhitespace();
const value =
parseString() ??
parseNumber() ??
parseObject() ??
parseArray() ??
parseKeyword("true", true) ??
parseKeyword("false", false) ??
parseKeyword("null", null);
skipWhitespace();
return value;
}
function parseKeyword(name, value) {
if (str.slice(i, i + name.length) === name) {
i += name.length;
return value;
}
}
function skipWhitespace() {
while (
str[i] === " " ||
str[i] === "\n" ||
str[i] === "\t" ||
str[i] === "\r"
) {
i++;
}
}
function parseString() {
if (str[i] === '"') {
i++;
let result = "";
if (str[i - 1] + str[i] === '""') {
(str[i - 1] + str[i]).replace('""', '"');
}
while (i < str.length && str[i] !== '"') {
if (str[i] === "\\") {
const char = str[i + 1];
if (
char === '"' ||
char === "\\" ||
char === "/" ||
char === "b" ||
char === "f" ||
char === "n" ||
char === "r" ||
char === "t"
) {
result += char;
i++;
} else if (char === "u") {
if (
isHexadecimal(str[i + 2]) &&
isHexadecimal(str[i + 3]) &&
isHexadecimal(str[i + 4]) &&
isHexadecimal(str[i + 5])
) {
result += String.fromCharCode(
parseInt(str.slice(i + 2, i + 6), 16)
);
i += 5;
} else {
i += 2;
expectEscapeUnicode(result);
}
} else {
expectEscapeCharacter(result);
}
} else {
result += str[i];
}
i++;
}
expectNotEndOfInput('"');
i++;
return result;
}
}
function isHexadecimal(char) {
return (
(char >= "0" && char <= "9") ||
(char.toLowerCase() >= "a" && char.toLowerCase() <= "f")
);
}
function parseNumber() {
let start = i;
if (str[i] === "-") {
i++;
expectDigit(str.slice(start, i));
}
if (str[i] === "0") {
i++;
} else if (str[i] >= "1" && str[i] <= "9") {
i++;
while (str[i] >= "0" && str[i] <= "9") {
i++;
}
}
if (str[i] === ".") {
i++;
expectDigit(str.slice(start, i));
while (str[i] >= "0" && str[i] <= "9") {
i++;
}
}
if (str[i] === "e" || str[i] === "E") {
i++;
if (str[i] === "-" || str[i] === "+") {
i++;
}
expectDigit(str.slice(start, i));
while (str[i] >= "0" && str[i] <= "9") {
i++;
}
}
if (i > start) {
return Number(str.slice(start, i));
}
}
function eatComma() {
expectCharacter(",");
i++;
}
function eatColon() {
expectCharacter(":");
i++;
}
// error handling
function expectNotEndOfInput(expected) {
if (i === str.length) {
printCodeSnippet(`Expecting a \`${expected}\` here`);
throw new Error("JSON_ERROR_0001 Unexpected End of Input");
}
}
function expectEndOfInput() {
if (i < str.length) {
printCodeSnippet("Expecting to end here");
throw new Error("JSON_ERROR_0002 Expected End of Input");
}
}
function expectObjectKey() {
printCodeSnippet(`Expecting object key here
For example:
{ "foo": "bar" }
^^^^^`);
throw new Error("JSON_ERROR_0003 Expecting JSON Key");
}
function expectCharacter(expected) {
if (str[i] !== expected) {
printCodeSnippet(`Expecting a \`${expected}\` here`);
throw new Error("JSON_ERROR_0004 Unexpected token");
}
}
function expectDigit(numSoFar) {
if (!(str[i] >= "0" && str[i] <= "9")) {
printCodeSnippet(`JSON_ERROR_0005 Expecting a digit here
For example:
${numSoFar}5
${" ".repeat(numSoFar.length)}^`);
throw new Error("JSON_ERROR_0006 Expecting a digit");
}
}
function expectEscapeCharacter(strSoFar) {
printCodeSnippet(`JSON_ERROR_0007 Expecting escape character
For example:
"${strSoFar}\\n"
${" ".repeat(strSoFar.length + 1)}^^
List of escape characters are: \\", \\\\, \\/, \\b, \\f, \\n, \\r, \\t, \\u`);
throw new Error("JSON_ERROR_0008 Expecting an escape character");
}
function expectEscapeUnicode(strSoFar) {
printCodeSnippet(`Expect escape unicode
For example:
"${strSoFar}\\u0123
${" ".repeat(strSoFar.length + 1)}^^^^^^`);
throw new Error("JSON_ERROR_0009 Expecting an escape unicode");
}
function printCodeSnippet(message) {
const from = Math.max(0, i - 10);
const trimmed = from > 0;
const padding = (trimmed ? 4 : 0) + (i - from);
const snippet = [
(trimmed ? "... " : "") + str.slice(from, i + 1),
" ".repeat(padding) + "^",
" ".repeat(padding) + message
].join("\n");
console.log(snippet);
}
}
console.log(`${fakeParseJSON('{"n": ""string, should, ""}')}`);
https://codesandbox.io/embed/json-parser-with-error-handling-forked-9zetnc?fontsize=14&hidenavigation=1&theme=dark

Related

How to return return boolean false if strings has empty spaces

How to check for blank space in javascript.
My code:
function checkSubstring(text, part) {
for (let i = 0; i <= text.length; i++) {
if (text.toLowerCase().indexOf(part.toLowerCase()) !== -1 || part.toLowerCase().indexOf(text.toLowerCase()) !== -1){
return true;
}
else if (text === ' ' || part === ' ') {
return false
}
}
return false
}
console.log(checkSubstring(' ', ' '));
I tried check if white space using indexOf(' '), check if strings === 0 but it always return true.
Change your function as below
function checkSubstring(text, part) {
for (let i = 0; i <= text.length; i++) {
if (text.trim().length === 0 || part.trim().length === 0) {
return false
}
if (text.toLowerCase().indexOf(part.toLowerCase()) !== -1 || part.toLowerCase().indexOf(text.toLowerCase()) !== -1){
return true;
}
}
return false
}

Recursive Palindrom does not returning neither true nor false only undefined

I've tried to write a recursive palindrom however, eventhough I reach at the end the true branch at the last iteration the return value is still undefined.
So if you type in the console my function with a palindrom.
rekurzivSzigoruPalindrom("radar");
It will iterate through it perfectly but the return value, will be undefined.
Could you please point out the error in my code below ?
Thanks
function rekurzivSzigoruPalindrom(str, strLength = str.length) {
// debug eleje
console.log(strLength);
if (strLength > 1) {
console.log(str[str.length - strLength] + " " +str[strLength-1] );
}
if(strLength == 1){
console.log(str[str.length-1]+ " " +str[strLength-1]);
}
//debug vége
if(typeof str == "string" || typeof str == "number"){
if(typeof str == "number"){
str = str.toString();
}
if(strLength > 1){
if(str[str.length - strLength] == str[strLength-1]){
//console.log(strLength);
strLength--;
rekurzivSzigoruPalindrom(str,strLength);
}
}
else if(strLength == 1){
if(str[str.length-1] == str[strLength-1]){
console.log(strLength+"true");
return true;
}
else{
console.log(strLength+"false");
return false;
}
}
}
else {
return false;
}
}
you have to return the result of your recursive call.
function rekurzivSzigoruPalindrom(str, strLength = str.length) {
// debug eleje
console.log(strLength);
if (strLength > 1) {
console.log(str[str.length - strLength] + " " +str[strLength-1] );
}
if(strLength == 1){
console.log(str[str.length-1]+ " " +str[strLength-1]);
}
//debug vége
if(typeof str == "string" || typeof str == "number"){
if(typeof str == "number"){
str = str.toString();
}
if(strLength > 1){
if(str[str.length - strLength] == str[strLength-1]){
//console.log(strLength);
strLength--;
return rekurzivSzigoruPalindrom(str,strLength);
}
}
else if(strLength == 1){
if(str[str.length-1] == str[strLength-1]){
console.log(strLength+"true");
return true;
}
else{
console.log(strLength+"false");
return false;
}
}
}
else {
return false;
}
}
Recursive:
function recPal(str) {
str=""+str; // for numbers
if(str.length<2) return true;
if(str[0]!=str[str.length-1]) return false;
return recPal(str.slice(1,-1));
};
var strs=[101, 75, "", "x", "xy", "99", "abba", "log", "racecar", "razor", "radar"];
strs.forEach(
word=>
console.log(
"'"+word+"'"+
(recPal(word)?" IS ":" is NOT ")+
"a palindrome"
)
);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Variable only works locally

I wrote some functions involving prime factorization and I noticed that when I identified my test paragraph (for testing the results of functions and such) as document.getElementById("text"), it worked fine. However, when I declared a global variable text as var text = document.getElementById("text"), and then substituted in text for the longer version, it no longer worked. I did, however, notice that it worked when I locally declared text. Why is this and how can I fix it? My JSFiddle is here: https://jsfiddle.net/MCBlastoise/3ehcz214/
And this is my code:
var text = document.getElementById("text");
function isPrime(num) {
var lastDigit = parseInt((num + "").split("").reverse()[0]);
if (typeof num !== "number" || num <= 1 || num % 1 !== 0) {
return undefined;
}
else if (num === 2) {
return true;
}
else if (lastDigit === 0 || lastDigit === 2 || lastDigit === 4 || lastDigit === 5 || lastDigit === 6 || lastDigit === 8) {
return false;
}
else {
for (var i = 2; i < num; i++) {
if (num % i === 0) {
return false;
}
}
return true;
}
}
function factorSplit(dig) {
if (typeof dig !== "number" || dig <= 1 || dig % 1 !== 0) {
return undefined;
}
else if (dig === 2) {
return undefined;
}
else {
var factor;
for (var i = 2; i < dig; i++) {
if (dig % i === 0) {
factor = i;
break;
}
}
if (factor === undefined) {
return undefined;
}
else {
return [factor, (dig / factor)];
}
}
}
function allPrimes(arr) {
if (Array.isArray(arr) === false || arr.length < 1) {
return undefined;
}
else {
for (var i = 0; i < arr.length; i++) {
if (isPrime(arr[i]) !== true) {
return false;
}
}
return true;
}
}
function primeFactors(int) {
if (typeof int !== "number" || int <= 1) {
return undefined;
}
else if (isPrime(int) === true) {
return false;
}
else {
var initFactors = factorSplit(int);
while (allPrimes(initFactors) !== true) {
initFactors = initFactors.concat(factorSplit(initFactors[initFactors.length - 1]));
initFactors.splice((initFactors.length - 3), 1);
}
return initFactors;
}
}
function listPrimes() {
repeat = setInterval(findPrime, 1);
}
var primeInts = [2];
var check;
function findPrime() {
var i = primeInts[primeInts.length - 1] + 1;
if (check === undefined) {
check = true;
text.innerHTML = primeInts[0];
}
else {
while (isPrime(i) !== true) {
i++;
}
primeInts.push(i);
text.innerHTML += ", " + primeInts[primeInts.length - 1];
}
}
//text.innerHTML = isPrime(6);
<div onclick="listPrimes()" style="cursor:pointer; background-color:black; width:30px; height:30px"></div>
<p id="text"></p>
The text is global, you just need to make sure the whole script file is included in the html. Here's an example of what I mean
Here in code snippets stackoverflow does this for us already.
var text = document.getElementById("text");
function isPrime(num) {
var lastDigit = parseInt((num + "").split("").reverse()[0]);
if (typeof num !== "number" || num <= 1 || num % 1 !== 0) {
return undefined;
} else if (num === 2) {
return true;
} else if (lastDigit === 0 || lastDigit === 2 || lastDigit === 4 || lastDigit === 5 || lastDigit === 6 || lastDigit === 8) {
return false;
} else {
for (var i = 2; i < num; i++) {
if (num % i === 0) {
return false;
}
}
return true;
}
}
function factorSplit(dig) {
if (typeof dig !== "number" || dig <= 1 || dig % 1 !== 0) {
return undefined;
} else if (dig === 2) {
return undefined;
} else {
var factor;
for (var i = 2; i < dig; i++) {
if (dig % i === 0) {
factor = i;
break;
}
}
if (factor === undefined) {
return undefined;
} else {
return [factor, (dig / factor)];
}
}
}
function allPrimes(arr) {
if (Array.isArray(arr) === false || arr.length < 1) {
return undefined;
} else {
for (var i = 0; i < arr.length; i++) {
if (isPrime(arr[i]) !== true) {
return false;
}
}
return true;
}
}
function primeFactors(int) {
if (typeof int !== "number" || int <= 1) {
return undefined;
} else if (isPrime(int) === true) {
return false;
} else {
var initFactors = factorSplit(int);
while (allPrimes(initFactors) !== true) {
initFactors = initFactors.concat(factorSplit(initFactors[initFactors.length - 1]));
initFactors.splice((initFactors.length - 3), 1);
}
return initFactors;
}
}
function listPrimes() {
repeat = setInterval(findPrime, 1);
}
var primeInts = [2];
var check;
function findPrime() {
var i = primeInts[primeInts.length - 1] + 1;
if (check === undefined) {
check = true;
text.innerHTML = primeInts[0];
} else {
while (isPrime(i) !== true) {
i++;
}
primeInts.push(i);
text.innerHTML += ", " + primeInts[primeInts.length - 1];
}
}
function test() {
console.log("inside test1")
console.log(text);
text.innerHTML = "testtt"
}
function test2() {
console.log("inside test2")
console.log(text);
text.innerHTML = "testtt2"
}
text.innerHTML = isPrime(6);
<div onclick="test()" style="cursor:pointer; background-color:black; width:30px; height:30px"></div>
<p id="text"></p>
<div onclick="test2()" style="cursor:pointer; background-color:black; width:30px; height:30px"></div>
In the head the script runs/loads first and because you don't have the var's in a function they are never re-used they remain with the original value which is null since the document didn't exist at that time, then when the page loads all it has is access to the functions a call to the global var is null. This is why the code previously only worked when text = document.getElementById('text') was in a function.

Except link with Javascript

can you help me?
I'm trying to get this code below to make a excesão links in case the variable would be
var except_link = "blogspot.com, wordpress.com";
But it is only making excesão of 'blogspot.com'
thank you
var except_link = "blogspot.com, wordpress.com";
var allow_file = ".3gp,.7z,.aac,.ac3,.asf,.asx,.avi,.bzip,.divx,.doc,.exe,.flv,.jpg,.png,.gz,.gzip,.iso,.jar,.jav,.mid,.mkv,.mov,.mp3,.mp4,.mpeg,.mpg,.msi,.nrg,.ogg,.pdf,.ppt,.psd,.rar,.rm,.rmvb,.rtf,.swf,.tar,.tar.gz,.tgz,.torrent,.ttf,.txt,.wav,.wma,.wmv,.xls,.zip,180upload,1fichier,1filesharing,2shared,4files,4share,4shared,a2zupload,adf,adrive,adv,amazo,";
except_link = (link_except != null) ? link_except : except_link;
function check(siteurl) {
if ("" + allow_file != "undefined" && allow_file != "" && allow_file.replace(/\s/g, "") != "" && siteurl != "") {
if ((" " + allow_file).indexOf(",") > 0) {
pular = allow_file.split(",")
} else {
pular = new Array(allow_file)
}
for (s = 0; s < pular.length; s++) {
if ((" " + siteurl.toLowerCase()).indexOf(pular[s].toLowerCase()) > 0) {
if ("" + except_link != "undefined" && except_link != "" && except_link.replace(/\s/g, "") != "" && siteurl != "") {
if ((" " + except_link).indexOf(",") > 0) {
pular = except_link.split(",")
} else {
pular = new Array(except_link)
}
for (s = 0; s < pular.length; s++) {
if ((" " + siteurl.toLowerCase()).indexOf(pular[s].toLowerCase()) > 0) {
return false;
break
}
}
return true
} else {
return true
}
}
}
return false
} else {
return false
}
}
You're splitting based on "," where you are delimiting with ", " (comma followed by space). The problem could be that it doesn't match since the second URL in the split array will be " wordpress.com" (wordpress.com with a space in front of it).
To remedy this, you could either change your split function to split accordingly:
except_link = "blogspot.com, wordpress.com" // comma-space
...
except_link.split(", ") // comma-space
Or, change your input string to accommodate your split requirements:
except_link = "blogspot.com,wordpress.com" // comma, no space
...
except_link.split(",") // comma, no space

What is the simplest way break text into single strings to be modified and joined again using JS?

For example, I am am working on a Pig Latin translator. I want a for loop to change the text to an array and allow the rest of my code to change single words and put it back together again as a result.
var pigLatinTranslator = function(firstWord) {
firstWord = firstWord.toLowerCase();
var splitText = firstWord.split(' ');
var finalResult = [];
for (var i = 0; i < splitText.length; i++) {
var singleWord = splitText[i];
if (singleWord.charAt(0) !== "a" && singleWord.charAt(0) !== "e" && singleWord.charAt(0) !== "i" && singleWord.charAt(0) !== "o" && singleWord.charAt(0) !== "u") {
var consonantsVar;
for (var i = 0; i < singleWord.length; i++) {
var chr = singleWord.charAt(i);
if ((chr === 'q') && (singleWord.charAt(i + 1) === 'u')) {
consonantsVar = (singleWord.slice(i + 2) + singleWord.slice(0, i) + "quay");
break;
} else if (chr === 'a' || chr === 'e' || chr === 'i' || chr === 'o' || chr === 'u') {
consonantsVar = (singleWord.slice(i) + singleWord.slice(0, i) + "ay");
break;
}
}
return consonantsVar;
}
else {
return (singleWord + "ay");
}
return splitText.join(' ');
}
};

Categories

Resources