refactor(scope): simplify trackScope to only track AssignableIdentifier
- Update trackScope ContextTracker to use ScopeContext wrapper - Simplify shift() to only capture AssignableIdentifier tokens - Simplify reduce() to handle only Assign, Params, and FunctionDef - Update hash function to use hashScope helper - Export ScopeContext class for use in tokenizer - Update tokenizer to access scope via ScopeContext.scope 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
7de1682e91
commit
aee9fa0747
|
|
@ -42,7 +42,7 @@ export class Scope {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper that adds temporary state for identifier capture
|
// Wrapper that adds temporary state for identifier capture
|
||||||
class ScopeContext {
|
export class ScopeContext {
|
||||||
constructor(
|
constructor(
|
||||||
public scope: Scope,
|
public scope: Scope,
|
||||||
public pendingIds: string[] = []
|
public pendingIds: string[] = []
|
||||||
|
|
@ -54,17 +54,12 @@ const hashScope = (context: ScopeContext): number => {
|
||||||
return context.scope.hash()
|
return context.scope.hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
export const trackScope = new ContextTracker<Scope>({
|
export const trackScope = new ContextTracker<ScopeContext>({
|
||||||
start: new Scope(null, new Set(), [], false),
|
start: new ScopeContext(new Scope(null, new Set())),
|
||||||
|
|
||||||
shift(context, term, stack, input) {
|
shift(context, term, stack, input) {
|
||||||
// Track fn keyword to enter param capture mode
|
// Only capture AssignableIdentifier tokens
|
||||||
if (term === terms.Fn) {
|
if (term === terms.AssignableIdentifier) {
|
||||||
return context.withIsInParams(true).withPendingIdentifiers([])
|
|
||||||
}
|
|
||||||
|
|
||||||
// Capture identifiers
|
|
||||||
if (term === terms.Identifier) {
|
|
||||||
// Build text by peeking backwards from stack.pos to input.pos
|
// Build text by peeking backwards from stack.pos to input.pos
|
||||||
let text = ''
|
let text = ''
|
||||||
const start = input.pos
|
const start = input.pos
|
||||||
|
|
@ -76,14 +71,10 @@ export const trackScope = new ContextTracker<Scope>({
|
||||||
text += String.fromCharCode(ch)
|
text += String.fromCharCode(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Capture ALL identifiers when in params
|
return new ScopeContext(
|
||||||
if (context.isInParams) {
|
context.scope,
|
||||||
return context.withPendingIdentifiers([...context.pendingIdentifiers, text])
|
[...context.pendingIds, text]
|
||||||
}
|
)
|
||||||
// Capture FIRST identifier for assignments
|
|
||||||
else if (context.pendingIdentifiers.length === 0) {
|
|
||||||
return context.withPendingIdentifiers([text])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
@ -91,31 +82,33 @@ export const trackScope = new ContextTracker<Scope>({
|
||||||
|
|
||||||
reduce(context, term, stack, input) {
|
reduce(context, term, stack, input) {
|
||||||
// Add assignment variable to scope
|
// Add assignment variable to scope
|
||||||
if (term === terms.Assign && context.pendingIdentifiers.length > 0) {
|
if (term === terms.Assign && context.pendingIds.length > 0) {
|
||||||
return context.add(context.pendingIdentifiers[0]!)
|
// Pop the last identifier (most recent AssignableIdentifier)
|
||||||
|
const varName = context.pendingIds[context.pendingIds.length - 1]!
|
||||||
|
return new ScopeContext(
|
||||||
|
context.scope.add(varName),
|
||||||
|
context.pendingIds.slice(0, -1)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push new scope and add parameters
|
// Push new scope and add all parameters
|
||||||
if (term === terms.Params) {
|
if (term === terms.Params) {
|
||||||
const newScope = context.push()
|
const newScope = context.scope.push()
|
||||||
if (context.pendingIdentifiers.length > 0) {
|
return new ScopeContext(
|
||||||
return newScope.add(...context.pendingIdentifiers).withIsInParams(false)
|
context.pendingIds.length > 0
|
||||||
}
|
? newScope.add(...context.pendingIds)
|
||||||
return newScope.withIsInParams(false)
|
: newScope,
|
||||||
|
[] // Clear all pending after consuming
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pop scope when exiting function
|
// Pop scope when exiting function
|
||||||
if (term === terms.FunctionDef) {
|
if (term === terms.FunctionDef) {
|
||||||
return context.pop()
|
return new ScopeContext(context.scope.pop(), [])
|
||||||
}
|
|
||||||
|
|
||||||
// Clear stale identifiers after non-assignment statements
|
|
||||||
if (term === terms.DotGet || term === terms.FunctionCallOrIdentifier || term === terms.FunctionCall) {
|
|
||||||
return context.clearPending()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return context
|
return context
|
||||||
},
|
},
|
||||||
|
|
||||||
hash: (context) => context.hash(),
|
hash: hashScope,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { ExternalTokenizer, InputStream, Stack } from '@lezer/lr'
|
import { ExternalTokenizer, InputStream, Stack } from '@lezer/lr'
|
||||||
import { Identifier, AssignableIdentifier, Word, IdentifierBeforeDot } from './shrimp.terms'
|
import { Identifier, AssignableIdentifier, Word, IdentifierBeforeDot } from './shrimp.terms'
|
||||||
import type { Scope } from './scopeTracker'
|
import type { ScopeContext } from './scopeTracker'
|
||||||
|
|
||||||
// The only chars that can't be words are whitespace, apostrophes, closing parens, and EOF.
|
// The only chars that can't be words are whitespace, apostrophes, closing parens, and EOF.
|
||||||
|
|
||||||
|
|
@ -36,7 +36,8 @@ export const tokenizer = new ExternalTokenizer(
|
||||||
identifierText += String.fromCharCode(charCode)
|
identifierText += String.fromCharCode(charCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
const scope = stack.context as Scope | undefined
|
const scopeContext = stack.context as ScopeContext | undefined
|
||||||
|
const scope = scopeContext?.scope
|
||||||
|
|
||||||
if (scope?.has(identifierText)) {
|
if (scope?.has(identifierText)) {
|
||||||
// In scope - stop here, let grammar parse property access
|
// In scope - stop here, let grammar parse property access
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user