UNPKG

python2igcse

Version:

Convert Python code to IGCSE Pseudocode format

318 lines 8.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseParser = void 0; // Base parser class const ir_1 = require("../types/ir"); const parser_1 = require("../types/parser"); /** * Base parser class * Provides common parsing functionality */ class BaseParser { constructor(options = {}) { this.startTime = 0; this.options = this.getDefaultOptions(options); this.context = this.createInitialContext(); } /** * Get default options */ getDefaultOptions(options) { return { debug: options.debug ?? false, strictTypes: options.strictTypes ?? true, strictMode: options.strictMode ?? false, preserveComments: options.preserveComments ?? true, includeComments: options.includeComments ?? true, preserveWhitespace: options.preserveWhitespace ?? false, indentSize: options.indentSize ?? 3, maxDepth: options.maxDepth ?? 50, maxErrors: options.maxErrors ?? 100, timeout: options.timeout ?? 30000 }; } /** * Create initial context */ createInitialContext() { const globalScope = { name: 'global', variables: new Map(), functions: new Map(), type: 'global' }; const context = { currentScope: globalScope, scopeStack: [globalScope], indentLevel: 0, errors: [], warnings: [], arrayInfo: {}, parameterMapping: {}, functionCalls: new Map(), startTime: Date.now(), isClass: (name) => { return !!(context.classDefinitions && context.classDefinitions[name] !== undefined); } }; return context; } /** * Add error */ addError(message, type, line, column) { const error = (0, parser_1.createParseError)(message, type, line, column); this.context.errors.push(error); if (this.options.debug) { console.error(`Parse Error: ${message} at line ${line}:${column}`); } } /** * Add warning */ addWarning(message, type, line, column) { const warning = (0, parser_1.createParseWarning)(message, type, line, column); this.context.warnings.push(warning); if (this.options.debug) { console.warn(`Parse Warning: ${message} at line ${line}:${column}`); } } /** * Start new scope */ enterScope(name, type) { const newScope = { name, parent: this.context.currentScope, variables: new Map(), functions: new Map(), type }; this.context.scopeStack.push(newScope); this.context.currentScope = newScope; } /** * End scope */ exitScope() { if (this.context.scopeStack.length > 1) { this.context.scopeStack.pop(); this.context.currentScope = this.context.scopeStack[this.context.scopeStack.length - 1]; } } /** * Get current loop type */ getCurrentLoopType() { // Search scope stack in reverse order and return the first loop scope found for (let i = this.context.scopeStack.length - 1; i >= 0; i--) { const scope = this.context.scopeStack[i]; if (scope.type === 'while' || scope.type === 'for') { return scope.type; } } return null; } /** * Register variable */ registerVariable(name, type, line) { const variable = { name, type, scope: this.context.currentScope.name, initialized: false, definedAt: line }; this.context.currentScope.variables.set(name, variable); } /** * Register function */ registerFunction(name, parameters, returnType, line) { const func = { name, parameters, returnType, isFunction: returnType !== undefined, hasReturn: returnType !== undefined, definedAt: line }; this.context.currentScope.functions.set(name, func); this.context.currentFunction = func; } /** * Find variable */ findVariable(name) { // Search from current scope to parent scopes in order let scope = this.context.currentScope; while (scope) { const variable = scope.variables.get(name); if (variable) { return variable; } scope = scope.parent; } return undefined; } /** * Find function */ findFunction(name) { // Search from current scope to parent scopes in order let scope = this.context.currentScope; while (scope) { const func = scope.functions.get(name); if (func) { return func; } scope = scope.parent; } return undefined; } /** * Register class */ registerClass(name, line) { // Register class information to current scope // Implementation is simplified, debug output only if (this.options.debug) { console.log(`Registering class: ${name} at line ${line}`); } } /** * Increase indent level */ increaseIndent() { this.context.indentLevel++; if (this.context.indentLevel > this.options.maxDepth) { this.addError(`Maximum nesting depth (${this.options.maxDepth}) exceeded`, 'validation_error'); } } /** * Decrease indent level */ decreaseIndent() { if (this.context.indentLevel > 0) { this.context.indentLevel--; } } /** * Create IR node (helper) */ createIRNode(kind, text, children = [], meta) { return (0, ir_1.createIR)(kind, text, children, meta); } /** * Create parse result */ createParseResult(ir) { const endTime = Date.now(); const parseTime = endTime - this.startTime; return { ir, errors: [...this.context.errors], warnings: [...this.context.warnings], stats: { linesProcessed: 0, // Set during implementation nodesGenerated: ir.reduce((sum, node) => sum + this.countNodes(node), 0), parseTime, functionsFound: this.countFunctions(), classesFound: 0, // Set during implementation variablesFound: this.countVariables() } }; } /** * Count IR nodes */ countNodes(ir) { return 1 + ir.children.reduce((sum, child) => sum + this.countNodes(child), 0); } /** * Count functions */ countFunctions() { let count = 0; for (const scope of this.context.scopeStack) { count += scope.functions.size; } return count; } /** * Count variables */ countVariables() { let count = 0; for (const scope of this.context.scopeStack) { count += scope.variables.size; } return count; } /** * Record parse start time */ startParsing() { this.startTime = Date.now(); } /** * Output debug information */ debug(_message) { // Debug logging disabled } /** * Reset context */ resetContext() { // Preserve function call information const functionCalls = this.context.functionCalls; this.context = this.createInitialContext(); this.context.functionCalls = functionCalls; } /** * Get errors */ getErrors() { return this.context.errors; } /** * Get warnings */ getWarnings() { return this.context.warnings; } /** * Record function call information */ recordFunctionCall(name, argumentTypes) { const existing = this.context.functionCalls.get(name); if (existing) { existing.callCount++; // Update argument type information (use latest call types) existing.argumentTypes = argumentTypes; } else { this.context.functionCalls.set(name, { name, argumentTypes, callCount: 1 }); } } /** * Get function call information */ getFunctionCallInfo(name) { return this.context.functionCalls.get(name); } /** * Get all function call information */ getAllFunctionCalls() { return this.context.functionCalls; } } exports.BaseParser = BaseParser; //# sourceMappingURL=base-parser.js.map