python2igcse
Version:
Convert Python code to IGCSE Pseudocode format
290 lines • 8.39 kB
JavaScript
"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,
maxNestingDepth: options.maxNestingDepth ?? 50,
maxErrors: options.maxErrors ?? 100,
timeout: options.timeout ?? 30000,
allowExperimentalSyntax: options.allowExperimentalSyntax ?? false,
};
}
/**
* 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: {},
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 first found loop scope
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;
}
/**
* 関数の検索
*/
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;
}
/**
* クラスの登録
*/
registerClass(name, line) {
// クラス情報を現在のスコープに登録
// 実装は簡略化し、デバッグ出力のみ
if (this.options.debug) {
console.log(`Registering class: ${name} at line ${line}`);
}
}
/**
* インデントレベルの増加
*/
increaseIndent() {
this.context.indentLevel++;
if (this.context.indentLevel > this.options.maxDepth) {
this.addError(`Maximum nesting depth (${this.options.maxDepth}) exceeded`, 'validation_error');
}
}
/**
* インデントレベルの減少
*/
decreaseIndent() {
if (this.context.indentLevel > 0) {
this.context.indentLevel--;
}
}
/**
* IRノードの作成(ヘルパー)
*/
createIRNode(kind, text, children = [], meta) {
return (0, ir_1.createIR)(kind, text, children, meta);
}
/**
* パース結果の作成
*/
createParseResult(ir) {
const endTime = Date.now();
const parseTime = endTime - this.startTime;
return {
ir,
errors: [...this.context.errors],
warnings: [...this.context.warnings],
stats: {
linesProcessed: 0, // 実装時に設定
nodesGenerated: ir.reduce((sum, node) => sum + this.countNodes(node), 0),
parseTime,
functionsFound: this.countFunctions(),
classesFound: this.context.classDefinitions
? Object.keys(this.context.classDefinitions).length
: 0,
variablesFound: this.countVariables(),
},
success: this.context.errors.length === 0,
parseTime,
};
}
/**
* IRノード数のカウント
*/
countNodes(ir) {
return 1 + ir.children.reduce((sum, child) => sum + this.countNodes(child), 0);
}
/**
* 関数数のカウント
*/
countFunctions() {
let count = 0;
for (const scope of this.context.scopeStack) {
count += scope.functions.size;
}
return count;
}
/**
* 変数数のカウント
*/
countVariables() {
let count = 0;
for (const scope of this.context.scopeStack) {
count += scope.variables.size;
}
return count;
}
/**
* パースの開始時刻を記録
*/
startParsing() {
this.startTime = Date.now();
}
/**
* デバッグ情報の出力
*/
debug(_message) {
// Debug logging disabled
}
/**
* コンテキストのリセット
*/
resetContext() {
this.context = this.createInitialContext();
}
/**
* エラーの取得
*/
getErrors() {
return this.context.errors;
}
/**
* 警告の取得
*/
getWarnings() {
return this.context.warnings;
}
}
exports.BaseParser = BaseParser;
//# sourceMappingURL=base-parser.js.map