@bis-toolkit/cppparser 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +53 -0
- package/dist/RvmatParser.d.ts +43 -0
- package/dist/ast.d.ts +74 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +772 -0
- package/dist/index.js.map +7 -0
- package/dist/lexer.d.ts +23 -0
- package/dist/parser.d.ts +19 -0
- package/dist/preprocessor.d.ts +21 -0
- package/dist/project.d.ts +49 -0
- package/package.json +51 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/lexer.ts", "../src/parser.ts", "../src/preprocessor.ts", "../src/RvmatParser.ts"],
|
|
4
|
+
"sourcesContent": ["export const CfgKeywords = new Set<string>([\n 'class', 'delete', 'enum', 'true', 'false', 'null', 'NULL'\n]);\n\nexport const CfgPunctuations = new Set<string>([\n '{', '}', ';', ':', '=', '[', ']', ',', '+', '-', '*', '/'\n]);\n\nexport const CfgOperators = new Set<string>([\n '+=', '-=', '=', '+', '-', '*', '/'\n]);\n\nexport enum TokenKind {\n Keyword,\n Identifier,\n Number,\n String,\n Punctuation,\n EOF,\n Unknown\n};\n\nexport interface CfgToken {\n kind: TokenKind;\n value: string;\n start: number;\n end: number;\n line: number;\n column: number;\n};\n\nexport const isCfgKeyword = (value: string): boolean => {\n return CfgKeywords.has(value);\n};;\n\nexport const isCfgPunctuation = (value: string): boolean => {\n return CfgPunctuations.has(value);\n};\n\n\nconst operators = Array.from(CfgOperators).sort((a, b) => b.length - a.length);\n\nexport const lex = (input: string): CfgToken[] => {\n const tokens: CfgToken[] = [];\n let i = 0;\n let currentLine = 1;\n let currentColumn = 1;\n\n const push = (kind: TokenKind, value: string, start: number, end: number, tokenLine: number, tokenColumn: number) : void => {\n tokens.push({ kind, value, start, end, line: tokenLine, column: tokenColumn });\n };\n\n const updatePosition = (text: string) : void => {\n for (const char of text) {\n if (char === '\\n') {\n currentLine++;\n currentColumn = 1;\n } else {\n currentColumn++;\n }\n }\n };\n\n while (i < input.length) {\n // Skip whitespace\n while (i < input.length && /\\s/.test(input[i])) {\n updatePosition(input[i]);\n i++;\n }\n if (i >= input.length) {break;}\n\n const start = i;\n const startLine = currentLine;\n const startColumn = currentColumn;\n\n // Skip comments\n if (input[i] === '/' && i + 1 < input.length) {\n if (input[i + 1] === '/') {\n // Single-line comment\n while (i < input.length && input[i] !== '\\n') {\n i++;\n }\n continue;\n } else if (input[i + 1] === '*') {\n // Multi-line comment\n i += 2;\n while (i + 1 < input.length) {\n if (input[i] === '*' && input[i + 1] === '/') {\n i += 2;\n break;\n }\n i++;\n }\n continue;\n }\n }\n\n // Lex operators\n let matched = false;\n for (const op of operators) {\n if (input.startsWith(op, i)) {\n push(TokenKind.Punctuation, op, i, i + op.length, startLine, startColumn);\n updatePosition(op);\n i += op.length;\n matched = true;\n break;\n }\n }\n if (matched) {continue;}\n\n // Lex the next token\n if (/[a-zA-Z_]/.test(input[i])) {\n while (i < input.length && /[a-zA-Z0-9_]/.test(input[i])) {\n i++;\n }\n const value = input.slice(start, i);\n const kind = isCfgKeyword(value) ? TokenKind.Keyword : TokenKind.Identifier;\n push(kind, value, start, i, startLine, startColumn);\n updatePosition(value);\n } else if (/\\d/.test(input[i])) {\n const numStart = i;\n // Handle integer part\n while (i < input.length && /\\d/.test(input[i])) {\n i++;\n }\n\n // Handle optional decimal part\n if (i < input.length && input[i] === '.') {\n i++;\n while (i < input.length && /\\d/.test(input[i])) {\n i++;\n }\n }\n\n // Handle optional scientific notation (e.g., e-4, E+8)\n if (i < input.length && /[eE]/.test(input[i])) {\n const ePos = i;\n i++;\n // Optional sign\n if (i < input.length && /[+-]/.test(input[i])) {\n i++;\n }\n // Check if followed by digits (valid scientific notation)\n if (i < input.length && /\\d/.test(input[i])) {\n // Exponent digits\n while (i < input.length && /\\d/.test(input[i])) {\n i++;\n }\n } else {\n // Not scientific notation, backtrack\n i = ePos;\n }\n }\n\n // Check if it's followed by a letter or underscore (making it an identifier)\n if (i < input.length && /[a-zA-Z_]/.test(input[i])) {\n // It's an identifier that starts with a digit\n while (i < input.length && /[a-zA-Z0-9_]/.test(input[i])) {\n i++;\n }\n const value = input.slice(numStart, i);\n push(TokenKind.Identifier, value, numStart, i, startLine, startColumn);\n updatePosition(value);\n continue;\n }\n\n const value = input.slice(numStart, i);\n push(TokenKind.Number, value, numStart, i, startLine, startColumn);\n updatePosition(value);\n } else if (input[i] === '\"') {\n const stringStart = i;\n i++;\n while (i < input.length) {\n if (input[i] === '\"') {\n // Check if it's an escaped quote (doubled quote)\n if (i + 1 < input.length && input[i + 1] === '\"') {\n i += 2; // Skip both quotes\n continue;\n }\n // End of string\n break;\n }\n i++;\n }\n const value = input.slice(stringStart + 1, i);\n push(TokenKind.String, value, stringStart, i + 1, startLine, startColumn);\n updatePosition(input.slice(stringStart, i + 1));\n i++;\n } else if (isCfgPunctuation(input[i])) {\n push(TokenKind.Punctuation, input[i], start, i + 1, startLine, startColumn);\n updatePosition(input[i]);\n i++;\n } else {\n const unknownStart = i;\n while (i < input.length && !/[a-zA-Z_]/.test(input[i]) && !/\\d/.test(input[i]) && input[i] !== '\"' && !isCfgPunctuation(input[i]) && !/\\s/.test(input[i])) {\n i++;\n }\n const value = input.slice(unknownStart, i);\n push(TokenKind.Unknown, value, unknownStart, i, startLine, startColumn);\n updatePosition(value);\n }\n }\n\n return tokens;\n};\n", "import { lex, CfgToken, TokenKind } from './lexer';\nimport {\n CfgType,\n CfgBaseType,\n CfgDocument,\n CfgSimpleVariable,\n CfgArrayVariable,\n CfgArrayExtend,\n CfgArrayShrink,\n CfgEnum,\n CfgClass,\n CfgPrototype,\n CfgDelete\n} from './ast';\n\nexport class Parser {\n private tokens: CfgToken[];\n private current = 0;\n private filename: string;\n\n constructor(input: string, filename?: string) {\n this.tokens = lex(input);\n this.filename = filename ?? '<unknown>';\n }\n\n private peek(): CfgToken | null {\n return this.current < this.tokens.length ? this.tokens[this.current] : null;\n }\n\n private advance(): CfgToken | null {\n if (this.current < this.tokens.length) {\n return this.tokens[this.current++];\n }\n return null;\n }\n\n private consume(kind: TokenKind, value?: string): CfgToken | null {\n const token = this.peek();\n if (token?.kind !== kind || (value && token.value !== value)) {\n const expected = value ? `'${value}'` : TokenKind[kind];\n const got = token ? `${TokenKind[token.kind]} '${token.value}'` : 'EOF';\n const location = token ? `${this.filename}:${token.line}:${token.column}` : this.filename;\n throw new Error(`${location}: Expected ${expected}, got ${got}`);\n }\n return this.advance();\n }\n\n private isAtEnd(): boolean {\n return this.current >= this.tokens.length;\n }\n\n private parseType(): CfgType {\n const token = this.peek();\n if (!token) {throw new Error(`${this.filename}: Unexpected end of input`);}\n\n // Handle negative numbers\n if (token.kind === TokenKind.Punctuation && (token.value === '-' || token.value === '+')) {\n this.advance();\n const numToken = this.peek();\n if (numToken?.kind === TokenKind.Number) {\n this.advance();\n const value = parseFloat(numToken.value);\n return token.value === '-' ? -value : value;\n }\n throw new Error(`${this.filename}:${token.line}:${token.column}: Expected number after '${token.value}'`);\n }\n\n if (token.kind === TokenKind.Number) {\n this.advance();\n return parseFloat(token.value);\n } else if (token.kind === TokenKind.String) {\n this.advance();\n return token.value;\n } else if (token.kind === TokenKind.Keyword) {\n if (token.value === 'true') {\n this.advance();\n return true;\n } else if (token.value === 'false') {\n this.advance();\n return false;\n } else if (token.value === 'null' || token.value === 'NULL') {\n this.advance();\n return null;\n }\n }\n throw new Error(`${this.filename}:${token.line}:${token.column}: Unexpected token for type: ${TokenKind[token.kind]} '${token.value}'`);\n }\n\n private parseExpression(): CfgType {\n const token = this.peek();\n if (token?.kind === TokenKind.Punctuation && token.value === '{') {\n // Nested array\n this.advance(); // consume '{'\n const elements = this.parseArrayElements();\n this.consume(TokenKind.Punctuation, '}');\n return elements;\n }\n return this.parseType();\n }\n\n private parseArrayElements(): CfgType[] {\n const elements: CfgType[] = [];\n while (!this.isAtEnd()) {\n const token = this.peek();\n if (token?.value === '}') {break;}\n elements.push(this.parseExpression());\n const comma = this.peek();\n if (comma?.value === ',') {\n this.advance();\n } else {\n break;\n }\n }\n return elements;\n }\n\n private parseVariable(): CfgSimpleVariable | CfgArrayVariable | CfgArrayExtend | CfgArrayShrink {\n const name = this.consume(TokenKind.Identifier)?.value;\n if (!name) {\n throw new Error(`${this.filename}: Expected variable name`);\n }\n const next = this.peek();\n if (next?.value === '[') {\n this.consume(TokenKind.Punctuation, '[');\n this.consume(TokenKind.Punctuation, ']');\n const op = this.consume(TokenKind.Punctuation);\n if (!op) {\n throw new Error(`${this.filename}: Unexpected end of input after array variable '${name}'`);\n }\n\n if (op.value !== '=' && op.value !== '+=' && op.value !== '-=') {\n throw new Error(`${this.filename}:${op.line}:${op.column}: Invalid operator for array: '${op.value}'`);\n }\n this.consume(TokenKind.Punctuation, '{');\n const elements = this.parseArrayElements();\n this.consume(TokenKind.Punctuation, '}');\n this.consume(TokenKind.Punctuation, ';');\n if (op.value === '=') {\n return {\n kind: 'array',\n name,\n values: elements\n };\n } else if (op.value === '+=') {\n return {\n kind: 'array-extend',\n name,\n values: elements\n };\n } else { // -=\n return {\n kind: 'array-shrink',\n name,\n values: elements\n };\n }\n } else {\n this.consume(TokenKind.Punctuation, '=');\n const value = this.parseExpression();\n this.consume(TokenKind.Punctuation, ';');\n return {\n kind: 'variable',\n name,\n value\n };\n }\n }\n\n private parseClass(): CfgClass | CfgPrototype {\n this.consume(TokenKind.Keyword, 'class');\n const name = this.consume(TokenKind.Identifier)?.value;\n if (!name) {\n throw new Error(`${this.filename}: Expected class name`);\n }\n let baseClassName: string | undefined;\n const colon = this.peek();\n if (colon?.value === ':') {\n this.advance();\n baseClassName = this.consume(TokenKind.Identifier)?.value;\n }\n const brace = this.peek();\n if (brace?.value === '{') {\n this.advance();\n const properties = new Map<string, CfgBaseType>();\n while (!this.isAtEnd()) {\n const token = this.peek();\n if (!token || token.value === '}') {break;}\n\n // Check if it's a nested class or a variable/delete/enum\n if (token.kind === TokenKind.Keyword && token.value === 'class') {\n const nestedClass = this.parseClass();\n properties.set(nestedClass.name, nestedClass);\n } else if (token.kind === TokenKind.Keyword && token.value === 'delete') {\n const deleteStmt = this.parseDelete();\n properties.set(deleteStmt.name, deleteStmt);\n } else {\n const prop = this.parseVariable();\n properties.set(prop.name, prop);\n }\n }\n this.consume(TokenKind.Punctuation, '}');\n this.consume(TokenKind.Punctuation, ';');\n return {\n kind: 'class',\n name,\n baseClassName,\n properties\n };\n } else {\n this.consume(TokenKind.Punctuation, ';');\n return {\n kind: 'prototype',\n name,\n baseClassName\n };\n }\n }\n\n private parseDelete(): CfgDelete {\n this.consume(TokenKind.Keyword, 'delete');\n const name = this.consume(TokenKind.Identifier)?.value;\n if (!name) {\n throw new Error(`${this.filename}: Expected delete name`);\n }\n this.consume(TokenKind.Punctuation, ';');\n return {\n kind: 'delete',\n name\n };\n }\n\n private parseEnum(): CfgEnum {\n this.consume(TokenKind.Keyword, 'enum');\n this.consume(TokenKind.Punctuation, '{');\n const members: { name: string; value?: number }[] = [];\n let nextValue = 0;\n while (!this.isAtEnd()) {\n const token = this.peek();\n if (token?.value === '}') {break;}\n const memberName = this.consume(TokenKind.Identifier)?.value;\n if (!memberName) {\n throw new Error(`${this.filename}: Expected enum member name`);\n }\n let value: number | undefined;\n const eq = this.peek();\n if (eq?.value === '=') {\n this.advance();\n const numToken = this.consume(TokenKind.Number);\n if (!numToken) {\n throw new Error(`${this.filename}: Expected number for enum member value`);\n }\n value = parseFloat(numToken.value);\n nextValue = value + 1;\n } else {\n value = nextValue++;\n }\n members.push({ name: memberName, value });\n const comma = this.peek();\n if (comma?.value === ',') {\n this.advance();\n } else {\n break;\n }\n }\n this.consume(TokenKind.Punctuation, '}');\n this.consume(TokenKind.Punctuation, ';');\n return {\n kind: 'enum',\n members\n };\n }\n\n public parse(): CfgDocument {\n const statements: CfgBaseType[] = [];\n while (!this.isAtEnd()) {\n const token = this.peek();\n if (!token) {break;}\n if (token.kind === TokenKind.Identifier) {\n statements.push(this.parseVariable());\n } else if (token.kind === TokenKind.Keyword && token.value === 'class') {\n statements.push(this.parseClass());\n } else if (token.kind === TokenKind.Keyword && token.value === 'delete') {\n statements.push(this.parseDelete());\n } else if (token.kind === TokenKind.Keyword && token.value === 'enum') {\n statements.push(this.parseEnum());\n } else {\n const token = this.peek();\n if (token) {\n throw new Error(`${this.filename}:${token.line}:${token.column}: Unexpected token: ${TokenKind[token.kind]} '${token.value}'`);\n } else {\n throw new Error(`${this.filename}: Unexpected end of input`);\n }\n }\n }\n return {\n kind: 'document',\n statements\n };\n }\n}\n", "/**\n * Basic C-style preprocessor for CFG files\n * Handles #define, #ifdef, #ifndef, #else, #endif, #include\n * Complex macros currently not supported\n */\n\n// Conditional imports for Node.js modules (browser compatibility)\nlet readFileSync: typeof import('fs').readFileSync | undefined;\nlet resolve: typeof import('path').resolve | undefined;\n\n// Try to load Node.js modules - will fail silently in browser\nif (typeof process !== 'undefined' && process.versions?.node) {\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports\n const fs = require('fs');\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports\n const path = require('path');\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n readFileSync = fs.readFileSync;\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access\n resolve = path.resolve;\n } catch {\n // Running in browser or bundled environment\n }\n}\n\nexport interface PreprocessorOptions {\n defines?: Map<string, string>;\n includePaths?: string[];\n}\n\nexport class Preprocessor {\n private defines: Map<string, string>;\n private conditionStack: boolean[];\n private skipLines: boolean;\n private processedFiles: Set<string>;\n private includePaths: string[];\n\n constructor(options: PreprocessorOptions = {}) {\n this.defines = new Map(options.defines ?? []);\n this.conditionStack = [];\n this.skipLines = false;\n this.processedFiles = new Set();\n this.includePaths = options.includePaths ?? [];\n }\n\n public preprocess(filePath: string): string {\n if (!readFileSync) {\n throw new Error('Preprocessor.preprocess() requires Node.js file system access');\n }\n const input = readFileSync(filePath, 'utf8');\n const lines = input.split('\\n');\n const output: string[] = [];\n\n for (const rawLine of lines) {\n const line = rawLine.trim();\n if (line.startsWith('#')) {\n const directive = this.parseDirective(line);\n if (!directive) {\n // Invalid directive, treat as comment\n continue;\n }\n\n this.processDirective(directive, output, filePath);\n } else {\n if (!this.skipLines) {\n // Apply defines\n let processedLine = line;\n for (const [key, value] of this.defines) {\n processedLine = processedLine.replace(new RegExp(`\\\\b${key}\\\\b`, 'g'), value);\n }\n output.push(processedLine);\n }\n }\n }\n\n return output.join('\\n');\n }\n\n private processDirective(directive: Directive, output: string[], currentFile: string): void {\n switch (directive.type) {\n case 'define':\n if (!this.skipLines) {\n this.defines.set(directive.name!, directive.value ?? '');\n }\n break;\n case 'undef':\n if (!this.skipLines) {\n this.defines.delete(directive.name!);\n }\n break;\n case 'ifdef':\n this.conditionStack.push(this.skipLines);\n this.skipLines = this.skipLines || !this.defines.has(directive.name!);\n break;\n\n case 'ifndef':\n this.conditionStack.push(this.skipLines);\n this.skipLines = this.skipLines || this.defines.has(directive.name!);\n break;\n\n case 'else':\n if (this.conditionStack.length > 0) {\n this.skipLines = !this.skipLines;\n }\n break;\n\n case 'endif':\n if (this.conditionStack.length > 0) {\n this.skipLines = this.conditionStack.pop()!;\n }\n break;\n\n case 'include':\n if (!this.skipLines && directive.file) {\n if (!resolve) {\n console.warn('#include directive ignored in browser environment');\n break;\n }\n const fullPath = currentFile ? resolve(currentFile, '..', directive.file) : directive.file;\n if (this.processedFiles.has(fullPath)) {\n console.warn(`Recursive include detected for ${directive.file}, skipping`);\n } else {\n try {\n this.processedFiles.add(fullPath);\n const includedContent = this.loadAndPreprocessFile(directive.file, currentFile);\n output.push(includedContent);\n } catch (error) {\n // For now, ignore include errors\n console.error(`Failed to include ${directive.file}: `, error);\n }\n }\n }\n break;\n\n default:\n // Unknown directive, skip\n break;\n }\n }\n\n private parseDirective(line: string): Directive | null {\n const parts = line.split(/\\s+/);\n if (parts.length === 0) { return null; }\n\n const type = parts[0].substring(1); // Remove #\n\n switch (type) {\n case 'define':\n if (parts.length >= 2) {\n const name = parts[1];\n const value = parts.slice(2).join(' ');\n return { type: 'define', name, value };\n }\n break;\n case 'undef':\n if (parts.length >= 2) {\n return { type: 'undef', name: parts[1] };\n }\n break;\n case 'ifdef':\n case 'ifndef':\n if (parts.length >= 2) {\n return { type, name: parts[1] };\n }\n break;\n\n case 'else':\n return { type: 'else' };\n\n case 'endif':\n return { type: 'endif' };\n\n case 'include':\n // Parse #include \"file\" or #include <file>\n const includeMatch = /^#include\\s+[\"<]([^\">]+)[\">]$/.exec(line);\n if (includeMatch) {\n const file = includeMatch[1];\n const isQuoted = line.includes('\"');\n if (isQuoted) {\n return { type: 'include', file };\n }\n // Skip angle bracket includes\n }\n break;\n }\n\n return null;\n }\n\n private loadAndPreprocessFile(includePath: string, currentFile: string): string {\n if (!resolve || !readFileSync) {\n throw new Error('#include requires Node.js file system access');\n }\n let fullPath: string;\n\n if (currentFile) {\n // Resolve relative to current file\n fullPath = resolve(currentFile, '..', includePath);\n } else {\n // Use include paths or current directory\n fullPath = includePath;\n for (const includePath of this.includePaths) {\n const candidate = resolve(includePath, includePath);\n try {\n readFileSync(candidate, 'utf8');\n fullPath = candidate;\n break;\n } catch {\n // Continue\n }\n }\n }\n\n return this.preprocess(fullPath);\n }\n}\n\ninterface Directive {\n type: 'define' | 'undef' | 'ifdef' | 'ifndef' | 'else' | 'endif' | 'include';\n name?: string;\n value?: string;\n file?: string;\n}\n", "\n/**\n * Simple RVMAT (material) file parser\n * Extracts texture paths from Stage definitions\n */\n\nimport { CfgArrayVariable, CfgBaseType, CfgClass, CfgDocument, CfgSimpleVariable, CfgType } from \"./ast\";\nimport { Parser } from \"./parser\";\n\nexport interface RvmatStage {\n name: string;\n texture: string;\n}\n\nexport interface RvmatData {\n stages: RvmatStage[];\n ambient?: number[];\n diffuse?: number[];\n forcedDiffuse?: number[];\n emmisive?: number[];\n specular?: number[];\n specularPower?: number;\n pixelShaderID?: string;\n vertexShaderID?: string;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-extraneous-class\nexport class RvmatParser {\n /**\n * Parse RVMAT file content\n */\n static parse(content: string, filename = '<rvmat>'): RvmatData {\n const parser = new Parser(content, filename);\n const document = parser.parse();\n const data: RvmatData = { stages: [] };\n\n data.ambient = this.readNumberArray(this.findVariable(document, 'ambient'));\n data.diffuse = this.readNumberArray(this.findVariable(document, 'diffuse'));\n data.forcedDiffuse = this.readNumberArray(this.findVariable(document, 'forcedDiffuse'));\n data.emmisive = this.readNumberArray(this.findVariable(document, 'emmisive'));\n data.specular = this.readNumberArray(this.findVariable(document, 'specular'));\n data.specularPower = this.readNumber(this.findVariable(document, 'specularPower'));\n data.pixelShaderID = this.readString(this.findVariable(document, 'PixelShaderID'));\n data.vertexShaderID = this.readString(this.findVariable(document, 'VertexShaderID'));\n\n this.extractStages(document, data);\n\n return data;\n }\n\n private static findVariable(document: CfgDocument, name: string): CfgSimpleVariable | CfgArrayVariable | undefined {\n const target = name.toLowerCase();\n for (let i = document.statements.length - 1; i >= 0; i--) {\n const statement = document.statements[i];\n if (this.isVariable(statement) && statement.name.toLowerCase() === target) {\n return statement;\n }\n }\n return undefined;\n }\n\n private static extractStages(document: CfgDocument, data: RvmatData): void {\n const collectFromClass = (cls: CfgClass): void => {\n if (/^stage\\d+$/i.test(cls.name)) {\n const textureProp = this.findClassProperty(cls, 'texture');\n if (textureProp && this.isSimpleVariable(textureProp)) {\n const texture = this.readString(textureProp);\n // Include both file paths and procedural textures (starting with #)\n if (texture && texture.trim() !== '') {\n data.stages.push({ name: cls.name, texture });\n }\n }\n }\n\n for (const property of cls.properties.values()) {\n if (this.isClass(property)) {\n collectFromClass(property);\n }\n }\n };\n\n for (const statement of document.statements) {\n if (this.isClass(statement)) {\n collectFromClass(statement);\n }\n }\n }\n\n private static findClassProperty(cls: CfgClass, propertyName: string): CfgBaseType | undefined {\n const target = propertyName.toLowerCase();\n let match: CfgBaseType | undefined;\n for (const [name, property] of cls.properties) {\n if (name.toLowerCase() === target) {\n match = property;\n }\n }\n return match;\n }\n\n private static readNumberArray(node?: CfgSimpleVariable | CfgArrayVariable): number[] | undefined {\n if (!node) { return undefined; }\n const raw = node.kind === 'array' ? node.values : node.value;\n if (!Array.isArray(raw)) { return undefined; }\n\n const numbers = raw\n .map(value => this.toNumber(value))\n .filter((value): value is number => value !== undefined);\n\n return numbers.length > 0 ? numbers : undefined;\n }\n\n private static readNumber(node?: CfgSimpleVariable | CfgArrayVariable): number | undefined {\n if (!node) { return undefined; }\n if (node.kind === 'variable') {\n return this.toNumber(node.value);\n }\n return node.values.length === 1 ? this.toNumber(node.values[0]) : undefined;\n }\n\n private static readString(node?: CfgSimpleVariable | CfgArrayVariable): string | undefined {\n if (!node || !this.isSimpleVariable(node)) { return undefined; }\n const value = node.value;\n return typeof value === 'string' ? value : undefined;\n }\n\n private static toNumber(value: CfgType): number | undefined {\n if (typeof value === 'number') { return value; }\n if (typeof value === 'string') {\n const parsed = parseFloat(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n }\n return undefined;\n }\n\n private static isVariable(node: CfgBaseType): node is CfgSimpleVariable | CfgArrayVariable {\n return node.kind === 'variable' || node.kind === 'array';\n }\n\n private static isSimpleVariable(node: CfgBaseType): node is CfgSimpleVariable {\n return node.kind === 'variable';\n }\n\n private static isClass(node: CfgBaseType): node is CfgClass {\n return node.kind === 'class';\n }\n\n /**\n * Get all texture paths from parsed data\n */\n static getTexturePaths(data: RvmatData): string[] {\n return data.stages.map(stage => stage.texture);\n }\n\n /**\n * Get main diffuse/color texture (typically Stage1)\n */\n static getMainTexture(data: RvmatData): string | undefined {\n return data.stages.find(s => s.name === 'Stage1')?.texture;\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["TokenKind", "value", "token", "includePath"]
|
|
7
|
+
}
|
package/dist/lexer.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const CfgKeywords: Set<string>;
|
|
2
|
+
export declare const CfgPunctuations: Set<string>;
|
|
3
|
+
export declare const CfgOperators: Set<string>;
|
|
4
|
+
export declare enum TokenKind {
|
|
5
|
+
Keyword = 0,
|
|
6
|
+
Identifier = 1,
|
|
7
|
+
Number = 2,
|
|
8
|
+
String = 3,
|
|
9
|
+
Punctuation = 4,
|
|
10
|
+
EOF = 5,
|
|
11
|
+
Unknown = 6
|
|
12
|
+
}
|
|
13
|
+
export interface CfgToken {
|
|
14
|
+
kind: TokenKind;
|
|
15
|
+
value: string;
|
|
16
|
+
start: number;
|
|
17
|
+
end: number;
|
|
18
|
+
line: number;
|
|
19
|
+
column: number;
|
|
20
|
+
}
|
|
21
|
+
export declare const isCfgKeyword: (value: string) => boolean;
|
|
22
|
+
export declare const isCfgPunctuation: (value: string) => boolean;
|
|
23
|
+
export declare const lex: (input: string) => CfgToken[];
|
package/dist/parser.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CfgDocument } from './ast';
|
|
2
|
+
export declare class Parser {
|
|
3
|
+
private tokens;
|
|
4
|
+
private current;
|
|
5
|
+
private filename;
|
|
6
|
+
constructor(input: string, filename?: string);
|
|
7
|
+
private peek;
|
|
8
|
+
private advance;
|
|
9
|
+
private consume;
|
|
10
|
+
private isAtEnd;
|
|
11
|
+
private parseType;
|
|
12
|
+
private parseExpression;
|
|
13
|
+
private parseArrayElements;
|
|
14
|
+
private parseVariable;
|
|
15
|
+
private parseClass;
|
|
16
|
+
private parseDelete;
|
|
17
|
+
private parseEnum;
|
|
18
|
+
parse(): CfgDocument;
|
|
19
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic C-style preprocessor for CFG files
|
|
3
|
+
* Handles #define, #ifdef, #ifndef, #else, #endif, #include
|
|
4
|
+
* Complex macros currently not supported
|
|
5
|
+
*/
|
|
6
|
+
export interface PreprocessorOptions {
|
|
7
|
+
defines?: Map<string, string>;
|
|
8
|
+
includePaths?: string[];
|
|
9
|
+
}
|
|
10
|
+
export declare class Preprocessor {
|
|
11
|
+
private defines;
|
|
12
|
+
private conditionStack;
|
|
13
|
+
private skipLines;
|
|
14
|
+
private processedFiles;
|
|
15
|
+
private includePaths;
|
|
16
|
+
constructor(options?: PreprocessorOptions);
|
|
17
|
+
preprocess(filePath: string): string;
|
|
18
|
+
private processDirective;
|
|
19
|
+
private parseDirective;
|
|
20
|
+
private loadAndPreprocessFile;
|
|
21
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for project file (config.cpp) parsing and management
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Represents a patch configuration class
|
|
6
|
+
*/
|
|
7
|
+
export interface CfgPatch {
|
|
8
|
+
requiredAddons: string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Represents a script module definition
|
|
12
|
+
*/
|
|
13
|
+
export interface ScriptModule {
|
|
14
|
+
name: string;
|
|
15
|
+
value: string;
|
|
16
|
+
files: string[];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Represents a mod definition in CfgMods
|
|
20
|
+
*/
|
|
21
|
+
export interface CfgMod {
|
|
22
|
+
dir: string;
|
|
23
|
+
type: string;
|
|
24
|
+
action?: string;
|
|
25
|
+
hideName?: boolean;
|
|
26
|
+
hidePicture?: boolean;
|
|
27
|
+
name: string;
|
|
28
|
+
overview?: string;
|
|
29
|
+
credits?: string;
|
|
30
|
+
author?: string;
|
|
31
|
+
authorID?: string;
|
|
32
|
+
version?: string;
|
|
33
|
+
extra?: number;
|
|
34
|
+
scriptModules: Map<string, ScriptModule>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Represents the CfgMods configuration
|
|
38
|
+
*/
|
|
39
|
+
export interface CfgMods {
|
|
40
|
+
mods: Map<string, CfgMod>;
|
|
41
|
+
}
|
|
42
|
+
export type CfgPatches = Map<string, CfgPatch>;
|
|
43
|
+
/**
|
|
44
|
+
* Represents the entire project file structure
|
|
45
|
+
*/
|
|
46
|
+
export interface ProjectFile {
|
|
47
|
+
cfgPatches: CfgPatches;
|
|
48
|
+
cfgMods: CfgMods;
|
|
49
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bis-toolkit/cppparser",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Arma/DayZ config parser",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "npm run build:types && npm run build:bundle",
|
|
25
|
+
"build:types": "tsc --declaration --emitDeclarationOnly --outDir dist",
|
|
26
|
+
"build:bundle": "node esbuild.config.js",
|
|
27
|
+
"prepublishOnly": "npm run build",
|
|
28
|
+
"watch": "tsc --watch",
|
|
29
|
+
"lint": "eslint",
|
|
30
|
+
"lint:fix": "eslint --fix"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"rap",
|
|
34
|
+
"cfg",
|
|
35
|
+
"config.cpp",
|
|
36
|
+
"arma",
|
|
37
|
+
"dayz"
|
|
38
|
+
],
|
|
39
|
+
"author": "Alpine Labs",
|
|
40
|
+
"license": "GPL-3.0-or-later",
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^25.0.3",
|
|
43
|
+
"@typescript-eslint/eslint-plugin": "^8.52.0",
|
|
44
|
+
"@typescript-eslint/parser": "^8.52.0",
|
|
45
|
+
"esbuild": "^0.27.2",
|
|
46
|
+
"eslint": "^9.39.2",
|
|
47
|
+
"typescript": "^5.9.3",
|
|
48
|
+
"typescript-eslint": "^8.52.0"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {}
|
|
51
|
+
}
|