private ScriptExpression GetEnumExpression(HS_Gen1Parser.LiteralContext context, string expectedValueType) { string text = context.GetTextSanitized(); ScriptValueType info = _opcodes.GetTypeInfo(expectedValueType); int val = info.GetEnumIndex(text); if (val == -1) { return(null); } if (info.Size == 4) { return(new ScriptExpression(_currentIndex, info.Opcode, info.Opcode, ScriptExpressionType.Expression, _strings.Cache(text), (short)context.Start.Line, (uint)val)); } else if (info.Size == 2) { return(new ScriptExpression(_currentIndex, info.Opcode, info.Opcode, ScriptExpressionType.Expression, _strings.Cache(text), (short)context.Start.Line, (ushort)val)); } else { return(null); } }
private ScriptExpression GetNumberExpression(HS_Gen1Parser.LiteralContext context) { // Is the number an integer? The default integer is a short for now. if (context.INT() != null) { string txt = context.GetTextSanitized(); if (!int.TryParse(txt, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out int num)) { throw new ArgumentException($"Failed to parse Long. Text: {txt}"); } if (num >= short.MinValue && num <= short.MaxValue) { return(GetShortExpression(context)); } else { return(GetLongExpression(context)); } } // Is the number a real? else if (context.FLOAT() != null) { return(GetRealExpression(context)); } else { return(null); } }
private ScriptExpression GetBooleanExpression(HS_Gen1Parser.LiteralContext context) { string text = context.GetTextSanitized(); if (context.BOOLEAN() == null) { return(null); } byte val; if (text == "true") { val = 1; } else if (text == "false") { val = 0; } else { return(null); } ushort opcode = _opcodes.GetTypeInfo("boolean").Opcode; return(new ScriptExpression(_currentIndex, opcode, opcode, ScriptExpressionType.Expression, context.GetCorrectTextPosition(_missingCarriageReturnPositions), (short)context.Start.Line, val)); }
private bool ProcessLiteral(string expectedValueType, HS_Gen1Parser.LiteralContext context) { // Casting might not be necessary. if (HandleValueType(context, expectedValueType)) { return(true); } // Casting. else { CastInfo info = _opcodes.GetTypeCast(expectedValueType); // This type can't be casted to. if (info is null) { return(false); } foreach (string cast in info.From) { if (HandleValueType(context, cast)) { // Overwrite the value type of the added expression node with the casted type. _expressions[_expressions.Count - 1].ReturnType = _opcodes.GetTypeInfo(expectedValueType).Opcode; return(true); } } return(false); } }
private ScriptExpression GetObjectNameExpression(HS_Gen1Parser.LiteralContext context, string valueType, string castTo) { string name = context.GetTextSanitized(); if (TryGetObjectFromContext(out ScriptingContextObject obj, Tuple.Create("object_name", name))) { ushort opcode = _opcodes.GetTypeInfo(valueType).Opcode; return(new ScriptExpression(_currentIndex, opcode, _opcodes.GetTypeInfo(castTo).Opcode, ScriptExpressionType.Expression, _strings.Cache(name), (short)context.Start.Line, (ushort)obj.Index)); }
private bool TryCreateObjectExpression(HS_Gen1Parser.LiteralContext context) { CastInfo info = _opcodes.GetTypeCast("object"); foreach (string type in info.From) { if (HandleValueType(context, type)) { return(true); } } return(false); }
/// <summary> /// Processes regular expressions, script variables and global references. Links to a datum. Opens a datum. /// </summary> /// <param name="context"></param> public override void EnterLiteral(HS_Gen1Parser.LiteralContext context) { if (_debug) { _logger.Literal(context, CompilerContextAction.Enter); } LinkDatum(); string text = context.GetTextSanitized(); string expectedType = _expectedTypes.PopType(); // Handle "none" expressions. The Value field of ai_line expressions stores their string offset. // Therefore the Value is not -1 if the expression is "none". if(IsNone(text) && expectedType != "ai_line" && expectedType != "string") { ushort opcode = _opcodes.GetTypeInfo(expectedType).Opcode; var expression = new ScriptExpression { Index = _currentIndex, Opcode = opcode, ReturnType = opcode, Type = ScriptExpressionType.Expression, Next = DatumIndex.Null, StringOffset = _strings.Cache(text), Value = new LongExpressionValue(0xFFFFFFFF), LineNumber = GetLineNumber(context) }; OpenDatumAddExpressionIncrement(expression); return; } // handle script variable references if (IsScriptParameter(expectedType, context)) return; // handle global references if (IsGlobalsReference(expectedType, context)) return; // handle regular expressions if (ProcessLiteral(expectedType, context)) return; throw new CompilerException($"Failed to process the expression \"{text.Trim('"')}\". A \"{expectedType}\" expression was expected.", context); }
private bool HandleValueType(HS_Gen1Parser.LiteralContext context, string expectedValueType) { ScriptExpression expression; // Enum expressions. if (_opcodes.GetTypeInfo(expectedValueType)?.IsEnum == true) { expression = GetEnumExpression(context, expectedValueType); } // Other expressions. else { switch (expectedValueType) { case "ANY": expression = GetNumberExpression(context); if (expression is null) { expression = GetBooleanExpression(context); if (expression is null) { if (TryCreateObjectExpression(context)) { return(true); } throw new CompilerException($"Failed to process \"{context.GetTextSanitized()}\" because it didn't know which value type to expect." + $" Try using a different function with clearly defined parameters.", context); } } break; case "NUMBER": expression = GetNumberExpression(context); break; case "short": expression = GetShortExpression(context); break; case "long": expression = GetLongExpression(context); break; case "boolean": expression = GetBooleanExpression(context); break; case "real": expression = GetRealExpression(context); break; case "string": expression = GetStringExpression(context); break; case "string_id": expression = CreateSIDExpression(context); break; case "unit_seat_mapping": expression = CreateUnitSeatMappingExpression(context); break; // 16 Bit Index. case "script": case "ai_command_script": case "trigger_volume": case "cutscene_flag": case "cutscene_camera_point": case "cutscene_title": case "starting_profile": case "zone_set": case "designer_zone": expression = GetIndex16Expression(context, expectedValueType); break; // 32 Bit Index. case "folder": case "cinematic_lightprobe": expression = GetIndex32Expression(context, expectedValueType); break; case "ai_line": expression = CreateLineExpression(context); break; case "point_reference": expression = GetPointReferenceExpression(context); break; case "sound": case "effect": case "damage": case "looping_sound": case "animation_graph": case "object_definition": case "bitmap": case "shader": case "render_model": case "structure_definition": case "lightmap_definition": case "cinematic_definition": case "cinematic_scene_definition": case "cinematic_transition_definition": case "bink_definition": case "cui_screen_definition": case "any_tag": case "any_tag_not_resolving": expression = GetTagrefExpression(context, expectedValueType); break; case "device_group": expression = GetDeviceGroupExpression(context); break; case "ai": // H3 does not share the same AI format as ODST and Reach. if (_buildInfo.Name.Contains("Reach") || _buildInfo.Name.Contains("ODST")) { expression = GetAIExpressionODST(context, expectedValueType); } else { expression = GetAIExpressionH3(context, expectedValueType); } break; case "object_name": case "unit_name": case "vehicle_name": case "weapon_name": case "device_name": case "scenery_name": case "effect_scenery_name": expression = GetObjectNameExpression(context, expectedValueType, expectedValueType); break; default: // Return false if this value type has not been implemented yet and the expression could not be handled. if (_opcodes.GetTypeInfo(expectedValueType) != null) { return(false); } // Throw an exception for unknown and misspelled value types. else { throw new CompilerException($"Unknown Value Type: \"{expectedValueType}\". " + $"A type definition might be missing from the scripting XML file or this could be a bug.", context); } } } // Failed to generate an expression. if (expression is null) { return(false); } // Finalize the expression. OpenDatumAddExpressionIncrement(expression); string actualType = _opcodes.GetTypeInfo(expression.Opcode).Name; EqualityPush(actualType); return(true); }
/// <summary> /// Exit a parse tree produced by <see cref="HS_Gen1Parser.literal"/>. /// <para>The default implementation does nothing.</para> /// </summary> /// <param name="context">The parse tree.</param> public virtual void ExitLiteral([NotNull] HS_Gen1Parser.LiteralContext context) { }