fix: lint, type errors

test: specify types for path checks in interpreter tests

test: add optional chaining in lexer tests to prevent errors

test: add optional chaining in parser tests to prevent errors

fix: clean up whitespace and formatting in AST and lexer files

feat: enhance CLI with improved error handling and user prompts

fix: update index and interpreter files for better type handling

fix: clean up parser code for better readability and error handling

build: enable minification in tsdown configuration
This commit is contained in:
2025-09-01 02:44:45 +07:00
parent eb357ef703
commit 13d79e37bb
14 changed files with 279 additions and 248 deletions
+1 -1
View File
@@ -138,6 +138,6 @@ describe('questLang Integration', () => {
interpreter.moveToNode('выбор_пути');
const choices = interpreter.getAvailableChoices();
expect(choices).toHaveLength(3);
expect(choices[0].text).toBe('Пойти в дешёвую шашлычную');
expect(choices[0]?.text).toBe('Пойти в дешёвую шашлычную');
});
});
+2 -2
View File
@@ -170,7 +170,7 @@ describe('questInterpreter', () => {
expect(paths.length).toBeGreaterThan(0);
// Should have at least two paths (налево->победа and направо)
expect(paths.some(path => path.includes('победа'))).toBe(true);
expect(paths.some(path => path.includes('направо'))).toBe(true);
expect(paths.some((path: string) => path.includes('победа'))).toBe(true);
expect(paths.some((path: string) => path.includes('направо'))).toBe(true);
});
});
+24 -24
View File
@@ -1,6 +1,6 @@
import { describe, expect, it } from 'vitest';
import { Lexer } from '../lexer';
import { TokenType } from '..';
import { Lexer } from '../lexer';
describe('lexer', () => {
it('should tokenize quest keywords', () => {
@@ -8,19 +8,19 @@ describe('lexer', () => {
const lexer = new Lexer(source);
const tokens = lexer.tokenize();
expect(tokens[0].type).toBe(TokenType.QUEST);
expect(tokens[0].value).toBe('квест');
expect(tokens[0]?.type).toBe(TokenType.QUEST);
expect(tokens[0]?.value).toBe('квест');
expect(tokens[1].type).toBe(TokenType.IDENTIFIER);
expect(tokens[1].value).toBe('Тест');
expect(tokens[1]?.type).toBe(TokenType.IDENTIFIER);
expect(tokens[1]?.value).toBe('Тест');
expect(tokens[2].type).toBe(TokenType.SEMICOLON);
expect(tokens[2]?.type).toBe(TokenType.SEMICOLON);
expect(tokens[3].type).toBe(TokenType.GOAL);
expect(tokens[3].value).toBe('цель');
expect(tokens[3]?.type).toBe(TokenType.GOAL);
expect(tokens[3]?.value).toBe('цель');
expect(tokens[4].type).toBe(TokenType.STRING);
expect(tokens[4].value).toBe('Описание');
expect(tokens[4]?.type).toBe(TokenType.STRING);
expect(tokens[4]?.value).toBe('Описание');
});
it('should tokenize strings correctly', () => {
@@ -28,8 +28,8 @@ describe('lexer', () => {
const lexer = new Lexer(source);
const tokens = lexer.tokenize();
expect(tokens[0].type).toBe(TokenType.STRING);
expect(tokens[0].value).toBe('Тестовая строка с пробелами');
expect(tokens[0]?.type).toBe(TokenType.STRING);
expect(tokens[0]?.value).toBe('Тестовая строка с пробелами');
});
it('should tokenize numbers', () => {
@@ -37,11 +37,11 @@ describe('lexer', () => {
const lexer = new Lexer(source);
const tokens = lexer.tokenize();
expect(tokens[0].type).toBe(TokenType.NUMBER);
expect(tokens[0].value).toBe('42');
expect(tokens[0]?.type).toBe(TokenType.NUMBER);
expect(tokens[0]?.value).toBe('42');
expect(tokens[1].type).toBe(TokenType.NUMBER);
expect(tokens[1].value).toBe('3.14');
expect(tokens[1]?.type).toBe(TokenType.NUMBER);
expect(tokens[1]?.value).toBe('3.14');
});
it('should handle comments', () => {
@@ -49,10 +49,10 @@ describe('lexer', () => {
const lexer = new Lexer(source);
const tokens = lexer.tokenize();
expect(tokens[0].type).toBe(TokenType.COMMENT);
expect(tokens[0].value).toBe('// это комментарий');
expect(tokens[0]?.type).toBe(TokenType.COMMENT);
expect(tokens[0]?.value).toBe('// это комментарий');
expect(tokens[1].type).toBe(TokenType.QUEST);
expect(tokens[1]?.type).toBe(TokenType.QUEST);
});
it('should track line and column numbers', () => {
@@ -60,11 +60,11 @@ describe('lexer', () => {
const lexer = new Lexer(source);
const tokens = lexer.tokenize();
expect(tokens[0].line).toBe(1);
expect(tokens[0].column).toBe(1);
expect(tokens[0]?.line).toBe(1);
expect(tokens[0]?.column).toBe(1);
expect(tokens[1].line).toBe(2);
expect(tokens[1].column).toBe(1);
expect(tokens[1]?.line).toBe(2);
expect(tokens[1]?.column).toBe(1);
});
it('should handle all symbols', () => {
@@ -86,7 +86,7 @@ describe('lexer', () => {
];
expectedTypes.forEach((expectedType, index) => {
expect(tokens[index].type).toBe(expectedType);
expect(tokens[index]?.type).toBe(expectedType);
});
});
+4 -4
View File
@@ -59,10 +59,10 @@ describe('parser', () => {
const nodes = ast.graph.nodes;
expect(Object.keys(nodes)).toHaveLength(4);
expect(nodes.старт.nodeType).toBe('начальный');
expect(nodes.действие1.nodeType).toBe('действие');
expect(nodes.конец1.nodeType).toBe('концовка');
expect(nodes.конец2.nodeType).toBe('концовка');
expect(nodes.старт?.nodeType).toBe('начальный');
expect(nodes.действие1?.nodeType).toBe('действие');
expect(nodes.конец1?.nodeType).toBe('концовка');
expect(nodes.конец2?.nodeType).toBe('концовка');
});
it('should parse action node with options', () => {