Parse error cleanup. Don't tokenize digraphs.

This commit is contained in:
Joshua Bell 2013-08-17 16:00:23 -07:00
parent e44c2069e8
commit c96d891dc3

View File

@ -1173,10 +1173,8 @@ this.basic = (function() {
currLineNumber = 0; currLineNumber = 0;
function parse_error(msg) { function parse_error(msg) {
var e = new basic.ParseError(msg + " in line " + currLineNumber, return new basic.ParseError(msg + " in line " + currLineNumber,
currLine, currColumn); currLine, currColumn);
throw e;
} }
@ -1214,7 +1212,7 @@ this.basic = (function() {
regexStringLiteral = /^"([^"]*?)(?:"|(?=\n|\r|$))/, regexStringLiteral = /^"([^"]*?)(?:"|(?=\n|\r|$))/,
regexNumberLiteral = /^[0-9]*\.?[0-9]+(?:[eE]\s*[\-+]?\s*[0-9]+)?/, regexNumberLiteral = /^[0-9]*\.?[0-9]+(?:[eE]\s*[\-+]?\s*[0-9]+)?/,
regexHexLiteral = /^\$[0-9A-Fa-f]+/, regexHexLiteral = /^\$[0-9A-Fa-f]+/,
regexOperator = /^(;|<[ \t]*=|=[ \t]*<|>[ \t]*=|=[ \t]*>|=[ \t]*=|<[ \t]*>|>[ \t]*<|=|<|>|\+|-|\*|\/|\^|\(|\)|,)/, regexOperator = /^[;=<>+\-*\/\^(),]/,
regexLineNumber = /^[0-9]+/, regexLineNumber = /^[0-9]+/,
regexSeparator = /^:/, regexSeparator = /^:/,
@ -1268,7 +1266,7 @@ this.basic = (function() {
// Extension - allow leading : to continue previous line // Extension - allow leading : to continue previous line
token.separator = stream.lastMatch[0]; token.separator = stream.lastMatch[0];
} else { } else {
parse_error("Syntax error: Expected line number or separator"); throw parse_error("Syntax error: Expected line number or separator");
} }
} else if (stream.match(regexRemark)) { } else if (stream.match(regexRemark)) {
token.remark = stream.lastMatch[2]; token.remark = stream.lastMatch[2];
@ -1291,7 +1289,7 @@ this.basic = (function() {
} else if (stream.match(regexSeparator)) { } else if (stream.match(regexSeparator)) {
token.separator = stream.lastMatch[0]; token.separator = stream.lastMatch[0];
} else { } else {
parse_error("Syntax error: Unexpected '" + source.substr(0, 40) + "'"); throw parse_error("Syntax error: Unexpected '" + source.substr(0, 40) + "'");
} }
return token; return token;
} }
@ -1301,7 +1299,7 @@ this.basic = (function() {
match = function match(type, value) { match = function match(type, value) {
if (!lookahead) { if (!lookahead) {
parse_error("Syntax error: Expected " + type + ", saw end of file"); throw parse_error("Syntax error: Expected " + type + ", saw end of file");
} }
var token = lookahead; var token = lookahead;
@ -1311,11 +1309,11 @@ this.basic = (function() {
lookahead = nextToken(); lookahead = nextToken();
if (!{}.hasOwnProperty.call(token, type)) { if (!{}.hasOwnProperty.call(token, type)) {
parse_error("Syntax error: Expected " + type + ", saw " + JSON.stringify(token)); throw parse_error("Syntax error: Expected " + type + ", saw " + JSON.stringify(token));
} }
if (value !== (void 0) && token[type] !== value) { if (value !== (void 0) && token[type] !== value) {
parse_error("Syntax error: Expected '" + value + "', saw " + JSON.stringify(token)); throw parse_error("Syntax error: Expected '" + value + "', saw " + JSON.stringify(token));
} }
return token[type]; return token[type];
@ -1397,7 +1395,7 @@ this.basic = (function() {
function enforce_type(actual, expected) { function enforce_type(actual, expected) {
if (actual !== expected) { if (actual !== expected) {
parse_error('Type mismatch error: Expected ' + expected); throw parse_error('Type mismatch error: Expected ' + expected);
} }
} }
@ -1477,7 +1475,7 @@ this.basic = (function() {
function parsefunction(name) { function parsefunction(name) {
if (!{}.hasOwnProperty.call(funlib, name)) { if (!{}.hasOwnProperty.call(funlib, name)) {
parse_error("Undefined function: " + name); throw parse_error("Undefined function: " + name);
} }
match("operator", "("); match("operator", "(");
@ -1618,31 +1616,29 @@ this.basic = (function() {
function parseRelationalExpression() { function parseRelationalExpression() {
var lhs = parseAdditiveExpression(), rhs, op; var lhs = parseAdditiveExpression(), rhs, op;
while ( while (test('operator', '<') || test('operator', '>') || test('operator', '=')) {
test('operator', '<') || test('operator', '>') ||
test('operator', '=') || test('operator', '==') ||
test('operator', '<=') || test('operator', '=<') ||
test('operator', '>=') || test('operator', '=>') ||
test('operator', '<>') || test('operator', '><')) {
op = match('operator'); op = match('operator');
switch (op) {
case '<':
if (test('operator', '=', true)) { op = '<='; break; }
if (test('operator', '>', true)) { op = '!=='; break; }
break;
case '>':
if (test('operator', '=', true)) { op = '>='; break; }
if (test('operator', '<', true)) { op = '!=='; break; }
break;
case '=':
if (test('operator', '<', true)) { op = '<='; break; }
if (test('operator', '>', true)) { op = '>='; break; }
if (test('operator', '=', true)) { op = '==='; break; }
op = '===';
}
rhs = parseAdditiveExpression(); rhs = parseAdditiveExpression();
enforce_type(rhs.type, lhs.type); enforce_type(rhs.type, lhs.type);
lhs = lhs = { source: '((' + lhs.source + op + rhs.source + ')?1:0)', type: 'number' };
switch (op) {
case "<": lhs = { source: '((' + lhs.source + '<' + rhs.source + ')?1:0)', type: 'number' }; break;
case ">": lhs = { source: '((' + lhs.source + '>' + rhs.source + ')?1:0)', type: 'number' }; break;
case "<=":
case "=<": lhs = { source: '((' + lhs.source + '<=' + rhs.source + ')?1:0)', type: 'number' }; break;
case ">=":
case "=>": lhs = { source: '((' + lhs.source + '>=' + rhs.source + ')?1:0)', type: 'number' }; break;
case "=":
case "==": lhs = { source: '((' + lhs.source + '===' + rhs.source + ')?1:0)', type: 'number' }; break;
case "<>":
case "><": lhs = { source: '((' + lhs.source + '!==' + rhs.source + ')?1:0)', type: 'number' }; break;
}
} }
return lhs; return lhs;
} }
@ -1748,7 +1744,7 @@ this.basic = (function() {
match("operator", "="); match("operator", "=");
if (vartype(name) !== vartype(param)) { if (vartype(name) !== vartype(param)) {
parse_error("DEF FN function type and argument type must match"); throw parse_error("DEF FN function type and argument type must match");
} }
expr = vartype(name) === 'string' expr = vartype(name) === 'string'
@ -1782,7 +1778,7 @@ this.basic = (function() {
keyword = match('reserved'); keyword = match('reserved');
if (keyword !== kws.GOTO && keyword !== kws.GOSUB) { if (keyword !== kws.GOTO && keyword !== kws.GOSUB) {
parse_error("Syntax error: Expected " + kws.GOTO + " or " + kws.GOSUB); throw parse_error("Syntax error: Expected " + kws.GOTO + " or " + kws.GOSUB);
} }
args = []; args = [];
@ -1804,7 +1800,7 @@ this.basic = (function() {
case kws.FOR: // FOR i = m TO n STEP s case kws.FOR: // FOR i = m TO n STEP s
name = match('identifier'); name = match('identifier');
if (vartype(name) !== 'float') { if (vartype(name) !== 'float') {
parse_error("Syntax error: Expected floating point variable"); throw parse_error("Syntax error: Expected floating point variable");
} }
identifiers.variables[name] = true; identifiers.variables[name] = true;
@ -2049,8 +2045,7 @@ this.basic = (function() {
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
case kws.LIST: // List program statements case kws.LIST: // List program statements
parse_error("Introspection statement not supported: " + keyword); throw parse_error("Introspection statement not supported: " + keyword);
return;
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// //
@ -2063,16 +2058,14 @@ this.basic = (function() {
case kws.SCALE: // Set rotation angle for hires shape case kws.SCALE: // Set rotation angle for hires shape
case kws.DRAW: // Draw hires shape case kws.DRAW: // Draw hires shape
case kws.XDRAW: // XOR draw hires shape case kws.XDRAW: // XOR draw hires shape
parse_error("Display statement not supported: " + keyword); throw parse_error("Display statement not supported: " + keyword);
return;
// Interpreter Routines // Interpreter Routines
case kws.CONT: // Continue stopped program (immediate mode) case kws.CONT: // Continue stopped program (immediate mode)
case kws.DEL: // Deletes program statements case kws.DEL: // Deletes program statements
case kws.NEW: // Wipe program case kws.NEW: // Wipe program
case kws.RUN: // Execute program case kws.RUN: // Execute program
parse_error("Interpreter statement not supported: " + keyword); throw parse_error("Interpreter statement not supported: " + keyword);
return;
// Native Routines // Native Routines
case kws.HIMEM: // Set upper bound of variable memory case kws.HIMEM: // Set upper bound of variable memory
@ -2080,8 +2073,7 @@ this.basic = (function() {
case kws.LOMEM: // Set low bound of variable memory case kws.LOMEM: // Set low bound of variable memory
case kws.WAIT: // Wait for memory value to match a condition case kws.WAIT: // Wait for memory value to match a condition
case kws.AMPERSAND: // Command hook case kws.AMPERSAND: // Command hook
parse_error("Native interop statement not supported: " + keyword); throw parse_error("Native interop statement not supported: " + keyword);
return;
// Tape Routines // Tape Routines
case kws.LOAD: // Load program from cassette port case kws.LOAD: // Load program from cassette port
@ -2089,8 +2081,7 @@ this.basic = (function() {
case kws.SAVE: // Save program to cassette port case kws.SAVE: // Save program to cassette port
case kws.STORE: // Store array to cassette port case kws.STORE: // Store array to cassette port
case kws.SHLOAD: // Load shape table from cassette port case kws.SHLOAD: // Load shape table from cassette port
parse_error("Tape statement not supported: " + keyword); throw parse_error("Tape statement not supported: " + keyword);
return;
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// //
@ -2100,8 +2091,7 @@ this.basic = (function() {
// Parts of other statements - AT, FN, STEP, TO, THEN, etc. // Parts of other statements - AT, FN, STEP, TO, THEN, etc.
default: default:
parse_error("Syntax error: " + keyword); throw parse_error("Syntax error: " + keyword);
return;
} }
} }