UNPKG

@maniascript/parser

Version:
1,296 lines 96.8 kB
// Loosely follow the estree syntax import {} from 'antlr4ng'; import { ProgramContext, ProgramContentContext, RequireContextDirectiveContext, ExtendsDirectiveContext, IncludeDirectiveContext, SettingDirectiveContext, CommandDirectiveContext, StructDirectiveContext, StructDeclarationContext, StructMemberContext, StructAliasingContext, ConstDirectiveContext, ConstDeclarationContext, ConstAliasingContext, TypeContext, InitializerTypeContext, BaseTypeContext, ArrayTypeContext, SimpleTypeContext, EnumTypeContext, CustomTypeContext, TextLiteralContext, LiteralContext, TextContext, IntegerContext, RealContext, BooleanContext, NullContext, NullIdContext, EnumContext, ExpressionContext, VectorContext, ArrayContext, ArrayExpressionContext, StructureContext, StructureMemberInitializationContext, FunctionCallExpressionContext, FunctionCallContext, LiteralExpressionContext, FunctionDeclarationContext, LabelDeclarationContext, StorageSpecifierContext, BlockContext, ParameterContext, StatementContext, MainStatementContext, ExpressionStatementContext, AsExpressionContext, IsExpressionContext, DotAccessExpressionContext, IndexAccessExpressionContext, UnaryMinusExpressionContext, NotExpressionContext, MultiplicativeExpressionContext, AdditiveExpressionContext, ConcatenationExpressionContext, RelationalExpressionContext, EqualityExpressionContext, OrExpressionContext, AndExpressionContext, TextInterpolationExpressionContext, DumptypeExpressionContext, DumpExpressionContext, CastExpressionContext, IdentifierExpressionContext, VectorExpressionContext, ThisExpressionContext, NowExpressionContext, ParenthesisExpressionContext, AssignmentStatementContext, ManiaScriptParser, ReturnStatementContext, LabelStatementContext, AssertStatementContext, ForeachStatementContext, ForStatementContext, WhileStatementContext, MeanwhileStatementContext, BreakStatementContext, ContinueStatementContext, SwitchStatementContext, SwitchCaseContext, SwitchDefaultContext, SwitchtypeStatementContext, SwitchtypeCaseContext, SwitchtypeDefaultContext, ConditionalStatementContext, IfBranchContext, ElseIfBranchContext, ElseBranchContext, LogStatementContext, SleepStatementContext, TuningstartStatementContext, TuningendStatementContext, TuningmarkStatementContext, WaitStatementContext, YieldStatementContext, StructureExpressionContext, VariableDeclarationWithTypeContext, VariableDeclarationWithoutTypeContext, VariableDeclarationLetContext } from '../antlr/ManiaScriptParser.js'; import { SourceLocationRange } from './position.js'; var Kind; (function (Kind) { Kind["Program"] = "Program"; Kind["SimpleType"] = "SimpleType"; Kind["ClassType"] = "ClassType"; Kind["EnumType"] = "EnumType"; Kind["CustomType"] = "CustomType"; Kind["InvalidType"] = "InvalidType"; Kind["ArrayType"] = "ArrayType"; Kind["InvalidLiteral"] = "InvalidLiteral"; Kind["TextLiteral"] = "TextLiteral"; Kind["IntegerLiteral"] = "IntegerLiteral"; Kind["RealLiteral"] = "RealLiteral"; Kind["BooleanLiteral"] = "BooleanLiteral"; Kind["NullLiteral"] = "NullLiteral"; Kind["NullIdLiteral"] = "NullIdLiteral"; Kind["EnumLiteral"] = "EnumLiteral"; Kind["Identifier"] = "Identifier"; Kind["InvalidIdentifier"] = "InvalidIdentifier"; Kind["RequireContextDirective"] = "RequireContextDirective"; Kind["InvalidDirective"] = "InvalidDirective"; Kind["ExtendsDirective"] = "ExtendsDirective"; Kind["IncludeDirective"] = "IncludeDirective"; Kind["InvalidSettingValue"] = "InvalidSettingValue"; Kind["SettingDirective"] = "SettingDirective"; Kind["CommandDirective"] = "CommandDirective"; Kind["StructMemberDeclaration"] = "StructMemberDeclaration"; Kind["StructDeclaration"] = "StructDeclaration"; Kind["StructAliasing"] = "StructAliasing"; Kind["StructDirective"] = "StructDirective"; Kind["InvalidConstValue"] = "InvalidConstValue"; Kind["ConstDeclaration"] = "ConstDeclaration"; Kind["ConstAliasing"] = "ConstAliasing"; Kind["ConstDirective"] = "ConstDirective"; Kind["InvalidDeclaration"] = "InvalidDeclaration"; Kind["VariableDeclaration"] = "VariableDeclaration"; Kind["FunctionParameterDeclaration"] = "FunctionParameterDeclaration"; Kind["FunctionDeclaration"] = "FunctionDeclaration"; Kind["LabelDeclaration"] = "LabelDeclaration"; Kind["BlockStatement"] = "BlockStatement"; Kind["InvalidStatement"] = "InvalidStatement"; Kind["ExpressionStatement"] = "ExpressionStatement"; Kind["InvalidExpression"] = "InvalidExpression"; Kind["VectorExpression"] = "VectorExpression"; Kind["ArrayExpression"] = "ArrayExpression"; Kind["StructMemberExpression"] = "StructMemberExpression"; Kind["StructExpression"] = "StructExpression"; Kind["FunctionCallExpression"] = "FunctionCallExpression"; Kind["AsExpression"] = "AsExpression"; Kind["IsExpression"] = "IsExpression"; Kind["DotAccessExpression"] = "DotAccessExpression"; Kind["IndexAccessExpression"] = "IndexAccessExpression"; Kind["UnaryExpression"] = "UnaryExpression"; Kind["BinaryExpression"] = "BinaryExpression"; Kind["LogicalExpression"] = "LogicalExpression"; Kind["TemplateTextLiteral"] = "TemplateTextLiteral"; Kind["TemplateTextElement"] = "TemplateTextElement"; Kind["DumptypeExpression"] = "DumptypeExpression"; Kind["DumpExpression"] = "DumpExpression"; Kind["CastExpression"] = "CastExpression"; Kind["ThisExpression"] = "ThisExpression"; Kind["NowExpression"] = "NowExpression"; Kind["AssignmentStatement"] = "AssignmentStatement"; Kind["ReturnStatement"] = "ReturnStatement"; Kind["LabelStatement"] = "LabelStatement"; Kind["AssertStatement"] = "AssertStatement"; Kind["ForeachStatement"] = "ForeachStatement"; Kind["ForStatement"] = "ForStatement"; Kind["WhileStatement"] = "WhileStatement"; Kind["MeanwhileStatement"] = "MeanwhileStatement"; Kind["BreakStatement"] = "BreakStatement"; Kind["ContinueStatement"] = "ContinueStatement"; Kind["SwitchStatement"] = "SwitchStatement"; Kind["SwitchCase"] = "SwitchCase"; Kind["SwitchtypeStatement"] = "SwitchtypeStatement"; Kind["SwitchtypeCase"] = "SwitchtypeCase"; Kind["ConditionalStatement"] = "ConditionalStatement"; Kind["ConditionalBranch"] = "ConditionalBranch"; Kind["LogStatement"] = "LogStatement"; Kind["SleepStatement"] = "SleepStatement"; Kind["TuningstartStatement"] = "TuningstartStatement"; Kind["TuningendStatement"] = "TuningendStatement"; Kind["TuningmarkStatement"] = "TuningmarkStatement"; Kind["WaitStatement"] = "WaitStatement"; Kind["YieldStatement"] = "YieldStatement"; Kind["Main"] = "Main"; })(Kind || (Kind = {})); function isNullish(value) { return value === undefined || value === null; } class ASTBuildError extends Error { } class Node { source; parent; constructor(parent, start, stop) { if (start === null) { throw new ASTBuildError('Failed to build node. Missing start token'); } else { this.source = new SourceLocationRange(start, stop); } this.parent = parent; } enter(enterCb) { if (enterCb !== null) enterCb(this); } exit(exitCb) { if (exitCb !== null) exitCb(this); } visit(enterCb, exitCb) { this.enter(enterCb); this.exit(exitCb); } } class Program extends Node { kind = Kind.Program; directives; declarations; main; constructor(program) { super(undefined, program.start, program.stop); this.directives = []; this.declarations = []; } visit(enterCb, exitCb) { this.enter(enterCb); for (const directives of this.directives) { directives.visit(enterCb, exitCb); } for (const declaration of this.declarations) { declaration.visit(enterCb, exitCb); } this.main?.visit(enterCb, exitCb); this.exit(exitCb); } } var TypeName; (function (TypeName) { TypeName["Boolean"] = "Boolean"; TypeName["Ident"] = "Ident"; TypeName["Int2"] = "Int2"; TypeName["Int3"] = "Int3"; TypeName["Integer"] = "Integer"; TypeName["Real"] = "Real"; TypeName["Text"] = "Text"; TypeName["Vec2"] = "Vec2"; TypeName["Vec3"] = "Vec3"; TypeName["Void"] = "Void"; TypeName["Invalid"] = "Invalid"; })(TypeName || (TypeName = {})); function isBaseType(node) { return (node.kind === Kind.SimpleType || node.kind === Kind.ClassType || node.kind === Kind.EnumType || node.kind === Kind.CustomType); } function isInitializerType(node) { return (node.kind === Kind.ArrayType || node.kind === Kind.SimpleType || node.kind === Kind.ClassType); } function isType(node) { return (node.kind === Kind.ArrayType || isBaseType(node)); } class SimpleType extends Node { kind = Kind.SimpleType; name; constructor(parent, simpleType) { super(parent, simpleType.start, simpleType.stop); if (simpleType.TYPE_BOOLEAN() !== null) { this.name = TypeName.Boolean; } else if (simpleType.TYPE_IDENT() !== null) { this.name = TypeName.Ident; } else if (simpleType.TYPE_INT2() !== null) { this.name = TypeName.Int2; } else if (simpleType.TYPE_INT3() !== null) { this.name = TypeName.Int3; } else if (simpleType.TYPE_INTEGER() !== null) { this.name = TypeName.Integer; } else if (simpleType.TYPE_REAL() !== null) { this.name = TypeName.Real; } else if (simpleType.TYPE_TEXT() !== null) { this.name = TypeName.Text; } else if (simpleType.TYPE_VEC2() !== null) { this.name = TypeName.Vec2; } else if (simpleType.TYPE_VEC3() !== null) { this.name = TypeName.Vec3; } else if (simpleType.TYPE_VOID() !== null) { this.name = TypeName.Void; } else { this.name = TypeName.Invalid; } } } class ClassType extends Node { kind = Kind.ClassType; name; constructor(parent, className) { super(parent, className); this.name = className.text ?? ''; } } class EnumType extends Node { kind = Kind.EnumType; class; name; constructor(parent, enumType) { super(parent, enumType.start, enumType.stop); const classToken = enumType.className()?.CLASS().symbol; if (classToken !== undefined) { this.class = new ClassType(this, classToken); } this.name = new Identifier(this, enumType.enumName().IDENTIFIER().symbol); } visit(enterCb, exitCb) { this.enter(enterCb); this.class?.visit(enterCb, exitCb); this.name.visit(enterCb, exitCb); this.exit(exitCb); } } class CustomType extends Node { kind = Kind.CustomType; name; constructor(parent, customType) { super(parent, customType.start, customType.stop); this.name = new Identifier(this, customType.structName().IDENTIFIER().symbol, customType.namespaceName()?.IDENTIFIER().symbol); } visit(enterCb, exitCb) { this.enter(enterCb); this.name.visit(enterCb, exitCb); this.exit(exitCb); } } class InvalidType extends Node { kind = Kind.InvalidType; error; constructor(parent, start, stop, error) { super(parent, start, stop); if (error instanceof Error) { this.error = error; } else { this.error = null; } } } class ArrayType extends Node { kind = Kind.ArrayType; value; keys; constructor(parent, arrayType) { super(parent, arrayType.start, arrayType.stop); this.value = createBaseTypeNode(this, arrayType.baseType()); this.keys = []; for (const keyType of arrayType.arrayTypeDimension()) { const baseType = keyType.baseType(); if (baseType !== null) { this.keys.push(createBaseTypeNode(this, baseType)); } else { this.keys.push('EmptyKey'); } } } visit(enterCb, exitCb) { this.enter(enterCb); this.value.visit(enterCb, exitCb); for (const key of this.keys) { if (key !== 'EmptyKey') { key.visit(enterCb, exitCb); } } this.exit(exitCb); } } function createBaseTypeNode(parent, baseType) { try { const simpleType = baseType.simpleType(); const classType = baseType.className(); const enumType = baseType.enumType(); const customType = baseType.customType(); if (simpleType != null) { return new SimpleType(parent, simpleType); } else if (classType !== null) { return new ClassType(parent, classType.CLASS().symbol); } else if (enumType !== null) { return new EnumType(parent, enumType); } else if (customType !== null) { return new CustomType(parent, customType); } else { return new InvalidType(parent, baseType.start, baseType.stop); } } catch (error) { if (error instanceof Error) { return new InvalidType(parent, baseType.start, baseType.stop, error); } else { return new InvalidType(parent, baseType.start, baseType.stop, new ASTBuildError('Failed to build `BaseType` node. Something went wrong while reading `BaseTypeContext`.')); } } } function createInitializerTypeNode(parent, type) { try { const arrayType = type.arrayType(); const simpleType = type.simpleType(); const classType = type.className(); if (arrayType !== null) { return new ArrayType(parent, arrayType); } else if (simpleType !== null) { return new SimpleType(parent, simpleType); } else if (classType !== null) { return new ClassType(parent, classType.CLASS().symbol); } else { return new InvalidType(parent, type.start, type.stop); } } catch (error) { if (error instanceof Error) { return new InvalidType(parent, type.start, type.stop, error); } else { return new InvalidType(parent, type.start, type.stop, new ASTBuildError('Failed to build `InitializerType` node. Something went wrong while reading `BaseTypeContext`.')); } } } function createTypeNode(parent, type) { try { const arrayType = type.arrayType(); const baseType = type.baseType(); if (arrayType !== null) { return new ArrayType(parent, arrayType); } else if (baseType !== null) { return createBaseTypeNode(parent, baseType); } else { return new InvalidType(parent, type.start, type.stop); } } catch (error) { if (error instanceof Error) { return new InvalidType(parent, type.start, type.stop, error); } else { return new InvalidType(parent, type.start, type.stop, new ASTBuildError('Failed to build `Type` node. Something went wrong while reading `TypeContext`.')); } } } function isLiteral(node) { return (node.kind === Kind.TextLiteral || node.kind === Kind.IntegerLiteral || node.kind === Kind.RealLiteral || node.kind === Kind.BooleanLiteral || node.kind === Kind.NullLiteral || node.kind === Kind.NullIdLiteral || node.kind === Kind.EnumLiteral); } class InvalidLiteral extends Node { kind = Kind.InvalidLiteral; error; constructor(parent, start, stop, error) { super(parent, start, stop); if (error instanceof Error) { this.error = error; } else { this.error = null; } } } class TextLiteral extends Node { kind = Kind.TextLiteral; isTranslated; isMultiline; value; raw; constructor(parent, textLiteral) { super(parent, textLiteral.start, textLiteral.stop); this.isMultiline = false; this.value = ''; this.raw = ''; const textTranslatedLiteral = textLiteral.textTranslatedLiteral(); this.isTranslated = textTranslatedLiteral !== null; let textBaseLiteral = textLiteral.textBaseLiteral(); if (textTranslatedLiteral !== null) { textBaseLiteral = textTranslatedLiteral.textBaseLiteral(); this.raw = textTranslatedLiteral.getText(); } if (textBaseLiteral !== null) { const textSingleQuoteLiteral = textBaseLiteral.textSingleQuoteLiteral(); const textTripleQuoteLiteral = textBaseLiteral.textTripleQuoteLiteral(); if (textSingleQuoteLiteral !== null) { this.value = textSingleQuoteLiteral.getText().slice(textSingleQuoteLiteral.OPERATOR_OPEN_TEXT_SINGLE().getText().length, -textSingleQuoteLiteral.OPERATOR_CLOSE_TEXT_SINGLE().getText().length); if (this.raw === '') this.raw = textSingleQuoteLiteral.getText(); } else if (textTripleQuoteLiteral !== null) { this.isMultiline = true; this.value = textTripleQuoteLiteral.getText().slice(textTripleQuoteLiteral.OPERATOR_OPEN_TEXT_TRIPLE().getText().length, -textTripleQuoteLiteral.OPERATOR_CLOSE_TEXT_TRIPLE().getText().length); if (this.raw === '') this.raw = textTripleQuoteLiteral.getText(); } } } } class IntegerLiteral extends Node { kind = Kind.IntegerLiteral; value; raw; constructor(parent, integerLiteral) { super(parent, integerLiteral.start, integerLiteral.stop); this.raw = integerLiteral.LITERAL_INTEGER().getText(); if (integerLiteral.OPERATOR_MINUS() !== null) { this.raw = `-${this.raw}`; } this.value = Number(this.raw); } } class RealLiteral extends Node { kind = Kind.RealLiteral; value; raw; constructor(parent, realLiteral) { super(parent, realLiteral.start, realLiteral.stop); this.raw = realLiteral.LITERAL_REAL().getText(); if (realLiteral.OPERATOR_MINUS() !== null) { this.raw = `-${this.raw}`; } this.value = Number(this.raw); } } class BooleanLiteral extends Node { kind = Kind.BooleanLiteral; value; constructor(parent, booleanLiteral) { super(parent, booleanLiteral.start, booleanLiteral.stop); if (booleanLiteral.LITERAL_BOOLEAN().getText() === 'True') { this.value = true; } else { this.value = false; } } } class NullLiteral extends Node { kind = Kind.NullLiteral; constructor(parent, nullLiteral) { super(parent, nullLiteral.start, nullLiteral.stop); } } class NullIdLiteral extends Node { kind = Kind.NullIdLiteral; constructor(parent, nullIdLiteral) { super(parent, nullIdLiteral.start, nullIdLiteral.stop); } } class EnumLiteral extends Node { kind = Kind.EnumLiteral; class; name; value; constructor(parent, enumLiteral) { super(parent, enumLiteral.start, enumLiteral.stop); const name = enumLiteral.enumLiteral().enumName().IDENTIFIER().symbol; const value = enumLiteral.enumLiteral().enumValue().IDENTIFIER().symbol; const classClass = enumLiteral.enumLiteral().className()?.CLASS().symbol; const classLib = enumLiteral.enumLiteral().namespaceName()?.IDENTIFIER().symbol; if (classClass !== undefined) { this.class = new ClassType(this, classClass); } else if (classLib !== undefined) { this.class = new Identifier(this, classLib); } this.name = new Identifier(this, name); this.value = new Identifier(this, value); } visit(enterCb, exitCb) { this.enter(enterCb); this.class?.visit(enterCb, exitCb); this.name.visit(enterCb, exitCb); this.value.visit(enterCb, exitCb); this.exit(exitCb); } } function createLiteralNode(parent, literal) { try { if (literal instanceof TextContext) { return new TextLiteral(parent, literal.textLiteral()); } else if (literal instanceof IntegerContext) { return new IntegerLiteral(parent, literal); } else if (literal instanceof RealContext) { return new RealLiteral(parent, literal); } else if (literal instanceof BooleanContext) { return new BooleanLiteral(parent, literal); } else if (literal instanceof NullContext) { return new NullLiteral(parent, literal); } else if (literal instanceof NullIdContext) { return new NullIdLiteral(parent, literal); } else if (literal instanceof EnumContext) { return new EnumLiteral(parent, literal); } else { return new InvalidLiteral(parent, literal.start, literal.stop); } } catch (error) { if (error instanceof Error) { return new InvalidLiteral(parent, literal.start, literal.stop, error); } else { return new InvalidLiteral(parent, literal.start, literal.stop, new ASTBuildError('Failed to build `Literal` node. Something went wrong while reading `LiteralContext`.')); } } } class Identifier extends Node { kind; namespace; name; isExpression; constructor(parent, identifier, namespace, isExpression) { if (namespace !== undefined && namespace !== null) { super(parent, namespace, identifier); this.namespace = namespace.text; } else { super(parent, identifier); } this.kind = Kind.Identifier; this.name = identifier.text ?? ''; this.isExpression = isExpression ?? false; } } class InvalidIdentifier extends Node { kind = Kind.InvalidIdentifier; } function isDirective(node) { return (node.kind === Kind.RequireContextDirective || node.kind === Kind.ExtendsDirective || node.kind === Kind.IncludeDirective || node.kind === Kind.SettingDirective || node.kind === Kind.CommandDirective || node.kind === Kind.StructDirective || node.kind === Kind.ConstDirective); } class InvalidDirective extends Node { kind = Kind.InvalidDirective; error; constructor(parent, start, stop, error) { super(parent, start, stop); if (error instanceof Error) { this.error = error; } else { this.error = null; } } } class RequireContextDirective extends Node { kind = Kind.RequireContextDirective; class; constructor(parent, requireContextDirective) { super(parent, requireContextDirective.start, requireContextDirective.stop); this.class = new ClassType(this, requireContextDirective.className().CLASS().symbol); } visit(enterCb, exitCb) { this.enter(enterCb); this.class.visit(enterCb, exitCb); this.exit(exitCb); } } class ExtendsDirective extends Node { kind = Kind.ExtendsDirective; path; constructor(parent, extendsDirective) { super(parent, extendsDirective.start, extendsDirective.stop); this.path = new TextLiteral(this, extendsDirective.extendsPath().textLiteral()); } visit(enterCb, exitCb) { this.enter(enterCb); this.path.visit(enterCb, exitCb); this.exit(exitCb); } } class IncludeDirective extends Node { kind = Kind.IncludeDirective; path; alias; constructor(parent, includeDirective) { super(parent, includeDirective.start, includeDirective.stop); this.path = new TextLiteral(this, includeDirective.includePath().textLiteral()); const identifier = includeDirective.includeAlias()?.namespaceDefinition().IDENTIFIER().symbol; if (identifier !== undefined) { this.alias = new Identifier(this, identifier); } } visit(enterCb, exitCb) { this.enter(enterCb); this.path.visit(enterCb, exitCb); this.alias?.visit(enterCb, exitCb); this.exit(exitCb); } } class InvalidSettingValue extends Node { kind = Kind.InvalidSettingValue; } class SettingDirective extends Node { kind = Kind.SettingDirective; name; value; description; constructor(parent, settingDirective) { super(parent, settingDirective.start, settingDirective.stop); this.name = new Identifier(this, settingDirective.settingName().IDENTIFIER().symbol); const literal = settingDirective.literal(); const vector = settingDirective.vector(); if (literal !== null) { this.value = createLiteralNode(this, literal); } else if (vector !== null) { this.value = new VectorExpression(this, vector); } else { this.value = new InvalidSettingValue(this, settingDirective.start, settingDirective.stop); } const descriptionAlias = settingDirective.textAlias()?._alias; if (descriptionAlias !== undefined) { this.description = new TextLiteral(this, descriptionAlias); } } visit(enterCb, exitCb) { this.enter(enterCb); this.name.visit(enterCb, exitCb); this.value.visit(enterCb, exitCb); this.description?.visit(enterCb, exitCb); this.exit(exitCb); } } class CommandDirective extends Node { kind = Kind.CommandDirective; name; type; description; constructor(parent, commandDirective) { super(parent, commandDirective.start, commandDirective.stop); this.name = new Identifier(this, commandDirective.commandName().IDENTIFIER().symbol); this.type = createTypeNode(this, commandDirective.type()); const alias = commandDirective.textAlias()?._alias; if (alias !== undefined) { this.description = new TextLiteral(this, alias); } } visit(enterCb, exitCb) { this.enter(enterCb); this.name.visit(enterCb, exitCb); this.type.visit(enterCb, exitCb); this.description?.visit(enterCb, exitCb); this.exit(exitCb); } } class StructMemberDeclaration extends Node { kind = Kind.StructMemberDeclaration; type; name; constructor(parent, structMember) { super(parent, structMember.start, structMember.stop); this.type = createTypeNode(this, structMember.type()); this.name = new Identifier(this, structMember.IDENTIFIER().symbol); } visit(enterCb, exitCb) { this.enter(enterCb); this.type.visit(enterCb, exitCb); this.name.visit(enterCb, exitCb); this.exit(exitCb); } } class StructDeclaration extends Node { kind = Kind.StructDeclaration; name; members; constructor(parent, structDeclaration) { super(parent, structDeclaration.start, structDeclaration.stop); this.name = new Identifier(this, structDeclaration.IDENTIFIER().symbol); this.members = []; const structMembers = structDeclaration.structMembers()?.structMember(); if (structMembers !== undefined) { for (const structMember of structMembers) { this.members.push(new StructMemberDeclaration(this, structMember)); } } } visit(enterCb, exitCb) { this.enter(enterCb); this.name.visit(enterCb, exitCb); for (const member of this.members) { member.visit(enterCb, exitCb); } this.exit(exitCb); } } class StructAliasing extends Node { kind = Kind.StructAliasing; name; alias; constructor(parent, structAliasing) { super(parent, structAliasing.start, structAliasing.stop); const structName = structAliasing.structName().IDENTIFIER().symbol; const structNamespace = structAliasing.namespaceName().IDENTIFIER().symbol; const structAlias = structAliasing.identifierAlias().IDENTIFIER().symbol; this.name = new Identifier(this, structName, structNamespace); this.alias = new Identifier(this, structAlias); } visit(enterCb, exitCb) { this.enter(enterCb); this.name.visit(enterCb, exitCb); this.alias.visit(enterCb, exitCb); this.exit(exitCb); } } class StructDirective extends Node { kind = Kind.StructDirective; declaration; aliasing; constructor(parent, structDirective) { super(parent, structDirective.start, structDirective.stop); const structDeclaration = structDirective.structDeclaration(); const structAliasing = structDirective.structAliasing(); if (structDeclaration !== null) { this.declaration = new StructDeclaration(this, structDeclaration); } if (structAliasing !== null) { this.aliasing = new StructAliasing(this, structAliasing); } if (this.declaration === undefined && this.aliasing === undefined) { throw new ASTBuildError('Failed to build `StructDirective` node. `declaration` and `aliasing` cannot both be `undefined`.'); } } visit(enterCb, exitCb) { this.enter(enterCb); this.declaration?.visit(enterCb, exitCb); this.aliasing?.visit(enterCb, exitCb); this.exit(exitCb); } } class InvalidConstValue extends Node { kind = Kind.InvalidConstValue; } class ConstDeclaration extends Node { kind = Kind.ConstDeclaration; name; value; constructor(parent, constDeclaration) { super(parent, constDeclaration.start, constDeclaration.stop); this.name = new Identifier(this, constDeclaration.IDENTIFIER().symbol); const literal = constDeclaration.literal(); const vector = constDeclaration.vector(); const array = constDeclaration.array(); const structure = constDeclaration.structure(); if (literal !== null) { this.value = createLiteralNode(this, literal); } else if (vector !== null) { this.value = new VectorExpression(this, vector); } else if (array !== null) { this.value = new ArrayExpression(this, array); } else if (structure !== null) { this.value = new StructExpression(this, structure); } else { this.value = new InvalidConstValue(this, constDeclaration.start, constDeclaration.stop); } } visit(enterCb, exitCb) { this.enter(enterCb); this.name.visit(enterCb, exitCb); this.value.visit(enterCb, exitCb); this.exit(exitCb); } } class ConstAliasing extends Node { kind = Kind.ConstAliasing; name; alias; constructor(parent, constAliasing) { super(parent, constAliasing.start, constAliasing.stop); const constName = constAliasing.constName().IDENTIFIER().symbol; const constNamespace = constAliasing.namespaceName().IDENTIFIER().symbol; const constAlias = constAliasing.identifierAlias().IDENTIFIER().symbol; this.name = new Identifier(this, constName, constNamespace); this.alias = new Identifier(this, constAlias); } visit(enterCb, exitCb) { this.enter(enterCb); this.name.visit(enterCb, exitCb); this.alias.visit(enterCb, exitCb); this.exit(exitCb); } } class ConstDirective extends Node { kind = Kind.ConstDirective; declaration; aliasing; constructor(parent, constDirective) { super(parent, constDirective.start, constDirective.stop); const constDeclaration = constDirective.constDeclaration(); const constAliasing = constDirective.constAliasing(); if (constDeclaration !== null) { this.declaration = new ConstDeclaration(this, constDeclaration); } if (constAliasing !== null) { this.aliasing = new ConstAliasing(this, constAliasing); } if (this.declaration === undefined && this.aliasing === undefined) { throw new ASTBuildError('Failed to build `ConstDirective` node. `declaration` and `aliasing` cannot both be `undefined`.'); } } visit(enterCb, exitCb) { this.enter(enterCb); this.declaration?.visit(enterCb, exitCb); this.aliasing?.visit(enterCb, exitCb); this.exit(exitCb); } } function isDeclaration(node) { return (node.kind === Kind.VariableDeclaration || node.kind === Kind.FunctionDeclaration || node.kind === Kind.LabelDeclaration); } var Storage; (function (Storage) { Storage["cloud"] = "cloud"; Storage["metadata"] = "metadata"; Storage["netread"] = "netread"; Storage["netwrite"] = "netwrite"; Storage["persistent"] = "persistent"; Storage["invalid"] = "invalid"; })(Storage || (Storage = {})); var InitializerSign; (function (InitializerSign) { InitializerSign["="] = "="; InitializerSign["<=>"] = "<=>"; InitializerSign["invalid"] = "invalid"; })(InitializerSign || (InitializerSign = {})); function toStorageEnum(storage) { if (storage.STORAGESPECIFIER_CLOUD() !== null) { return Storage.cloud; } else if (storage.STORAGESPECIFIER_METADATA() !== null) { return Storage.metadata; } else if (storage.STORAGESPECIFIER_NETREAD() !== null) { return Storage.netread; } else if (storage.STORAGESPECIFIER_NETWRITE() !== null) { return Storage.netwrite; } else if (storage.STORAGESPECIFIER_PERSISTENT() !== null) { return Storage.persistent; } else { return Storage.invalid; } } function toInitializerSign(sign) { if (sign.type === ManiaScriptParser.OPERATOR_ASSIGN) { return InitializerSign['=']; } else if (sign.type === ManiaScriptParser.OPERATOR_ARROWASSIGN) { return InitializerSign['<=>']; } else { return InitializerSign.invalid; } } class InvalidDeclaration extends Node { kind = Kind.InvalidDeclaration; error; constructor(parent, start, stop, error) { super(parent, start, stop); if (error instanceof Error) { this.error = error; } else { this.error = null; } } } class VariableDeclaration extends Node { kind = Kind.VariableDeclaration; isGlobal; isLet; storage; type; name; alias; forTarget; initializerSign; initializerExpression; initializerType; constructor(parent, variableDeclaration, isGlobal) { super(parent, variableDeclaration.start, variableDeclaration.stop); this.isGlobal = isGlobal; this.isLet = variableDeclaration instanceof VariableDeclarationLetContext; if (variableDeclaration instanceof VariableDeclarationWithTypeContext) { const storageSpecifier = variableDeclaration.storageSpecifier(); if (storageSpecifier !== null) { this.storage = toStorageEnum(storageSpecifier); } this.type = createTypeNode(this, variableDeclaration.type()); this.name = new Identifier(this, variableDeclaration.variableName().IDENTIFIER().symbol); const identifierAlias = variableDeclaration.identifierAlias(); if (identifierAlias !== null) { this.alias = new Identifier(this, identifierAlias.IDENTIFIER().symbol); } if (variableDeclaration._forTarget !== undefined) { this.forTarget = createExpressionNode(this, variableDeclaration._forTarget); } const initializer = variableDeclaration.initializer(); if (initializer !== null) { if (isNullish(initializer._sign)) { throw new ASTBuildError('Failed to build `VariableDeclaration` node. Missing initializer sign.'); } this.initializerSign = toInitializerSign(initializer._sign); const initializerExpression = initializer.expression(); const initializerType = initializer.initializerType(); if (initializerExpression !== null) { this.initializerExpression = createExpressionNode(this, initializerExpression); } else if (initializerType !== null) { this.initializerType = createInitializerTypeNode(this, initializerType); } } } else if (variableDeclaration instanceof VariableDeclarationWithoutTypeContext) { const storageSpecifier = variableDeclaration.storageSpecifier(); if (storageSpecifier !== null) { this.storage = toStorageEnum(storageSpecifier); } this.name = new Identifier(this, variableDeclaration.variableName().IDENTIFIER().symbol); const identifierAlias = variableDeclaration.identifierAlias(); if (identifierAlias !== null) { this.alias = new Identifier(this, identifierAlias.IDENTIFIER().symbol); } if (variableDeclaration._forTarget !== undefined) { this.forTarget = createExpressionNode(this, variableDeclaration._forTarget); } const initializer = variableDeclaration.initializer(); if (isNullish(initializer._sign)) { throw new ASTBuildError('Failed to build `VariableDeclaration` node. Missing initializer sign.'); } this.initializerSign = toInitializerSign(initializer._sign); const initializerExpression = initializer.expression(); const initializerType = initializer.initializerType(); if (initializerExpression !== null) { this.initializerExpression = createExpressionNode(this, initializerExpression); } else if (initializerType !== null) { this.initializerType = createInitializerTypeNode(this, initializerType); } } else { this.name = new Identifier(this, variableDeclaration.IDENTIFIER().symbol); this.initializerSign = toInitializerSign(variableDeclaration.OPERATOR_ASSIGN().symbol); const initializerExpression = variableDeclaration.expression(); const intializerArrayType = variableDeclaration.arrayType(); if (initializerExpression !== null) { this.initializerExpression = createExpressionNode(this, initializerExpression); } else if (intializerArrayType !== null) { this.initializerType = new ArrayType(this, intializerArrayType); } } } visit(enterCb, exitCb) { this.enter(enterCb); this.type?.visit(enterCb, exitCb); this.name.visit(enterCb, exitCb); this.alias?.visit(enterCb, exitCb); this.forTarget?.visit(enterCb, exitCb); this.initializerExpression?.visit(enterCb, exitCb); this.initializerType?.visit(enterCb, exitCb); this.exit(exitCb); } } class FunctionParameterDeclaration extends Node { kind = Kind.FunctionParameterDeclaration; type; name; constructor(parent, parameter) { super(parent, parameter.start, parameter.stop); this.type = createTypeNode(this, parameter.type()); this.name = new Identifier(this, parameter.IDENTIFIER().symbol); } visit(enterCb, exitCb) { this.enter(enterCb); this.type.visit(enterCb, exitCb); this.name.visit(enterCb, exitCb); this.exit(exitCb); } } class FunctionDeclaration extends Node { kind = Kind.FunctionDeclaration; type; name; parameters; body; constructor(parent, functionDeclaration) { super(parent, functionDeclaration.start, functionDeclaration.stop); this.type = createTypeNode(this, functionDeclaration.type()); this.name = new Identifier(this, functionDeclaration.functionName().IDENTIFIER().symbol); this.parameters = []; const parameters = functionDeclaration.parameters(); if (parameters !== null) { for (const parameter of parameters.parameter()) { this.parameters.push(new FunctionParameterDeclaration(this, parameter)); } } this.body = new BlockStatement(this, functionDeclaration.block()); } visit(enterCb, exitCb) { this.enter(enterCb); this.type.visit(enterCb, exitCb); this.name.visit(enterCb, exitCb); for (const parameter of this.parameters) { parameter.visit(enterCb, exitCb); } this.body.visit(enterCb, exitCb); this.exit(exitCb); } } class LabelDeclaration extends Node { kind = Kind.LabelDeclaration; name; body; constructor(parent, labelDeclaration) { super(parent, labelDeclaration.start, labelDeclaration.stop); this.name = new Identifier(this, labelDeclaration.labelName().IDENTIFIER().symbol); this.body = []; for (const statement of labelDeclaration.statements().statement()) { this.body.push(createStatementNode(this, statement)); } } visit(enterCb, exitCb) { this.enter(enterCb); this.name.visit(enterCb, exitCb); for (const statement of this.body) { statement.visit(enterCb, exitCb); } this.exit(exitCb); } } function isStatement(node) { return (node.kind === Kind.BlockStatement || node.kind === Kind.VariableDeclaration || node.kind === Kind.ExpressionStatement || node.kind === Kind.AssignmentStatement || node.kind === Kind.ReturnStatement || node.kind === Kind.LabelStatement || node.kind === Kind.AssertStatement || node.kind === Kind.ForeachStatement || node.kind === Kind.ForStatement || node.kind === Kind.WhileStatement || node.kind === Kind.MeanwhileStatement || node.kind === Kind.BreakStatement || node.kind === Kind.ContinueStatement || node.kind === Kind.SwitchStatement || node.kind === Kind.SwitchtypeStatement || node.kind === Kind.ConditionalStatement || node.kind === Kind.ConditionalBranch || node.kind === Kind.LogStatement || node.kind === Kind.SleepStatement || node.kind === Kind.TuningstartStatement || node.kind === Kind.TuningendStatement || node.kind === Kind.TuningmarkStatement || node.kind === Kind.WaitStatement || node.kind === Kind.YieldStatement); } class BlockStatement extends Node { kind = Kind.BlockStatement; body; constructor(parent, block) { super(parent, block.start, block.stop); this.body = []; const statements = block.statements()?.statement(); if (statements !== undefined) { for (const statement of statements) { this.body.push(createStatementNode(this, statement)); } } } visit(enterCb, exitCb) { this.enter(enterCb); for (const statement of this.body) { statement.visit(enterCb, exitCb); } this.exit(exitCb); } } class InvalidStatement extends Node { kind = Kind.InvalidStatement; error; constructor(parent, start, stop, error) { super(parent, start, stop); if (error instanceof Error) { this.error = error; } else { this.error = null; } } } class ExpressionStatement extends Node { kind = Kind.ExpressionStatement; expression; constructor(parent, expressionStatement) { super(parent, expressionStatement.start, expressionStatement.stop); this.expression = createExpressionNode(this, expressionStatement.expression()); } visit(enterCb, exitCb) { this.enter(enterCb); this.expression.visit(enterCb, exitCb); this.exit(exitCb); } } var AssignmentOperator; (function (AssignmentOperator) { AssignmentOperator["="] = "="; AssignmentOperator["<=>"] = "<=>"; AssignmentOperator["*="] = "*="; AssignmentOperator["/="] = "/="; AssignmentOperator["+="] = "+="; AssignmentOperator["-="] = "-="; AssignmentOperator["%="] = "%="; AssignmentOperator["^="] = "^="; })(AssignmentOperator || (AssignmentOperator = {})); class AssignmentStatement extends Node { kind = Kind.AssignmentStatement; left; right; operator; isInitializedByType; constructor(parent, assignmentStatement) { super(parent, assignmentStatement.start, assignmentStatement.stop); if (assignmentStatement._left === undefined) { throw new ASTBuildError('Failed to build `AssignmentStatement` node. Missing left part of the assignment.'); } this.left = createExpressionNode(this, assignmentStatement._left); const initializerType = assignmentStatement.initializerType(); if (initializerType !== null) { this.right = createInitializerTypeNode(this, initializerType); this.isInitializedByType = true; } else { if (assignmentStatement._right === undefined) { throw new ASTBuildError('Failed to build `AssignmentStatement` node. Missing right part of the assignment.'); } this.right = createExpressionNode(this, assignmentStatement._right); this.isInitializedByType = false; } const assignmentOperator = assignmentStatement.assignmentOperator(); if (assignmentOperator !== null) { if (assignmentOperator.OPERATOR_ARROWASSIGN() !== null) { this.operator = AssignmentOperator['<=>']; } else if (assignmentOperator.OPERATOR_CONCATASSIGN() !== null) { this.operator = AssignmentOperator['^=']; } else if (assignmentOperator.OPERATOR_DIVIDEASSIGN() !== null) { this.operator = AssignmentOperator['/=']; } else if (assignmentOperator.OPERATOR_MINUSASSIGN() !== null) { this.operator = AssignmentOperator['-=']; } else if (assignmentOperator.OPERATOR_MODULOASSIGN() !== null) { this.operator = AssignmentOperator['%=']; } else if (assignmentOperator.OPERATOR_MULTIPLYASSIGN() !== null) { this.operator = AssignmentOperator['*=']; } else if (assignmentOperator.OPERATOR_PLUSASSIGN() !== null) { this.operator = AssignmentOperator['+=']; } else { this.operator = AssignmentOperator['=']; } } else if (assignmentStatement.OPERATOR_ARROWASSIGN() !== null) { this.operator = AssignmentOperator['<=>']; } else { this.operator = AssignmentOperator['=']; } } visit(enterCb, exitCb) { this.enter(enterCb); this.left.visit(enterCb, exitCb); this.right.visit(enterCb, exitCb); this.exit(exitCb); } } class ReturnStatement extends Node { kind = Kind.ReturnStatement; argument; isReturningType; constructor(parent, returnStatement) { super(parent, returnStatement.start, returnStatement.stop); this.isReturningType = false; const initializerType = returnStatement.initializerType(); const returnExpression = returnStatement.expression(); if (initializerType !== null) { this.argument = createInitializerTypeNode(this, initializerType); this.isReturningType = true; } else if (returnExpression !== null) { this.argument = createExpressionNode(this, returnExpression); } } visit(enterCb, exitCb) { this.enter(enterCb); this.argument?.visit(enterCb, exitCb); this.exit(exitCb); } } class LabelStatement extends Node { kind = Kind.LabelStatement; isOverwrite; name; constructor(parent, labelStatement) { super(parent, labelStatement.start, labelStatement.stop); const labelInsert = labelStatement.labelInsert(); const labelOverwrite = labelStatement.labelOverwrite(); if (labelInsert !== null) { this.isOverwrite = false; this.name = new Identifier(this, labelInsert.IDENTIFIER().symbol); } else if (labelOverwrite !== null) { this.isOverwrite = true; this.name = new Identifier(this, labelOverwrite.IDENTIFIER().symbol); } else { this.isOverwrite = false; this.name = new InvalidIdentifier(this, labelStatement.start, labelStatement.stop); } } visit(enterCb, exitCb) { this.enter(enterCb); this.name.visit(enterCb, exitCb); this.exit(exitCb); } } class AssertStatement extends Node { kind = Kind.AssertStatement; test; message; constructor(parent, assertStatement) { super(parent, assertStatement.start, assertStatement.stop); if (assertStatement._test === undefined) { throw new ASTBuildError('Failed to build `AssertStatement` node. Missing assert test.'); } this.test = createExpressionNode(this, assertStatement._test); if (assertStatement._message !== undefined) { this.message = createExpressionNode(this, assertStatement._mes