diff --git a/dev/index.php b/dev/index.php index 6ac56e2..f775650 100644 --- a/dev/index.php +++ b/dev/index.php @@ -112,15 +112,20 @@ // parse source code /**/const parse_start = performance.now(); - juicescript.parse(juice_program); + let parse_success = juicescript.parse(juice_program); /**/const parse_end = performance.now(); /**/juicescript.io.stderr.info("Parsing took " + (parse_end - parse_start) + "ms"); // execute program - /**/const run_start = performance.now(); - juicescript.run(); - /**/const run_end = performance.now(); - /**/juicescript.io.stderr.info("Running took " + (run_end - run_start) + "ms"); + if(parse_success){ + /**/const run_start = performance.now(); + juicescript.run(); + /**/const run_end = performance.now(); + /**/juicescript.io.stderr.info("Running took " + (run_end - run_start) + "ms"); + + } else { + juicescript.io.stderr.info("Not executing program due to parse error"); + } }); diff --git a/src/lexer.js b/src/lexer.js index 4455aea..785e3ed 100644 --- a/src/lexer.js +++ b/src/lexer.js @@ -25,6 +25,10 @@ class Juicescript_lexer { // token list this.token_list = []; + // warning and error counter + this.warning_count = 0; + this.error_count = 0; + // SCAN WHOLE SOURCE // while(!this.is_at_end()){ @@ -84,7 +88,7 @@ class Juicescript_lexer { case "=": if (this.match("=")) this.token_add({type: Juicescript.token_type.EQUAL}); - else this.warning("unexpected character '" + char + "'"); + else this.error("unexpected character '" + char + "'"); break; case "<": @@ -127,7 +131,7 @@ class Juicescript_lexer { // single slash if(char === "/" && !this.match("/")){ - this.warning("unexpected character '" + char + "'"); + this.error("unexpected character '" + char + "'"); break; } @@ -172,8 +176,8 @@ class Juicescript_lexer { break; } - // ignore with warning - this.warning("unexpected character '" + char + "'"); + // ignore with error + this.error("unexpected character '" + char + "'"); break; @@ -186,8 +190,8 @@ class Juicescript_lexer { break; } - // ignore with warning - this.warning("unexpected character '" + char + "'"); + // ignore with error + this.error("unexpected character '" + char + "'"); break; @@ -205,8 +209,8 @@ class Juicescript_lexer { break; } - // unexpected - this.warning("unexpected character '" + char + "'"); + // unexpected (ignore with error) + this.error("unexpected character '" + char + "'"); break; } } @@ -239,8 +243,8 @@ class Juicescript_lexer { // DID WE REACH THE END OF SOURCE WITHOUT TERMINATION? // if(this.is_at_end()){ - // ignore with warning - this.warning("unterminated string"); + // ignore with error + this.error("unterminated string"); return; } @@ -334,8 +338,8 @@ class Juicescript_lexer { // DID WE REACH THE END OF SOURCE WITHOUT TERMINATION? // if(this.is_at_end()){ - // ignore with warning - this.warning("unterminated block comment"); + // ignore with error + this.error("unterminated block comment"); return; } @@ -364,8 +368,8 @@ class Juicescript_lexer { return; } - // ignore with warning - this.warning("unexpected character '" + this.source.charAt(this.start) + "'"); + // ignore with error + this.error("unexpected character '" + this.source.charAt(this.start) + "'"); return; } @@ -539,8 +543,8 @@ class Juicescript_lexer { // CHECK IF THERE EVEN IS A NAME // if(flag.length <= 0){ - // ignore with warning - this.warning("unexpected character '" + this.source.charAt(this.start) + "'"); + // ignore with error + this.error("unexpected character '" + this.source.charAt(this.start) + "'"); return; } @@ -679,6 +683,11 @@ class Juicescript_lexer { this.io.stderr.info(text, additional); } warning(text, additional){ + // KEEP TRACK OF PROBLEM // + this.warning_count++; + + + // PRINT MESSAGE // // add defaults additional ??= {}; additional.line ??= this.line; @@ -686,12 +695,17 @@ class Juicescript_lexer { // forward this.io.stderr.warning(text, additional); } - debug(text, additional){ + error(text, additional){ + // KEEP TRACK OF PROBLEM // + this.error_count++; + + + // PRINT MESSAGE // // add defaults additional ??= {}; additional.line ??= this.line; // forward - this.io.stderr.debug(text, additional); + this.io.stderr.error(text, additional); } } diff --git a/src/main.js b/src/main.js index 3c928c2..6bdc7dc 100644 --- a/src/main.js +++ b/src/main.js @@ -61,6 +61,10 @@ class Juicescript { Parse given PROGRAM-STRING and store syntax tree */ parse(program_string){ + // CLEAR OLD PROGRAM TREE // + this.program_tree = null; + + // DO SCANNING // // get lexer let lexer = new Juicescript_lexer(program_string, { @@ -69,10 +73,29 @@ class Juicescript { // run lexical analysis let token_list = lexer.scan(); - /**/for(let one_token of token_list){ - /**/one_token.type = Juicescript.token_type.name(one_token.type); - /**/console.log(one_token); - /**/} + + // stop here if unsuccessful + if(lexer.error_count > 0) return false; + + + // GET PROGRAM TREE FROM TOKENS // + // get parser + let parser = new Juicescript_parser(token_list, { + io: this.io + }); + + // do parsing + let program_tree = parser.parse(); + + // store program tree + this.program_tree = program_tree; + + // stop here if unsuccessful + if(parser.error_count > 0) return false; + + + // RETURN SUCCESS // + return true; } /* diff --git a/src/parser.js b/src/parser.js new file mode 100644 index 0000000..ae03cad --- /dev/null +++ b/src/parser.js @@ -0,0 +1,23 @@ +class Juicescript_parser { + /* + CONSTRUCTOR: Return new juicescript lexer for SOURCE with OPTIONS + */ + constructor(token_list, options){ + // STORE ARGUMENTS // + // list of tokens + this.token_list = token_list; + + // io adapter + this.io = options.io; + } + + /* + MAIN: Do parsing + */ + parse(){ + /**/for(let one_token of this.token_list){ + /**/one_token.type = Juicescript.token_type.name(one_token.type); + /**/console.log(one_token); + /**/} + } +}