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);
        }
Exemple #7
0
        /// <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)
 {
 }