Better names

This commit is contained in:
Corey Johnson 2025-11-06 10:21:02 -08:00
parent 4494cbce91
commit 061452a334
7 changed files with 11 additions and 11 deletions

View File

@ -200,7 +200,7 @@ function parseExpression(input: string) {
- **Not in scope** → Parses as `Word("obj.prop")` → compiles to `PUSH 'obj.prop'` (treated as file path/string) - **Not in scope** → Parses as `Word("obj.prop")` → compiles to `PUSH 'obj.prop'` (treated as file path/string)
Implementation files: Implementation files:
- **src/parser/scopeTracker.ts**: ContextTracker that maintains immutable scope chain - **src/parser/parserScopeContext.ts**: ContextTracker that maintains immutable scope chain
- **src/parser/tokenizer.ts**: External tokenizer checks `stack.context` to decide if dot creates DotGet or Word - **src/parser/tokenizer.ts**: External tokenizer checks `stack.context` to decide if dot creates DotGet or Word
- Scope tracking: Captures variables from assignments (`x = 5`) and function parameters (`fn x:`) - Scope tracking: Captures variables from assignments (`x = 5`) and function parameters (`fn x:`)
- See `src/parser/tests/dot-get.test.ts` for comprehensive examples - See `src/parser/tests/dot-get.test.ts` for comprehensive examples

View File

@ -1,6 +1,6 @@
@external propSource highlighting from "./highlight" @external propSource highlighting from "./highlight"
@context trackScope from "./scopeTracker" @context trackScope from "./parserScopeContext"
@skip { space | Comment } @skip { space | Comment }

View File

@ -2,7 +2,7 @@
import {LRParser, LocalTokenGroup} from "@lezer/lr" import {LRParser, LocalTokenGroup} from "@lezer/lr"
import {operatorTokenizer} from "./operatorTokenizer" import {operatorTokenizer} from "./operatorTokenizer"
import {tokenizer, specializeKeyword} from "./tokenizer" import {tokenizer, specializeKeyword} from "./tokenizer"
import {trackScope} from "./scopeTracker" import {trackScope} from "./parserScopeContext"
import {highlighting} from "./highlight" import {highlighting} from "./highlight"
const spec_Identifier = {__proto__:null,if:66, null:94, catch:100, finally:106, end:108, else:116, while:130, try:136, throw:140} const spec_Identifier = {__proto__:null,if:66, null:94, catch:100, finally:106, end:108, else:116, while:130, try:136, throw:140}
export const parser = LRParser.deserialize({ export const parser = LRParser.deserialize({

View File

@ -1,10 +1,10 @@
import { test, expect, describe } from 'bun:test' import { test, expect, describe } from 'bun:test'
import { ScopeTracker } from './scopeTracker' import { EditorScopeAnalyzer } from './editorScopeAnalyzer'
import { TextDocument } from 'vscode-languageserver-textdocument' import { TextDocument } from 'vscode-languageserver-textdocument'
import { parser } from '../../../src/parser/shrimp' import { parser } from '../../../src/parser/shrimp'
import * as Terms from '../../../src/parser/shrimp.terms' import * as Terms from '../../../src/parser/shrimp.terms'
describe('ScopeTracker', () => { describe('EditorScopeAnalyzer', () => {
test('top-level assignment is in scope', () => { test('top-level assignment is in scope', () => {
const code = 'x = 5\necho x' const code = 'x = 5\necho x'
const { tree, tracker } = parseAndGetScope(code) const { tree, tracker } = parseAndGetScope(code)
@ -146,6 +146,6 @@ end`
const parseAndGetScope = (code: string) => { const parseAndGetScope = (code: string) => {
const document = TextDocument.create('test://test.sh', 'shrimp', 1, code) const document = TextDocument.create('test://test.sh', 'shrimp', 1, code)
const tree = parser.parse(code) const tree = parser.parse(code)
const tracker = new ScopeTracker(document) const tracker = new EditorScopeAnalyzer(document)
return { document, tree, tracker } return { document, tree, tracker }
} }

View File

@ -7,7 +7,7 @@ import { globals } from '../../../src/prelude'
* Tracks variables in scope at a given position in the parse tree. * Tracks variables in scope at a given position in the parse tree.
* Used to distinguish identifiers (in scope) from words (not in scope). * Used to distinguish identifiers (in scope) from words (not in scope).
*/ */
export class ScopeTracker { export class EditorScopeAnalyzer {
private document: TextDocument private document: TextDocument
private scopeCache = new Map<number, Set<string>>() private scopeCache = new Map<number, Set<string>>()

View File

@ -7,7 +7,7 @@ import {
SemanticTokenTypes, SemanticTokenTypes,
SemanticTokenModifiers, SemanticTokenModifiers,
} from 'vscode-languageserver/node' } from 'vscode-languageserver/node'
import { ScopeTracker } from './scopeTracker' import { EditorScopeAnalyzer } from './editorScopeAnalyzer'
export const TOKEN_TYPES = [ export const TOKEN_TYPES = [
SemanticTokenTypes.function, SemanticTokenTypes.function,
@ -32,7 +32,7 @@ export function buildSemanticTokens(document: TextDocument): number[] {
const text = document.getText() const text = document.getText()
const tree = parser.parse(text) const tree = parser.parse(text)
const builder = new SemanticTokensBuilder() const builder = new SemanticTokensBuilder()
const scopeTracker = new ScopeTracker(document) const scopeTracker = new EditorScopeAnalyzer(document)
walkTree(tree.topNode, document, builder, scopeTracker) walkTree(tree.topNode, document, builder, scopeTracker)
@ -77,7 +77,7 @@ function walkTree(
node: SyntaxNode, node: SyntaxNode,
document: TextDocument, document: TextDocument,
builder: SemanticTokensBuilder, builder: SemanticTokensBuilder,
scopeTracker: ScopeTracker scopeTracker: EditorScopeAnalyzer
) { ) {
// Special handling for NamedArgPrefix to split "name=" into two tokens // Special handling for NamedArgPrefix to split "name=" into two tokens
if (node.type.id === Terms.NamedArgPrefix) { if (node.type.id === Terms.NamedArgPrefix) {
@ -104,7 +104,7 @@ type TokenInfo = { type: number; modifiers: number } | undefined
function getTokenType( function getTokenType(
node: SyntaxNode, node: SyntaxNode,
document: TextDocument, document: TextDocument,
scopeTracker: ScopeTracker scopeTracker: EditorScopeAnalyzer
): TokenInfo { ): TokenInfo {
const nodeTypeId = node.type.id const nodeTypeId = node.type.id
const parentTypeId = node.parent?.type.id const parentTypeId = node.parent?.type.id