diff --git a/parse.js b/parse.js index b5f3041..8b3875b 100644 --- a/parse.js +++ b/parse.js @@ -71,11 +71,11 @@ class Parser { - constructor(tokenStream, mustConsumeBeforeUsingError = 4) + constructor(tokenStream, mustMatchBeforeConsiderExpression = 4) { this.tokenStream = tokenStream; this.tokenStream.index = 0; - this.mustConsumeBeforeUsingError = mustConsumeBeforeUsingError; + this.mustMatchBeforeConsiderExpression = mustMatchBeforeConsiderExpression; } block() @@ -84,7 +84,7 @@ if (openError) return this.getError(openError); let { ast:statements, error, numMatched } = this.attemptSubtree(this.statements); - if (error && numMatched > this.mustConsumeBeforeUsingError) return this.getError(error); + if (error) return this.getError(error); let { error:closeError } = this.tokenStream.consume(lex.TokenType.Op, "}"); if (closeError) return this.getError(closeError); @@ -105,7 +105,8 @@ if (error) { - if (errorMatched > mostErrorMatched) mostErrorMatched = errorMatched; + if (error.expectingMatch) return { ast: null, error: error }; + break; } else { @@ -113,7 +114,7 @@ } } - if (mostErrorMatched > this.mustConsumeBeforeUsingError) return { ast: null, error: error }; + if (error) return this.getError({ msg: "Expecting expression", ...this.tokenStream.currentLinePos() }); return { ast: { node: ASTNode.Statements, statements: statements }, error: null }; } @@ -136,6 +137,14 @@ return { ast:stmt, error: null }; } + ifStmt() + { + let error; + error = this.tokenStream.consume(lex.TokenType.Word, "if").error; + + if (error) return this.getError(error); + } + statementInternal() { return this.choice( @@ -148,7 +157,9 @@ expression() { - return this.expressionInternal(this.tokenStream, 0); + let result = this.attemptSubtree(this.expressionInternal, 0); + if (result.error) return this.getError(result.error, result.numMatched > this.mustMatchBeforeConsiderExpression); + return result; } /* Parses an expression consisting of a set of values, all separated by infix operators, @@ -410,34 +421,35 @@ return { numMatched: numMatched, ...subtree}; } - getError(error) + getError(error, expectingMatch = undefined) { - return { ast: null, error: error }; + if (expectingMatch === undefined) + { + if (error.expectingMatch !== undefined) + { + expectingMatch = error.expectingMatch; + } + else + { + expectingMatch = false; + } + } + return { ast: null, error: { ...error, expectingMatch: expectingMatch } }; } choice(choices, genericError) { - let bestError, bestErrorNumMatched = 0; - for (let choice of choices) { if (choice.parse && choice.handle) { let { ast, error, numMatched } = this.attemptSubtree(choice.parse); if (!error) return { ast: choice.handle(ast), error: null }; - if (numMatched > bestErrorNumMatched) - { - bestError = error; - bestErrorNumMatched = numMatched; - } + if (error.expectingMatch) return this.getError(error); } } - if (bestError && bestErrorNumMatched > this.mustConsumeBeforeUsingError) - { - return { ast: null, error: bestError }; - } - return { ast: null, error: { msg: genericError, ...this.tokenStream.currentLinePos() } }; + return this.getError({ msg: genericError, ...this.tokenStream.currentLinePos() }); } }