in src/powerquery-parser/parser/disambiguation/disambiguationUtils.ts [180:248]
export function maybeDisambiguateParenthesis(state: ParseState, parser: Parser): ParenthesisDisambiguation | undefined {
const trace: Trace = state.traceManager.entry(
DisambiguationTraceConstant.Disambiguation,
maybeDisambiguateParenthesis.name,
);
const initialTokenIndex: number = state.tokenIndex;
const tokens: ReadonlyArray<Token.Token> = state.lexerSnapshot.tokens;
const totalTokens: number = tokens.length;
let nestedDepth: number = 1;
let offsetTokenIndex: number = initialTokenIndex + 1;
while (offsetTokenIndex < totalTokens) {
const offsetTokenKind: Token.TokenKind = tokens[offsetTokenIndex].kind;
if (offsetTokenKind === Token.TokenKind.LeftParenthesis) {
nestedDepth += 1;
} else if (offsetTokenKind === Token.TokenKind.RightParenthesis) {
nestedDepth -= 1;
}
let maybeDisambiguation: ParenthesisDisambiguation | undefined = undefined;
if (nestedDepth === 0) {
// '(x as number) as number' could either be either case,
// so we need to consume test if the trailing 'as number' is followed by a FatArrow.
if (ParseStateUtils.isTokenKind(state, Token.TokenKind.KeywordAs, offsetTokenIndex + 1)) {
const checkpoint: ParseStateCheckpoint = parser.createCheckpoint(state);
unsafeMoveTo(state, offsetTokenIndex + 2);
try {
parser.readNullablePrimitiveType(state, parser);
} catch {
parser.restoreCheckpoint(state, checkpoint);
if (ParseStateUtils.isOnTokenKind(state, Token.TokenKind.FatArrow)) {
return ParenthesisDisambiguation.FunctionExpression;
} else {
return ParenthesisDisambiguation.ParenthesizedExpression;
}
}
if (ParseStateUtils.isOnTokenKind(state, Token.TokenKind.FatArrow)) {
maybeDisambiguation = ParenthesisDisambiguation.FunctionExpression;
} else {
maybeDisambiguation = ParenthesisDisambiguation.ParenthesizedExpression;
}
parser.restoreCheckpoint(state, checkpoint);
} else if (ParseStateUtils.isTokenKind(state, Token.TokenKind.FatArrow, offsetTokenIndex + 1)) {
maybeDisambiguation = ParenthesisDisambiguation.FunctionExpression;
} else {
maybeDisambiguation = ParenthesisDisambiguation.ParenthesizedExpression;
}
}
if (maybeDisambiguation) {
trace.exit({ [TraceConstant.Result]: maybeDisambiguation });
return maybeDisambiguation;
}
offsetTokenIndex += 1;
}
trace.exit({ [TraceConstant.Result]: undefined });
return undefined;
}