refactor in preparation for parsing local types

This commit is contained in:
Dave Holoway
2020-06-11 18:06:44 +01:00
parent d0308781f7
commit ac9a7ed43a

View File

@@ -95,7 +95,24 @@ function addLocals(tokens, locals, new_locals) {
* @returns {ResolvedIdent|Local[]|Statement} * @returns {ResolvedIdent|Local[]|Statement}
*/ */
function statement(tokens, locals, method, imports, typemap) { function statement(tokens, locals, method, imports, typemap) {
let s; let s, modifiers = [];
for (;;) {
switch(tokens.current.kind) {
case 'modifier':
modifiers.push(tokens.current);
tokens.inc();
continue;
}
break;
}
// modifiers are only allowed on local variable decls
if (modifiers.length) {
s = var_decl(modifiers, tokens, locals, method, imports, typemap);
addLocals(tokens, locals, s);
semicolon(tokens);
return s;
}
switch(tokens.current.kind) { switch(tokens.current.kind) {
case 'statement-kw': case 'statement-kw':
s = statementKeyword(tokens, locals, method, imports, typemap); s = statementKeyword(tokens, locals, method, imports, typemap);
@@ -112,7 +129,6 @@ function statement(tokens, locals, method, imports, typemap) {
return statement(tokens, locals, method, imports, typemap); return statement(tokens, locals, method, imports, typemap);
} }
// fall-through to expression_or_var_decl // fall-through to expression_or_var_decl
case 'modifier':
case 'primitive-type': case 'primitive-type':
s = expression_or_var_decl(tokens, locals, method, imports, typemap); s = expression_or_var_decl(tokens, locals, method, imports, typemap);
if (Array.isArray(s)) { if (Array.isArray(s)) {
@@ -772,23 +788,31 @@ function checkThrowExpression(tokens, throw_expression, typemap) {
* @param {SourceMC} method * @param {SourceMC} method
* @param {ResolvedImport[]} imports * @param {ResolvedImport[]} imports
* @param {Map<string,JavaType>} typemap * @param {Map<string,JavaType>} typemap
* @returns {ResolvedIdent|Local[]} * @returns {Local[]}
*/ */
function expression_or_var_decl(tokens, locals, method, imports, typemap) { function var_decl(mods, tokens, locals, method, imports, typemap) {
const mods = []; const type = typeIdent(tokens, method, imports, typemap);
while (tokens.current.kind === 'modifier') { return var_ident_list(mods, type, tokens, locals, method, imports, typemap)
mods.push(tokens.current);
tokens.inc();
} }
/** @type {ResolvedIdent} */ /**
let matches = expression(tokens, locals, method, imports, typemap); *
* @param {Token[]} mods
// if theres at least one type followed by an ident, we assume a variable declaration * @param {JavaType} type
if (matches.types[0] && tokens.current.kind === 'ident') { * @param {TokenList} tokens
const new_locals = []; * @param {Local[]} locals
* @param {SourceMC} method
* @param {ResolvedImport[]} imports
* @param {Map<string,JavaType>} typemap
*/
function var_ident_list(mods, type, tokens, locals, method, imports, typemap) {
checkLocalModifiers(tokens, mods); checkLocalModifiers(tokens, mods);
const new_locals = [];
for (;;) { for (;;) {
if (tokens.current.kind !== 'ident') {
addproblem(tokens, ParseProblem.Error(tokens.current, `Variable name expected`));
break;
}
const name = tokens.current; const name = tokens.current;
tokens.inc(); tokens.inc();
// look for [] after the variable name // look for [] after the variable name
@@ -797,7 +821,7 @@ function expression_or_var_decl(tokens, locals, method, imports, typemap) {
postnamearrdims += 1; postnamearrdims += 1;
tokens.expectValue(']'); tokens.expectValue(']');
} }
let local = new Local(mods, name.value, name, matches.types[0], postnamearrdims); let local = new Local(mods, name.value, name, type, postnamearrdims);
if (tokens.isValue('=')) { if (tokens.isValue('=')) {
const op = tokens.previous; const op = tokens.previous;
local.init = expression(tokens, locals, method, imports, typemap); local.init = expression(tokens, locals, method, imports, typemap);
@@ -806,19 +830,31 @@ function expression_or_var_decl(tokens, locals, method, imports, typemap) {
} }
new_locals.push(local); new_locals.push(local);
if (tokens.isValue(',')) { if (tokens.isValue(',')) {
if (tokens.current.kind === 'ident') {
continue; continue;
} }
addproblem(tokens, ParseProblem.Error(tokens.current, `Variable name expected`));
}
break; break;
} }
return new_locals; return new_locals;
} }
if (mods.length) { /**
addproblem(tokens, ParseProblem.Error(mods[0], `Unexpected token: '${mods[0].value}'`)) * @param {TokenList} tokens
* @param {Local[]} locals
* @param {SourceMC} method
* @param {ResolvedImport[]} imports
* @param {Map<string,JavaType>} typemap
* @returns {ResolvedIdent|Local[]}
*/
function expression_or_var_decl(tokens, locals, method, imports, typemap) {
/** @type {ResolvedIdent} */
let matches = expression(tokens, locals, method, imports, typemap);
// if theres at least one type followed by an ident, we assume a variable declaration
if (matches.types[0] && tokens.current.kind === 'ident') {
return var_ident_list([], matches.types[0], tokens, locals, method, imports, typemap);
} }
return matches; return matches;
} }