<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/Commands/CreateVfddFileCommand.cs<|end_filename|>
﻿using Microsoft.VisualStudio.Shell;
using Spect.Net.SpectrumEmu.Abstraction.Devices.Floppy;
using Spect.Net.SpectrumEmu.Devices.Floppy;
using Spect.Net.VsPackage.Dialogs.Vfdd;
using Spect.Net.VsPackage.SolutionItems;
using Spect.Net.VsPackage.VsxLibrary;
using Spect.Net.VsPackage.VsxLibrary.Command;
using System;
using System.IO;
using Task = System.Threading.Tasks.Task;

namespace Spect.Net.VsPackage.Commands
{
    /// <summary>
    /// This command creates a virtual floppy disk file
    /// </summary>
    [CommandId(0x1B00)]
    public class CreateVfddFileCommand: SpectNetCommandBase
    {
        private const string FILE_EXISTS_MESSAGE = "The virtual floppy disk file exists in the project. " +
                                           "Would you like to override it?";

        private const string INVALID_FOLDER_MESSAGE = "The virtual floppy disk folder specified in the Options dialog " +
                                                      "contains invalid characters or an absolute path. Go to the Options dialog and " +
                                                      "fix the issue so that you can add the file to the project.";

        /// <summary>
        /// Eanble this command only if there's any floppy disk present
        /// </summary>
        /// <param name="mc"></param>
        protected override void OnQueryStatus(OleMenuCommand mc)
        {
            base.OnQueryStatus(mc);

            if (!mc.Visible) 
                return;

            mc.Visible = (SpectNetPackage.Default?.EmulatorViewModel?.Machine?.SpectrumVm?.FloppyDevice ?? (object)null) is FloppyDevice;
        }

        /// <summary>
        /// Sets the active project to the current project file
        /// </summary>
        protected async override Task ExecuteAsync()
        {
            // --- Collect export parameters from the UI
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
            if (DisplayCreateVfddDialog(out var vm)) return;

            // --- Create a temporary file
            string fullPath;
            try
            {
                var filename = Path.ChangeExtension(Path.GetFileName(vm.Filename), ".vfdd");
                var userPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
                fullPath = Path.Combine(Path.Combine(userPath, "SpectNetFloppies"), filename);
                VirtualFloppyFile.CreateSpectrumFloppyFile(fullPath, vm.Format);
            }
            catch (Exception ex)
            {
                VsxDialogs.Show($"Error: {ex.Message}", "Error creating virtual floppy disk file");
                return;
            }

            // --- Add the temp file to the project
            SpectrumProject.AddFileToProject(SpectNetPackage.Default.Options.VfddFolder, fullPath,
                INVALID_FOLDER_MESSAGE, FILE_EXISTS_MESSAGE);

            // --- Remove the temp file
            try
            {
                File.Delete(fullPath);
            }
            catch (Exception)
            {
                // --- This exception is intentionally ignored
            }
        }

        /// <summary>
        /// Displays the Export Z80 Code dialog to collect parameter data
        /// </summary>
        /// <param name="vm">View model with collected data</param>
        /// <returns>
        /// True, if the user stars export; false, if the export is cancelled
        /// </returns>
        private bool DisplayCreateVfddDialog(out CreateVfddFileViewModel vm)
        {
            var createVfddDialog = new CreateVfddFileDialog()
            {
                HasMaximizeButton = false,
                HasMinimizeButton = false
            };

            vm = new CreateVfddFileViewModel
            {
                Format = FloppyFormat.SpectrumP3,
                Filename = "Floppy.vfdd",
            };

            createVfddDialog.SetVm(vm);
            var accepted = createVfddDialog.ShowModal();
            if (accepted.HasValue && accepted.Value) return false;

            IsCancelled = true;
            return true;
        }

    }
}


<|start_filename|>v2/Assembler/Spect.Net.Assembler/Assembler/BinarySegment.cs<|end_filename|>
﻿using System.Collections.Generic;

namespace Spect.Net.Assembler.Assembler
{
    /// <summary>
    /// This class represents a single segment of the code compilation
    /// </summary>
    public class BinarySegment
    {
        /// <summary>
        /// The bank of this segment
        /// </summary>
        public ushort? Bank { get; set; }

        /// <summary>
        /// Start offset used for banks
        /// </summary>
        public ushort BankOffset { get; set; }

        /// <summary>
        /// Maximum code length
        /// </summary>
        public int MaxCodeLength { get; set; }

        /// <summary>
        /// Start address of the compiled block
        /// </summary>
        public ushort StartAddress { get; set; }

        /// <summary>
        /// Displacement of the this segment
        /// </summary>
        public ushort? Displacement { get; set; }

        /// <summary>
        /// The current assembly address when DISP pragma was used
        /// </summary>
        public ushort? DispPragmaOffset { get; set; }

        /// <summary>
        /// Intel HEX start address of the this segment
        /// </summary>
        public ushort? XorgValue { get; set; }

        /// <summary>
        /// Emitted Z80 binary code
        /// </summary>
        public List<byte> EmittedCode { get; set; } = new List<byte>(1024);

        /// <summary>
        /// Signs if overflow has been detected
        /// </summary>
        public bool OverflowDetected { get; private set; }

        /// <summary>
        /// The current code generation offset
        /// </summary>
        public int CurrentOffset => EmittedCode.Count;

        /// <summary>
        /// Shows the offset of the instruction being compiled.
        /// </summary>
        public int CurrentInstructionOffset { get; set; }

        /// <summary>
        /// Emits a new data byte
        /// </summary>
        /// <param name="data"></param>
        public string EmitByte(byte data)
        {
            EmittedCode.Add(data);
            if (StartAddress + EmittedCode.Count > 0x10000 && !OverflowDetected)
            {
                OverflowDetected = true;
                return Errors.Z0304;
            }
            if (EmittedCode.Count > MaxCodeLength && !OverflowDetected)
            {
                OverflowDetected = true;
                return Errors.Z0309;
            }
            return null;
        }
    }
}

<|start_filename|>v2/Core/Spect.Net.SpectrumEmu/Abstraction/Machine/ISpectrumVmRunCodeSupport.cs<|end_filename|>
﻿using System.Collections.Generic;

namespace Spect.Net.SpectrumEmu.Abstraction.Machine
{
    /// <summary>
    /// This interface defines the operations that support 
    /// running injected Z80 code on the Spectrum virtual machine.
    /// </summary>
    public interface ISpectrumVmRunCodeSupport
    {
        /// <summary>
        /// Injects code into the memory.
        /// </summary>
        /// <param name="addr">Start address.</param>
        /// <param name="code">Code to inject.</param>
        /// <remarks>The code leaves the ROM area untouched.</remarks>
        void InjectCodeToMemory(ushort addr, IReadOnlyCollection<byte> code);

        /// <summary>
        /// Injects code to the specified bank, starting at address 0
        /// </summary>
        /// <param name="bankIndex">Index of the bank</param>
        /// <param name="bankOffset">Offset within the bank</param>
        /// <param name="code">Code to insert</param>
        void InjectCodeToBank(int bankIndex, int bankOffset, IReadOnlyCollection<byte> code);

        /// <summary>
        /// Prepares the custom code for running, as if it were started
        /// with the RUN command.
        /// </summary>
        void PrepareRunMode(HashSet<string> options);

        /// <summary>
        /// Clears the screen
        /// </summary>
        void ClearScreen();
    }
}

<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/ToolWindows/BasicList/BasicListViewModel.cs<|end_filename|>
﻿using Spect.Net.SpectrumEmu.Devices.Rom;
using Spect.Net.VsPackage.VsxLibrary;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
using System.Windows;

namespace Spect.Net.VsPackage.ToolWindows.BasicList
{
    /// <summary>
    /// This view model represent the ZX Spectrum BASIC List
    /// </summary>
    public class BasicListViewModel : SpectrumToolWindowViewModelBase
    {
        private readonly List<string> _tokens;

        /// <summary>
        /// The memory address to decode the basic listing from
        /// </summary>
        public byte[] Memory { get; }

        /// <summary>
        /// The offset where the Basic program starts in the memory
        /// </summary>
        public ushort StartOffset { get; }

        /// <summary>
        /// The offset wher the basic program ends in the memory
        /// </summary>
        public ushort EndOffset { get; }

        /// <summary>
        /// Signs if ZX BASIC should be mimicked
        /// </summary>
        public bool MimicZxBasic { get; set; }

        /// <summary>
        /// Program lines decoded
        /// </summary>
        public ObservableCollection<BasicLineViewModel> ProgramLines { get; set; } = new ObservableCollection<BasicLineViewModel>();

        /// <summary>
        /// Instantiates this view model
        /// </summary>
        public BasicListViewModel()
        {
            if (!IsInDesignMode) return;

            ProgramLines = new ObservableCollection<BasicLineViewModel>
            {
                new BasicLineViewModel {LineNo = 10, Length = 10, Text = "Line 10"},
                new BasicLineViewModel {LineNo = 20, Length = 10, Text = "Line 20"},
                new BasicLineViewModel {LineNo = 30, Length = 10, Text = "Line 30"},
                new BasicLineViewModel {LineNo = 40, Length = 10, Text = "Line 40"},
            };
        }

        /// <summary>
        /// Instantiates this view model with the specified attributes
        /// </summary>
        /// <param name="memory">Memory array</param>
        /// <param name="startOffset">Start offset of the BASIC code</param>
        /// <param name="endOffset">End offset of the BASIC Code (exclusive)</param>
        public BasicListViewModel(byte[] memory, ushort startOffset, ushort endOffset, bool mimicZxBasic = false) : this()
        {
            var romDevice = SpectrumVm?.RomDevice;
            if (romDevice != null)
            {
                romDevice.GetProperty<List<string>>(SpectrumRomDevice.TOKEN_TABLE_KEY, out var tokenList,
                    romDevice.HostVm.RomConfiguration.Spectrum48RomIndex);
                {
                    _tokens = tokenList;
                }
            }
            Memory = memory;
            StartOffset = startOffset;
            EndOffset = endOffset;
            MimicZxBasic = mimicZxBasic;
        }

        /// <summary>
        /// Decodes the BASIC program in the memory
        /// </summary>
        public void DecodeBasicProgram(List<BasicLineViewModel> list = null)
        {
            var progStart = StartOffset;
            var progEnd = EndOffset;

            if (progStart == 0 || progEnd == 0) return;

            while (progStart < progEnd)
            {
                progStart = GetBasicLine(progStart, out BasicLineViewModel line);
                if (list != null)
                {
                    list.Add(line);
                }
                else
                {
                    ProgramLines.Add(line);
                }
            }
        }

        /// <summary>
        /// Gets the specified BASIC code line
        /// </summary>
        /// <param name="progStart">Code line address in the memory</param>
        /// <param name="lineVm">BASIC line view model</param>
        /// <returns></returns>
        public ushort GetBasicLine(ushort progStart, out BasicLineViewModel lineVm)
        {
            lineVm = new BasicLineViewModel
            {
                LineNo = Memory[progStart++] * 0x100 + Memory[progStart++],
                Length = Memory[progStart++] + Memory[progStart++] * 0x100
            };
            var lineEnd = progStart + lineVm.Length;
            if (lineEnd > Memory.Length - 1)
            {
                lineEnd = Memory.Length - 1;
            }

            var spaceBeforeToken = false;
            var withinQuotes = false;
            var sb = new StringBuilder(256);

            while (progStart < lineEnd)
            {
                var nextSymbol = Memory[progStart++];
                if (nextSymbol >= 0xA5)
                {
                    // --- This is a token
                    if (spaceBeforeToken)
                    {
                        sb.Append(" ");
                    }
                    var tokenCode = nextSymbol - 0xA5;
                    var token = _tokens[tokenCode];
                    sb.Append(token);
                    if (tokenCode > 2 && char.IsLetter(token[token.Length - 1]))
                    {
                        sb.Append(" ");
                        spaceBeforeToken = false;
                    }
                    continue;
                }

                // --- Whatever we print, the next token needs a space
                spaceBeforeToken = true;

                // --- Skip ENTER
                if (nextSymbol == 0x0D)
                {
                    continue;
                }

                // --- Skip binary number characters
                if (nextSymbol == 0x0E)
                {
                    // --- Skip the binary form of a floating point number
                    progStart += 5;
                    continue;
                }

                if (nextSymbol == 0x22)
                {
                    // --- Printable character
                    sb.Append((char)nextSymbol);
                    withinQuotes = !withinQuotes;
                    continue;
                }

                if (MimicZxBasic && !withinQuotes && nextSymbol < 0x20)
                {
                    // --- Skip all remaining control characters in ZX BASIC mode
                    continue;
                }

                if (nextSymbol >= 0x20 && nextSymbol <= 0x7F)
                {
                    // --- Printable character
                    if (withinQuotes)
                    {
                        if (nextSymbol == (int)'\\')
                        {
                            sb.Append(MimicZxBasic ? "\\\\" : "\\");
                            continue;
                        }
                        else if (nextSymbol == 0x60)
                        {
                            sb.Append(MimicZxBasic ? "\\`" : "Ł");
                            continue;
                        }
                        else if (nextSymbol == 0x7f)
                        {
                            sb.Append(MimicZxBasic ? "\\*" : "©");
                            continue;
                        }
                    } 
                    else
                    {
                        if (nextSymbol == (int)'\\')
                        {
                            sb.Append("\\");
                            continue;
                        }
                        else if (nextSymbol == 0x60)
                        {
                            sb.Append("Ł");
                            continue;
                        }
                        else if (nextSymbol == 0x7f)
                        {
                            sb.Append("©");
                            continue;
                        }
                    }
                    sb.Append((char)nextSymbol);
                    continue;
                }

                // --- Non-printable character, let's display it with an escape sequence
                if (MimicZxBasic && withinQuotes)
                {
                    if (nextSymbol >= 0x90 && nextSymbol <= 0xA4)
                    {
                        // --- Handle UDG chars in ZX BASIC
                        sb.Append($"\\{(char)(nextSymbol - 0x90 + 'A')}");
                        continue;
                    }

                    var lookahead = progStart < Memory.Length ? Memory[progStart] : -1;
                    switch (nextSymbol)
                    {
                        case 0x10:
                            if (lookahead >= 0)
                            {
                                sb.Append("\\{i" + lookahead + "}");
                                progStart++;
                            }
                            break;
                        case 0x11:
                            if (lookahead >= 0)
                            {
                                sb.Append("\\{p" + lookahead + "}");
                                progStart++;
                            }
                            break;
                        case 0x12:
                            if (lookahead >= 0)
                            {
                                sb.Append("\\{f" + lookahead + "}");
                                progStart++;
                            }
                            break;
                        case 0x13:
                            if (lookahead >= 0)
                            {
                                sb.Append("\\{b" + lookahead + "}");
                                progStart++;
                            }
                            break;
                        case 0x80:
                            sb.Append("\\  ");
                            break;
                        case 0x81:
                            sb.Append("\\ '");
                            break;
                        case 0x82:
                            sb.Append("\\' ");
                            break;
                        case 0x83:
                            sb.Append("\\''");
                            break;
                        case 0x84:
                            sb.Append("\\ .");
                            break;
                        case 0x85:
                            sb.Append("\\ :");
                            break;
                        case 0x86:
                            sb.Append("\\'.");
                            break;
                        case 0x87:
                            sb.Append("\\':");
                            break;
                        case 0x88:
                            sb.Append("\\. ");
                            break;
                        case 0x89:
                            sb.Append("\\.'");
                            break;
                        case 0x8a:
                            sb.Append("\\: ");
                            break;
                        case 0x8b:
                            sb.Append("\\:'");
                            break;
                        case 0x8c:
                            sb.Append("\\..");
                            break;
                        case 0x8d:
                            sb.Append("\\.:");
                            break;
                        case 0x8e:
                            sb.Append("\\:.");
                            break;
                        case 0x8f:
                            sb.Append("\\::");
                            break;
                        default:
                            sb.Append($"#{nextSymbol & 0xff}");
                            break;
                    }
                }
                else
                {
                    sb.Append($"°{nextSymbol:X2}°");
                }
            }

            lineVm.Text = sb.ToString();
            return progStart;
        }

        /// <summary>
        /// Exports the list to the specified file
        /// </summary>
        /// <param name="filename"></param>
        public void ExportToFile(string filename)
        {
            var listing = new StringBuilder(4096);
            foreach (var line in ProgramLines)
            {
                listing.Append(line.LineNo);
                listing.Append(" ");
                listing.AppendLine(line.Text);
            }
            try
            {
                var dirName = Path.GetDirectoryName(filename);
                if (!string.IsNullOrEmpty(dirName) && !Directory.Exists(dirName))
                {
                    Directory.CreateDirectory(dirName);
                }
                File.WriteAllText(filename, listing.ToString());
            }
            catch (Exception ex)
            {
                VsxDialogs.Show($"Error while exporting to file {filename}: {ex.Message}",
                    "Export BASIC listing error.", MessageBoxButton.OK, VsxMessageBoxIcon.Error);
                return;
            }
        }

        /// <summary>
        /// Compares this view model with another
        /// </summary>
        /// <param name="other">Other view model</param>
        /// <returns>True, if the two view models are equal; otherwise, false</returns>
        public static bool Compare(BasicListViewModel thisModel, BasicListViewModel other)
        {
            if (other == null) return false;
            if (other.ProgramLines.Count != thisModel.ProgramLines.Count) return false;
            for (var i = 0; i < thisModel.ProgramLines.Count; i++)
            {
                var otherItem = other.ProgramLines[i];
                var thisItem = thisModel.ProgramLines[i];
                if (otherItem.LineNo != thisItem.LineNo ||
                    otherItem.Length != thisItem.Length ||
                    otherItem.Text != thisItem.Text)
                {
                    return false;
                }
            }
            return true;
        }
    }
}


<|start_filename|>v2/Core/Spect.Net.SpectrumEmu/SpectrumModels.cs<|end_filename|>
﻿using System.Collections.Generic;
using Spect.Net.Assembler.Assembler;
using Spect.Net.SpectrumEmu.Abstraction.Configuration;
using Spect.Net.SpectrumEmu.Abstraction.Models;

namespace Spect.Net.SpectrumEmu
{
    /// <summary>
    /// This class is an inventory of available Spectrum models and
    /// revisions supported by SpectNetIde
    /// </summary>
    public static class SpectrumModels
    {
        private static readonly Dictionary<string, SpectrumModelEditions> s_StockModels = 
            new Dictionary<string, SpectrumModelEditions>
        {
            {
                ZX_SPECTRUM_48, new SpectrumModelEditions
                {
                    Editions = new Dictionary<string, SpectrumEdition>
                    {
                        {
                            PAL, new SpectrumEdition
                            {
                                Cpu = new CpuConfigurationData
                                {
                                    BaseClockFrequency = 3_500_000,
                                    ClockMultiplier = 1,
                                    SupportsNextOperations = false
                                },
                                Rom = new RomConfigurationData
                                {
                                    RomName = "ZxSpectrum48",
                                    NumberOfRoms = 1,
                                    Spectrum48RomIndex = 0
                                },
                                Memory = new MemoryConfigurationData
                                {
                                    SupportsBanking = false,
                                    ContentionType = MemoryContentionType.Ula
                                },
                                Screen = new ScreenConfigurationData
                                {
                                    InterruptTact = 11,
                                    VerticalSyncLines = 8,
                                    NonVisibleBorderTopLines = 8,
                                    BorderTopLines = 48,
                                    BorderBottomLines = 48,
                                    NonVisibleBorderBottomLines = 8,
                                    DisplayLines = 192,
                                    BorderLeftTime = 24,
                                    BorderRightTime = 24,
                                    DisplayLineTime = 128,
                                    HorizontalBlankingTime = 40,
                                    NonVisibleBorderRightTime = 8,
                                    PixelDataPrefetchTime = 2,
                                    AttributeDataPrefetchTime = 1
                                },
                                Beeper = new AudioConfigurationData
                                {
                                    AudioSampleRate = 35000,
                                    SamplesPerFrame = 699,
                                    TactsPerSample = 100
                                }
                            }
                        },
                        {
                            PAL2, new SpectrumEdition
                            {
                                UlaIssue = "2",
                                Cpu = new CpuConfigurationData
                                {
                                    BaseClockFrequency = 3_500_000,
                                    ClockMultiplier = 1,
                                    SupportsNextOperations = false
                                },
                                Rom = new RomConfigurationData
                                {
                                    RomName = "ZxSpectrum48",
                                    NumberOfRoms = 1,
                                    Spectrum48RomIndex = 0
                                },
                                Memory = new MemoryConfigurationData
                                {
                                    SupportsBanking = false,
                                    ContentionType = MemoryContentionType.Ula
                                },
                                Screen = new ScreenConfigurationData
                                {
                                    InterruptTact = 11,
                                    VerticalSyncLines = 8,
                                    NonVisibleBorderTopLines = 8,
                                    BorderTopLines = 48,
                                    BorderBottomLines = 48,
                                    NonVisibleBorderBottomLines = 8,
                                    DisplayLines = 192,
                                    BorderLeftTime = 24,
                                    BorderRightTime = 24,
                                    DisplayLineTime = 128,
                                    HorizontalBlankingTime = 40,
                                    NonVisibleBorderRightTime = 8,
                                    PixelDataPrefetchTime = 2,
                                    AttributeDataPrefetchTime = 1
                                },
                                Beeper = new AudioConfigurationData
                                {
                                    AudioSampleRate = 35000,
                                    SamplesPerFrame = 699,
                                    TactsPerSample = 100
                                }
                            }
                        },
                        {
                            NTSC, new SpectrumEdition
                            {
                                Cpu = new CpuConfigurationData
                                {
                                    BaseClockFrequency = 3_500_000,
                                    ClockMultiplier = 1,
                                    SupportsNextOperations = false
                                },
                                Rom = new RomConfigurationData
                                {
                                    RomName = "ZxSpectrum48",
                                    NumberOfRoms = 1,
                                    Spectrum48RomIndex = 0
                                },
                                Memory = new MemoryConfigurationData
                                {
                                    SupportsBanking = false,
                                    ContentionType = MemoryContentionType.Ula
                                },
                                Screen = new ScreenConfigurationData
                                {
                                    InterruptTact = 11,
                                    VerticalSyncLines = 8,
                                    NonVisibleBorderTopLines = 16,
                                    BorderTopLines = 24,
                                    BorderBottomLines = 24,
                                    NonVisibleBorderBottomLines = 0,
                                    DisplayLines = 192,
                                    BorderLeftTime = 24,
                                    BorderRightTime = 24,
                                    DisplayLineTime = 128,
                                    HorizontalBlankingTime = 40,
                                    NonVisibleBorderRightTime = 8,
                                    PixelDataPrefetchTime = 2,
                                    AttributeDataPrefetchTime = 1
                                },
                                Beeper = new AudioConfigurationData
                                {
                                    AudioSampleRate = 35000,
                                    SamplesPerFrame = 591,
                                    TactsPerSample = 100
                                }
                            }
                        },
                        {
                            PAL_2_X, new SpectrumEdition
                            {
                                Cpu = new CpuConfigurationData
                                {
                                    BaseClockFrequency = 3_500_000,
                                    ClockMultiplier = 2,
                                    SupportsNextOperations = false
                                },
                                Rom = new RomConfigurationData
                                {
                                    RomName = "ZxSpectrum48",
                                    NumberOfRoms = 1,
                                    Spectrum48RomIndex = 0
                                },
                                Memory = new MemoryConfigurationData
                                {
                                    SupportsBanking = false,
                                    ContentionType = MemoryContentionType.Ula
                                },
                                Screen = new ScreenConfigurationData
                                {
                                    InterruptTact = 11,
                                    VerticalSyncLines = 8,
                                    NonVisibleBorderTopLines = 8,
                                    BorderTopLines = 48,
                                    BorderBottomLines = 48,
                                    NonVisibleBorderBottomLines = 8,
                                    DisplayLines = 192,
                                    BorderLeftTime = 24,
                                    BorderRightTime = 24,
                                    DisplayLineTime = 128,
                                    HorizontalBlankingTime = 40,
                                    NonVisibleBorderRightTime = 8,
                                    PixelDataPrefetchTime = 2,
                                    AttributeDataPrefetchTime = 1
                                },
                                Beeper = new AudioConfigurationData
                                {
                                    AudioSampleRate = 35000,
                                    SamplesPerFrame = 699,
                                    TactsPerSample = 100
                                }
                            }
                        },
                        {
                            NTSC_2_X, new SpectrumEdition
                            {
                                Cpu = new CpuConfigurationData
                                {
                                    BaseClockFrequency = 3_500_000,
                                    ClockMultiplier = 2,
                                    SupportsNextOperations = false
                                },
                                Rom = new RomConfigurationData
                                {
                                    RomName = "ZxSpectrum48",
                                    NumberOfRoms = 1,
                                    Spectrum48RomIndex = 0
                                },
                                Memory = new MemoryConfigurationData
                                {
                                    SupportsBanking = false,
                                    ContentionType = MemoryContentionType.Ula
                                },
                                Screen = new ScreenConfigurationData
                                {
                                    InterruptTact = 11,
                                    VerticalSyncLines = 8,
                                    NonVisibleBorderTopLines = 16,
                                    BorderTopLines = 24,
                                    BorderBottomLines = 24,
                                    NonVisibleBorderBottomLines = 0,
                                    DisplayLines = 192,
                                    BorderLeftTime = 24,
                                    BorderRightTime = 24,
                                    DisplayLineTime = 128,
                                    HorizontalBlankingTime = 40,
                                    NonVisibleBorderRightTime = 8,
                                    PixelDataPrefetchTime = 2,
                                    AttributeDataPrefetchTime = 1
                                },
                                Beeper = new AudioConfigurationData
                                {
                                    AudioSampleRate = 35000,
                                    SamplesPerFrame = 699,
                                    TactsPerSample = 100
                                }
                            }
                        }
                    }
                }
            },
            {
                ZX_SPECTRUM_128, new SpectrumModelEditions
                {
                    Editions = new Dictionary<string, SpectrumEdition>
                    {
                        {
                            PAL, new SpectrumEdition
                            {
                                Cpu = new CpuConfigurationData
                                {
                                    BaseClockFrequency = 3_546_900,
                                    ClockMultiplier = 1,
                                    SupportsNextOperations = false
                                },
                                Rom = new RomConfigurationData
                                {
                                    RomName = "ZxSpectrum128",
                                    NumberOfRoms = 2,
                                    Spectrum48RomIndex = 1
                                },
                                Memory = new MemoryConfigurationData
                                {
                                    SupportsBanking = true,
                                    RamBanks = 8,
                                    ContentionType = MemoryContentionType.Ula
                                },
                                Screen = new ScreenConfigurationData
                                {
                                    InterruptTact = 14,
                                    VerticalSyncLines = 8,
                                    NonVisibleBorderTopLines = 7,
                                    BorderTopLines = 48,
                                    BorderBottomLines = 48,
                                    NonVisibleBorderBottomLines = 8,
                                    DisplayLines = 192,
                                    BorderLeftTime = 24,
                                    BorderRightTime = 24,
                                    DisplayLineTime = 128,
                                    HorizontalBlankingTime = 40,
                                    NonVisibleBorderRightTime = 12,
                                    PixelDataPrefetchTime = 2,
                                    AttributeDataPrefetchTime = 1
                                },
                                Beeper = new AudioConfigurationData
                                {
                                    AudioSampleRate = 35469,
                                    SamplesPerFrame = 709,
                                    TactsPerSample = 100
                                },
                                Sound = new AudioConfigurationData
                                {
                                    AudioSampleRate = 27710,
                                    SamplesPerFrame = 553,
                                    TactsPerSample = 128
                                }
                            }
                        }
                    }
                }
            },
            {
                ZX_SPECTRUM_P3_E, new SpectrumModelEditions
                {
                    Editions = new Dictionary<string, SpectrumEdition>
                    {
                        {
                            PAL, new SpectrumEdition
                            {
                                Cpu = new CpuConfigurationData
                                {
                                    BaseClockFrequency = 3_546_900,
                                    ClockMultiplier = 1,
                                    SupportsNextOperations = false
                                },
                                Rom = new RomConfigurationData
                                {
                                    RomName = "ZxSpectrumP3E",
                                    NumberOfRoms = 4,
                                    Spectrum48RomIndex = 3
                                },
                                Memory = new MemoryConfigurationData
                                {
                                    SupportsBanking = true,
                                    RamBanks = 8,
                                    ContentionType = MemoryContentionType.GateArray
                                },
                                Screen = new ScreenConfigurationData
                                {
                                    InterruptTact = 14,
                                    VerticalSyncLines = 8,
                                    NonVisibleBorderTopLines = 7,
                                    BorderTopLines = 48,
                                    BorderBottomLines = 48,
                                    NonVisibleBorderBottomLines = 8,
                                    DisplayLines = 192,
                                    BorderLeftTime = 24,
                                    BorderRightTime = 24,
                                    DisplayLineTime = 128,
                                    HorizontalBlankingTime = 40,
                                    NonVisibleBorderRightTime = 12,
                                    PixelDataPrefetchTime = 2,
                                    AttributeDataPrefetchTime = 1
                                },
                                Beeper = new AudioConfigurationData
                                {
                                    AudioSampleRate = 35469,
                                    SamplesPerFrame = 709,
                                    TactsPerSample = 100
                                },
                                Sound = new AudioConfigurationData
                                {
                                    AudioSampleRate = 27710,
                                    SamplesPerFrame = 553,
                                    TactsPerSample = 128
                                }
                            }
                        },
                        {
                            FLOPPY1, new SpectrumEdition
                            {
                                Cpu = new CpuConfigurationData
                                {
                                    BaseClockFrequency = 3_546_900,
                                    ClockMultiplier = 1,
                                    SupportsNextOperations = false
                                },
                                Rom = new RomConfigurationData
                                {
                                    RomName = "ZxSpectrumP3E",
                                    NumberOfRoms = 4,
                                    Spectrum48RomIndex = 3
                                },
                                Memory = new MemoryConfigurationData
                                {
                                    SupportsBanking = true,
                                    RamBanks = 8,
                                    ContentionType = MemoryContentionType.GateArray
                                },
                                Screen = new ScreenConfigurationData
                                {
                                    InterruptTact = 14,
                                    VerticalSyncLines = 8,
                                    NonVisibleBorderTopLines = 7,
                                    BorderTopLines = 48,
                                    BorderBottomLines = 48,
                                    NonVisibleBorderBottomLines = 8,
                                    DisplayLines = 192,
                                    BorderLeftTime = 24,
                                    BorderRightTime = 24,
                                    DisplayLineTime = 128,
                                    HorizontalBlankingTime = 40,
                                    NonVisibleBorderRightTime = 12,
                                    PixelDataPrefetchTime = 2,
                                    AttributeDataPrefetchTime = 1
                                },
                                Beeper = new AudioConfigurationData
                                {
                                    AudioSampleRate = 35469,
                                    SamplesPerFrame = 709,
                                    TactsPerSample = 100
                                },
                                Sound = new AudioConfigurationData
                                {
                                    AudioSampleRate = 27710,
                                    SamplesPerFrame = 553,
                                    TactsPerSample = 128
                                },
                                Floppy = new FloppyConfiguration
                                {
                                    FloppyPresent = true,
                                    DriveBPresent = false
                                }
                            }
                        },
                        {
                            FLOPPY2, new SpectrumEdition
                            {
                                Cpu = new CpuConfigurationData
                                {
                                    BaseClockFrequency = 3_546_900,
                                    ClockMultiplier = 1,
                                    SupportsNextOperations = false
                                },
                                Rom = new RomConfigurationData
                                {
                                    RomName = "ZxSpectrumP3E",
                                    NumberOfRoms = 4,
                                    Spectrum48RomIndex = 3
                                },
                                Memory = new MemoryConfigurationData
                                {
                                    SupportsBanking = true,
                                    RamBanks = 8,
                                    ContentionType = MemoryContentionType.GateArray
                                },
                                Screen = new ScreenConfigurationData
                                {
                                    InterruptTact = 14,
                                    VerticalSyncLines = 8,
                                    NonVisibleBorderTopLines = 7,
                                    BorderTopLines = 48,
                                    BorderBottomLines = 48,
                                    NonVisibleBorderBottomLines = 8,
                                    DisplayLines = 192,
                                    BorderLeftTime = 24,
                                    BorderRightTime = 24,
                                    DisplayLineTime = 128,
                                    HorizontalBlankingTime = 40,
                                    NonVisibleBorderRightTime = 12,
                                    PixelDataPrefetchTime = 2,
                                    AttributeDataPrefetchTime = 1
                                },
                                Beeper = new AudioConfigurationData
                                {
                                    AudioSampleRate = 35469,
                                    SamplesPerFrame = 709,
                                    TactsPerSample = 100
                                },
                                Sound = new AudioConfigurationData
                                {
                                    AudioSampleRate = 27710,
                                    SamplesPerFrame = 553,
                                    TactsPerSample = 128
                                },
                                Floppy = new FloppyConfiguration
                                {
                                    FloppyPresent = true,
                                    DriveBPresent = true
                                }
                            }
                        }
                    }
                }
            },
            {
                ZX_SPECTRUM_NEXT, new SpectrumModelEditions
                {
                    Editions = new Dictionary<string, SpectrumEdition>
                    {
                        {
                            PAL, new SpectrumEdition
                            {
                                Cpu = new CpuConfigurationData
                                {
                                    BaseClockFrequency = 3_546_900,
                                    ClockMultiplier = 1,
                                    SupportsNextOperations = true
                                },
                                Rom = new RomConfigurationData
                                {
                                    RomName = "ZxSpectrumNext",
                                    NumberOfRoms = 5,
                                    Spectrum48RomIndex = 3
                                },
                                Memory = new MemoryConfigurationData
                                {
                                    SupportsBanking = true,
                                    RamBanks = 8,
                                    ContentionType = MemoryContentionType.GateArray
                                },
                                Screen = new ScreenConfigurationData
                                {
                                    InterruptTact = 26,
                                    VerticalSyncLines = 8,
                                    NonVisibleBorderTopLines = 7,
                                    BorderTopLines = 48,
                                    BorderBottomLines = 48,
                                    NonVisibleBorderBottomLines = 8,
                                    DisplayLines = 192,
                                    BorderLeftTime = 24,
                                    BorderRightTime = 24,
                                    DisplayLineTime = 128,
                                    HorizontalBlankingTime = 40,
                                    NonVisibleBorderRightTime = 12,
                                    PixelDataPrefetchTime = 2,
                                    AttributeDataPrefetchTime = 1
                                },
                                Beeper = new AudioConfigurationData
                                {
                                    AudioSampleRate = 35469,
                                    SamplesPerFrame = 709,
                                    TactsPerSample = 100
                                },
                                Sound = new AudioConfigurationData
                                {
                                    AudioSampleRate = 27710,
                                    SamplesPerFrame = 553,
                                    TactsPerSample = 128
                                }
                            }
                        }
                    }
                }
            }
        };

        /// <summary>
        /// Key for ZX Spectrum 48K
        /// </summary>
        public const string ZX_SPECTRUM_48 = "ZX Spectrum 48K";

        /// <summary>
        /// Key for ZX Spectrum 128K
        /// </summary>
        public const string ZX_SPECTRUM_128 = "ZX Spectrum 128K";

        /// <summary>
        /// Key for ZX Spectrum +3E
        /// </summary>
        public const string ZX_SPECTRUM_P3_E = "ZX Spectrum +3E";

        /// <summary>
        /// Key for ZX Spectrum Next
        /// </summary>
        public const string ZX_SPECTRUM_NEXT = "ZX Spectrum Next";

        /// <summary>
        /// Key for PAL revisions
        /// </summary>
        public const string PAL = "PAL";

        /// <summary>
        /// Key for PAL with ULA 2 revision
        /// </summary>
        public const string PAL2 = "PAL2";

        /// <summary>
        /// Key for NTSC revisions
        /// </summary>
        public const string NTSC = "NTSC";

        /// <summary>
        /// Key for PAL turbo revisions
        /// </summary>
        public const string PAL_2_X = "PAL2X";

        /// <summary>
        /// Key for NTSC revisions
        /// </summary>
        public const string NTSC_2_X = "NTSC2X";

        /// <summary>
        /// Key for single floppy
        /// </summary>
        public const string FLOPPY1 = "FLOPPY1";

        /// <summary>
        /// Key for double floppy
        /// </summary>
        public const string FLOPPY2 = "FLOPPY2";

        /// <summary>
        /// The Spectrum models available 
        /// </summary>
        public static IReadOnlyDictionary<string, SpectrumModelEditions> StockModels => s_StockModels;

        /// <summary>
        /// Shortcut to access ZX Spectrum 48K model PAL Revision
        /// </summary>
        public static SpectrumEdition ZxSpectrum48Pal => 
            StockModels[ZX_SPECTRUM_48].Editions[PAL].Clone();

        /// <summary>
        /// Shortcut to access ZX Spectrum 48K model PAL ULA 2 Revision
        /// </summary>
        public static SpectrumEdition ZxSpectrum48Pal2 =>
            StockModels[ZX_SPECTRUM_48].Editions[PAL2].Clone();

        /// <summary>
        /// Shortcut to access ZX Spectrum 48K model PAL Revision
        /// </summary>
        public static SpectrumEdition ZxSpectrum48Ntsc =>
            StockModels[ZX_SPECTRUM_48].Editions[NTSC].Clone();

        /// <summary>
        /// Shortcut to access ZX Spectrum 48K model PAL Revision
        /// </summary>
        public static SpectrumEdition ZxSpectrum48Pal2X =>
            StockModels[ZX_SPECTRUM_48].Editions[PAL_2_X].Clone();

        /// <summary>
        /// Shortcut to access ZX Spectrum 48K model PAL Revision
        /// </summary>
        public static SpectrumEdition ZxSpectrum48Ntsc2X =>
            StockModels[ZX_SPECTRUM_48].Editions[NTSC_2_X].Clone();

        /// <summary>
        /// Shortcut to access ZX Spectrum 128K model PAL Revision
        /// </summary>
        public static SpectrumEdition ZxSpectrum128Pal =>
            StockModels[ZX_SPECTRUM_128].Editions[PAL].Clone();

        /// <summary>
        /// Shortcut to access ZX Spectrum +3E model PAL Revision
        /// </summary>
        public static SpectrumEdition ZxSpectrumP3EPal =>
            StockModels[ZX_SPECTRUM_P3_E].Editions[PAL].Clone();

        /// <summary>
        /// Shortcut to access ZX Spectrum +3E model PAL Revision + 1 floppy
        /// </summary>
        public static SpectrumEdition ZxSpectrumP3EFloppy1 =>
            StockModels[ZX_SPECTRUM_P3_E].Editions[FLOPPY1].Clone();

        /// <summary>
        /// Shortcut to access ZX Spectrum +3E model PAL Revision + 2 floppy
        /// </summary>
        public static SpectrumEdition ZxSpectrumP3EFloppy2 =>
            StockModels[ZX_SPECTRUM_P3_E].Editions[FLOPPY2].Clone();

        /// <summary>
        /// Shortcut to access ZX Spectrum Next model PAL Revision
        /// </summary>
        public static SpectrumEdition ZxSpectrumNextPal =>
            StockModels[ZX_SPECTRUM_NEXT].Editions[PAL].Clone();

        /// <summary>
        /// Gets the model type enumeration from the model name
        /// </summary>
        /// <returns>Spectrum model enumeration</returns>
        public static SpectrumModelType GetModelTypeFromName(string modelName)
        {
            switch (modelName)
            {
                case ZX_SPECTRUM_NEXT:
                    return SpectrumModelType.Next;
                case ZX_SPECTRUM_P3_E:
                    return SpectrumModelType.SpectrumP3;
                case ZX_SPECTRUM_128:
                    return SpectrumModelType.Spectrum128;
                default:
                    return SpectrumModelType.Spectrum48;
            }
        }

        /// <summary>
        /// Checks if the specified Spectrum model of the project in compatible with the 
        /// specified model type
        /// </summary>
        /// <param name="modelName">Spectrum model name</param>
        /// <param name="type">Model type</param>
        /// <returns>
        /// True, if the project's Spectrum model is compatible with the specified one;
        /// otherwise, false
        /// </returns>
        public static bool IsModelCompatibleWith(string modelName, SpectrumModelType type)
        {
            switch (type)
            {
                case SpectrumModelType.Next:
                    return modelName == ZX_SPECTRUM_NEXT;
                case SpectrumModelType.SpectrumP3:
                    return modelName == ZX_SPECTRUM_P3_E;
                case SpectrumModelType.Spectrum128:
                    return modelName == ZX_SPECTRUM_128;
                case SpectrumModelType.Spectrum48:
                    return true;
                default:
                    return false;
            }
        }
    }
}

<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/ToolWindows/Keyboard/KeyboardToolWindowViewModel.cs<|end_filename|>
﻿namespace Spect.Net.VsPackage.ToolWindows.Keyboard
{
    /// <summary>
    /// The view model of the Keyboard tool window
    /// </summary>
    public class KeyboardToolWindowViewModel : SpectrumToolWindowViewModelBase
    {
        private KeyboardLayoutTypeOptions _keyboardLayoutType;
        private KeyboardFitTypeOptions _keyboardFitType;

        public bool Initialized { get; set; } = false;

        /// <summary>
        /// Keyboard layout type
        /// </summary>
        public KeyboardLayoutTypeOptions KeyboardLayoutType
        {
            get => _keyboardLayoutType;
            set
            {
                if (Set(ref _keyboardLayoutType, value))
                {
                    RaisePropertyChanged(nameof(IsSpectrum48Layout));
                }
            }
        }

        /// <summary>
        /// Spectrum 48 layout is selected?
        /// </summary>
        public bool IsSpectrum48Layout =>
            KeyboardLayoutType == KeyboardLayoutTypeOptions.Default && SpectNetPackage.IsSpectrum48Model()
            || KeyboardLayoutType == KeyboardLayoutTypeOptions.Spectrum48;

        /// <summary>
        /// Keyboard fit type
        /// </summary>
        public KeyboardFitTypeOptions KeyboardFitType
        {
            get => _keyboardFitType;
            set
            {
                if (!Set(ref _keyboardFitType, value)) return;
                RaisePropertyChanged(nameof(IsOriginalSize));
            }
        }

        /// <summary>
        /// Is the keyboard displayed in original size?
        /// </summary>
        public bool IsOriginalSize => _keyboardFitType == KeyboardFitTypeOptions.OriginalSize;

        /// <summary>
        /// Instantiates this view model
        /// </summary>
        public KeyboardToolWindowViewModel()
        {
            if (IsInDesignMode)
            {
                KeyboardLayoutType = KeyboardLayoutTypeOptions.Spectrum128;
                KeyboardFitType = KeyboardFitTypeOptions.OriginalSize;
                return;
            }

            Initialized = false;
        }

        public void Initialize()
        {
            if (Initialized) return;
            Initialized = true;

            KeyboardLayoutType = SpectNetPackage.Default.Options.KeyboardLayoutType;
            KeyboardFitType = SpectNetPackage.Default.Options.KeyboardFitType;

            SpectNetPackage.Default.Options.KeyboardLayoutTypeChanged
                += OnKeyboardLayoutTypeChanged;
            SpectNetPackage.Default.Options.KeyboardFitTypeChanged
                += OnKeyboardFitTypeChanged;
        }
        /// <summary>
        /// Handle the event when the keyboard layout type has changed
        /// </summary>
        private void OnKeyboardLayoutTypeChanged(object sender, KeyboardLayoutTypeChangedEventArgs args)
        {
            KeyboardLayoutType = args.LayoutType;
        }

        /// <summary>
        /// Handle the event when the keyboard fit type has changed
        /// </summary>
        private void OnKeyboardFitTypeChanged(object sender, KeyboardFitTypeChangedEventArgs args)
        {
            KeyboardFitType = args.FitType;
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, 
        /// or resetting unmanaged resources.
        /// </summary>
        public override void Dispose()
        {
            SpectNetPackage.Default.Options.KeyboardLayoutTypeChanged
                -= OnKeyboardLayoutTypeChanged;
            SpectNetPackage.Default.Options.KeyboardFitTypeChanged
                -= OnKeyboardFitTypeChanged;
            base.Dispose();
        }
    }
}

<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/Commands/SetAsDefaultCodeFileCommand.cs<|end_filename|>
﻿using Microsoft.VisualStudio.Shell;
using Spect.Net.VsPackage.VsxLibrary.Command;
using Task = System.Threading.Tasks.Task;

namespace Spect.Net.VsPackage.Commands
{
    /// <summary>
    /// Sets the specified annotation file as the default one to use
    /// </summary>
    [CommandId(0x0805)]
    public class SetAsDefaultCodeFileCommand : SpectrumProgramCommandBase
    {
        /// <summary>
        /// Override this method to define the status query action
        /// </summary>
        /// <param name="mc"></param>
        protected override void OnQueryStatus(OleMenuCommand mc)
        {
            base.OnQueryStatus(mc);
            if (!mc.Visible) return;
            var item = ItemPath;
            var dteItem = SpectNetPackage.Default.Solution.GetProjectOfFile(item)?.GetDteProjectItem(item);
            if (dteItem == null || dteItem.Properties.Item("IsDependentFile").Value.Equals(true))
            {
                mc.Visible = false;
            }
        }

        /// <summary>
        /// Override this method to define the async command body te execute on the
        /// background thread
        /// </summary>
        protected override Task ExecuteAsync()
        {
            SpectrumProject?.SetDefaultCodeItem(this);
            return Task.FromResult(0);
        }
    }
}

<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/Compilers/ZxbOptions.cs<|end_filename|>
﻿namespace Spect.Net.VsPackage.Compilers
{
    /// <summary>
    /// This class represents the command line options of the ZXB executable.
    /// </summary>
    public class ZxbOptions
    {
        private ushort _optimize = 1;

        /// <summary>
        /// Signs in raw arguments are used.
        /// </summary>
        public string RawArgs { get; set; }

        /// <summary>
        /// Sets the program file name.
        /// </summary>
        public string ProgramFilename { get; set; }

        /// <summary>
        /// --optimize
        /// The default optimization level is 1. Setting this to a value greater than 1 will enable
        /// the compiler code optimizations (e.g.Peephole optimizer). Setting this to 0 will produce
        /// slower code, but could be useful for debugging purposes (both for the compiler or the BASIC
        /// program). A value of 3 will enable aggressive optimizations not fully tested yet! So, beware!
        /// </summary>
        public ushort Optimize
        {
            get => _optimize;
            set
            {
                _optimize = value;
                if (_optimize < 1) _optimize = 1;
                else if (_optimize > 4) _optimize = 4;
            }
        }

        /// <summary>
        /// --output
        /// Sets the output file name. By default it will be the same as the input file, but with the
        /// extension changed as appropriated (.BIN, .TAP, .ASM, .TZX).
        /// </summary>
        public string OutputFilename { get; set; }

        /// <summary>
        /// --stderr
        /// This specifies an output file name for error messages. This is useful if you want to capture
        /// compilation error messages (for example, to call ZX BASIC compiler from within an IDE).
        /// </summary>
        public string ErrorFilename { get; set; }

        /// <summary>
        /// --tzx
        /// Outputs the binary result in TZX Format. This format can be converted to sound (.WAV or .MP3).
        /// </summary>
        public bool? TzxFormat { get; set; }

        /// <summary>
        /// --tap
        /// Outputs the binary result in TAP Format.
        /// </summary>
        public bool? TapFormat { get; set; }

        /// <summary>
        /// --BASIC
        /// This is a very useful option. It will prepend a ZX spectrum BASIC loader that will load the
        /// rest of your binary compiled program. This option requires the --tap or --tzx to be specified.
        /// This way you can type LOAD "" to load your program.
        /// </summary>
        public bool? BasicLoader { get; set; }

        /// <summary>
        /// --autorun
        /// Makes your program to run automatically. If specified with the -B or --basic option, your program
        /// will automatically run if loaded with LOAD "". If --BASIC is not used this option is ignored.
        /// </summary>
        public bool? AutoRun { get; set; }

        /// <summary>
        /// --org
        /// This will change the default machine code ORiGin. By default your code will start at memory position
        /// 32768 (8000h). But you can change this with this parameter.
        /// </summary>
        public ushort OrgValue { get; set; } = 0x8000;

        /// <summary>
        /// --stderr
        /// This specifies an output file name for error msgs. This is useful if you want to capture compilation
        /// error messages (for example, to call ZX BASIC compiler from within an IDE).
        /// </summary>
        public string StdErr { get; set; }

        /// <summary>
        /// --array-base
        /// Unlike original Sinclair BASIC, array indexes starts from 0, not from 1 (see DIM). You can change this
        /// behavior. For example setting --array-base=1 will make array indexes start from 1 (like in Sinclair BASIC).
        /// This option (array-base=1) is active when --sinclair compatibility flag is specified.
        /// </summary>
        public bool? ArrayBaseOne { get; set; }

        /// <summary>
        /// --string-base
        /// Unlike original Sinclair BASIC, string indexes starts from 0, not from 1. That is, in ZX BASIC, a$(1)
        /// is the 2nd letter in a$ string variable, and a$(0) the 1st. You can change this behavior, setting which
        /// position in the string refers to the 1st letter. For example, setting --string-base=1 will make strings
        /// start from 1 (like in Sinclair BASIC). This option (string-base=1) is active when --sinclair compatibility
        /// flag is specified.
        /// </summary>
        public bool? StringBaseOne { get; set; }

        /// <summary>
        /// --heap-size
        /// Set the size of the heap. Default heap size is above 4K (4768 bytes exactly). The heap is a memory zone
        /// used to store and manipulate strings (and other dynamic size objects where available) If you don't make
        /// use of strings, you can get back part of the heap memory. You might also need more heap space, so set it
        /// with this flag. The heap zone comes at the end of your program, and it size is fixed (won't change during
        /// program execution).
        /// </summary>
        public ushort HeapSize { get; set; } = 0x1000;

        /// <summary>
        /// --debug-memory
        /// During your program execution, using strings might fail due to lack of memory, but your program won't
        /// report it will continue executing (except the strings not fitting into the heap will be converted to
        /// NULL string or ""). The same applies to other dynamic objects. So enabling this flag, will make your
        /// program to stop reporting a ROM Out of memory error. This will add a little overhead to your program
        /// execution, but it's useful to detect Out of Memory errors.
        /// </summary>
        public bool? DebugMemory { get; set; }

        /// <summary>
        /// --debug-array
        /// As above, using wrong subscript (out of range) in arrays won't trigger an error. Setting this flag will
        /// raise ROM error Subscript out of Range. This flag will add a little overhead to your program execution,
        /// but it's useful to detect Out of Range errors.
        /// </summary>
        public bool? DebugArray { get; set; }

        /// <summary>
        /// --strict-bool
        /// By default, ZX BASIC will treat boolean values as 0 = False, Any other value = True. Some programmers
        /// expect TRUE = 1 always. Using this option will enforce boolean results to be always 0 or 1. Using this
        /// option might add a little overhead to your program. Using --sinclair option will also enable this feature.
        /// </summary>
        public bool? StrictBool { get; set; }

        /// <summary>
        /// --enable-break
        /// Unlike Sinclair BASIC, Your program, being converted to machine code, won't be affected by BREAK. If
        /// you enable this flag, you will be able to stop your program pressing BREAK (Shift + SPACE). The ROM Break
        /// message will also report the line in which the program was interrupted. This option will add some
        /// overhead to your program.
        /// </summary>
        public bool? EnableBreak { get; set; }

        /// <summary>
        /// --explicit
        /// Requires all variables to be declared with DIM before being used. This is something similar to Sinclair
        /// BASIC, in which when you tried to read a variable not previously set, a "Variable not Found" error was
        /// triggered. This option is really useful and you should enable it for large programs.
        /// </summary>
        public bool? ExplicitDim { get; set; }

        /// <summary>
        /// --strict
        /// Requires all variables (and parameters and functions!) to have an explicit type declared (e.g. Uinteger).
        /// Otherwise, forgetting a type will cause an error and the program won't compile. This is very useful to
        /// avoid forgetting type declarations. When the type is explicitly declared the compiler can make better
        /// assumptions and further error checking and optimizations.
        /// </summary>
        public bool? StrictTypes { get; set; }

        /// <summary>Returns a string that represents the current object.</summary>
        /// <returns>A string that represents the current object.</returns>
        public override string ToString()
        {
            var argRoot = $"\"{ProgramFilename}\" "
                + $"--output \"{OutputFilename}\" "
                + "--asm ";
            var additional = string.IsNullOrWhiteSpace(RawArgs)
                ? (ArrayBaseOne ?? false ? "--array-base=1 " : "")
                    + $"--optimize {Optimize} "
                    + $"--org {OrgValue} "
                    + $"--heap-size {HeapSize} "
                    + "--sinclair "
                    + (StringBaseOne ?? false ? "--string-base=1 " : "")
                    + (TzxFormat ?? false ? "--tzx " : "")
                    + (TapFormat ?? false ? "--tap " : "")
                    + (BasicLoader ?? false ? "--BASIC " : "")
                    + (AutoRun ?? false ? "--autorun " : "")
                    + (DebugMemory ?? false ? "--debug-memory " : "")
                    + (DebugArray ?? false ? "--debug-array " : "")
                    + (StrictBool ?? false ? "--strict-bool " : "")
                    + (EnableBreak ?? false ? "--enable-break " : "")
                    + (ExplicitDim ?? false ? "--explicit " : "")
                    + (StrictTypes ?? false ? "--strict " : "")
                : RawArgs;
            return (argRoot + additional).Trim();
        }
    }
}


<|start_filename|>v2/Assembler/Spect.Net.BasicParser/Generated/ZxBasicLexer.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     ANTLR Version: 4.6.4
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

// Generated from C:\Users\dotne\source\repos\spectnetide\v2\Assembler\AntlrZxBasicParserGenerator\AntlrZxBasicParserGenerator\ZxBasic.g4 by ANTLR 4.6.4

// Unreachable code detected
#pragma warning disable 0162
// The variable '...' is assigned but its value is never used
#pragma warning disable 0219
// Missing XML comment for publicly visible type or member '...'
#pragma warning disable 1591
// Ambiguous reference in cref attribute
#pragma warning disable 419

namespace Spect.Net.BasicParser.Generated {
using Antlr4.Runtime;
using Antlr4.Runtime.Atn;
using Antlr4.Runtime.Misc;
using DFA = Antlr4.Runtime.Dfa.DFA;

[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.6.4")]
[System.CLSCompliant(false)]
public partial class ZxBasicLexer : Lexer {
	public const int
		WS=1, NEWL=2, COLON=3, UNDERSCORE=4, SINGLE_QUOTE=5, SLASH=6, DOLLAR=7, 
		SCOLON=8, COMMA=9, ASSIGN=10, LPAR=11, RPAR=12, LSBRAC=13, RSBRAC=14, 
		QMARK=15, PLUS=16, MINUS=17, VBAR=18, UPARR=19, AMP=20, LTOP=21, LTEOP=22, 
		GTOP=23, GTEOP=24, LSHOP=25, RSHOP=26, MULOP=27, DOT=28, HMARK=29, LBRAC=30, 
		RBRAC=31, EXCLM=32, DECNUM=33, REALNUM=34, BLOCK_COMMENT=35, LINE_COMMENT=36, 
		NOTEQ=37, P_DEFINE=38, P_ELSE=39, P_ELSEIF=40, P_ENDIF=41, P_IF=42, P_IFDEF=43, 
		P_IFNDEF=44, P_INCLIB=45, P_INCLUDE=46, P_LINE=47, P_PRAGMA=48, P_REQUIRE=49, 
		P_UNDEF=50, P_DINCLUDE=51, END_ASM=52, ABS=53, ACS=54, AND=55, ALIGN=56, 
		ASC=57, ASM=58, ASN=59, AS=60, AT=61, ATN=62, ATTR=63, BAND=64, BNOT=65, 
		BOR=66, BXOR=67, BEEP=68, BOLD=69, BORDER=70, BRIGHT=71, BYREF=72, BYTE=73, 
		BYVAL=74, CAST=75, CLEAR=76, CHR=77, CIRCLE=78, CLS=79, CODE=80, CONST=81, 
		CONTINUE=82, COS=83, CSRLIN=84, DECLARE=85, DIM=86, DO=87, DATA=88, DRAW=89, 
		ELSE=90, ELSEIF=91, END=92, EXIT=93, EXP=94, FASTCALL=95, FIXED=96, FLASH=97, 
		FLOAT=98, FOR=99, FUNCTION=100, GETKEY=101, GETKEYSCANCODE=102, GO=103, 
		GOTO=104, GOSUB=105, HEX=106, HEX16=107, IF=108, IN=109, INK=110, INKEY=111, 
		INPUT=112, INT=113, INTEGER=114, INVERSE=115, ITALIC=116, LBOUND=117, 
		LCASE=118, LET=119, LEN=120, LN=121, LOAD=122, LONG=123, LOOP=124, MOD=125, 
		MULTIKEYS=126, NEXT=127, NOT=128, OR=129, OVER=130, OUT=131, PAPER=132, 
		PAUSE=133, PEEK=134, PI=135, PLOT=136, POINT=137, POKE=138, POS=139, PRINT=140, 
		PRINT42=141, PRINTAT42=142, PRINT64=143, PRINTAT64=144, RANDOMIZE=145, 
		READ=146, REM=147, RESTORE=148, RETURN=149, RND=150, SAVE=151, SCREEN=152, 
		SGN=153, SHL=154, SHR=155, SIN=156, SQR=157, STDCALL=158, STEP=159, STOP=160, 
		STR=161, STRING=162, SUB=163, TAB=164, TAN=165, THEN=166, TO=167, UBOUND=168, 
		UBYTE=169, UCASE=170, UINTEGER=171, ULONG=172, UNTIL=173, VAL=174, VERIFY=175, 
		WEND=176, WHILE=177, XOR=178, HEXNUM=179, BINNUM=180, IDENTIFIER=181, 
		IDSTART=182, IDCONT=183, ZXB_STRING=184, ZXB_FSTRING=185, LINE_END=186, 
		ErrorCharacter=187;
	public static string[] modeNames = {
		"DEFAULT_MODE"
	};

	public static readonly string[] ruleNames = {
		"WS", "NEWL", "COLON", "UNDERSCORE", "SINGLE_QUOTE", "SLASH", "DOLLAR", 
		"SCOLON", "COMMA", "ASSIGN", "LPAR", "RPAR", "LSBRAC", "RSBRAC", "QMARK", 
		"PLUS", "MINUS", "VBAR", "UPARR", "AMP", "LTOP", "LTEOP", "GTOP", "GTEOP", 
		"LSHOP", "RSHOP", "MULOP", "DOT", "HMARK", "LBRAC", "RBRAC", "EXCLM", 
		"DECNUM", "REALNUM", "BLOCK_COMMENT", "LINE_COMMENT", "NOTEQ", "P_DEFINE", 
		"P_ELSE", "P_ELSEIF", "P_ENDIF", "P_IF", "P_IFDEF", "P_IFNDEF", "P_INCLIB", 
		"P_INCLUDE", "P_LINE", "P_PRAGMA", "P_REQUIRE", "P_UNDEF", "P_DINCLUDE", 
		"END_ASM", "ABS", "ACS", "AND", "ALIGN", "ASC", "ASM", "ASN", "AS", "AT", 
		"ATN", "ATTR", "BAND", "BNOT", "BOR", "BXOR", "BEEP", "BOLD", "BORDER", 
		"BRIGHT", "BYREF", "BYTE", "BYVAL", "CAST", "CLEAR", "CHR", "CIRCLE", 
		"CLS", "CODE", "CONST", "CONTINUE", "COS", "CSRLIN", "DECLARE", "DIM", 
		"DO", "DATA", "DRAW", "ELSE", "ELSEIF", "END", "EXIT", "EXP", "FASTCALL", 
		"FIXED", "FLASH", "FLOAT", "FOR", "FUNCTION", "GETKEY", "GETKEYSCANCODE", 
		"GO", "GOTO", "GOSUB", "HEX", "HEX16", "IF", "IN", "INK", "INKEY", "INPUT", 
		"INT", "INTEGER", "INVERSE", "ITALIC", "LBOUND", "LCASE", "LET", "LEN", 
		"LN", "LOAD", "LONG", "LOOP", "MOD", "MULTIKEYS", "NEXT", "NOT", "OR", 
		"OVER", "OUT", "PAPER", "PAUSE", "PEEK", "PI", "PLOT", "POINT", "POKE", 
		"POS", "PRINT", "PRINT42", "PRINTAT42", "PRINT64", "PRINTAT64", "RANDOMIZE", 
		"READ", "REM", "RESTORE", "RETURN", "RND", "SAVE", "SCREEN", "SGN", "SHL", 
		"SHR", "SIN", "SQR", "STDCALL", "STEP", "STOP", "STR", "STRING", "SUB", 
		"TAB", "TAN", "THEN", "TO", "UBOUND", "UBYTE", "UCASE", "UINTEGER", "ULONG", 
		"UNTIL", "VAL", "VERIFY", "WEND", "WHILE", "XOR", "HEXNUM", "BINNUM", 
		"IDENTIFIER", "IDSTART", "IDCONT", "ZXB_STRING", "ZXB_FSTRING", "LINE_END", 
		"ErrorCharacter", "InputCharacter", "CommonCharacter", "SimpleEscapeSequence", 
		"HexEscapeSequence", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", 
		"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", 
		"Y", "Z", "HexDigit", "OctDigit", "Digit", "BinDigit", "ExponentPart", 
		"NewLine"
	};


	public ZxBasicLexer(ICharStream input)
		: base(input)
	{
		_interp = new LexerATNSimulator(this,_ATN);
	}

	private static readonly string[] _LiteralNames = {
		null, null, null, "':'", "'_'", "'''", "'/'", "'$'", "';'", "','", "'='", 
		"'('", "')'", "'['", "']'", "'?'", "'+'", "'-'", "'|'", "'^'", "'&'", 
		"'<'", "'<='", "'>'", "'>='", "'<<'", "'>>'", "'*'", "'.'", "'#'", "'{'", 
		"'}'", "'!'", null, null, null, null, "'<>'"
	};
	private static readonly string[] _SymbolicNames = {
		null, "WS", "NEWL", "COLON", "UNDERSCORE", "SINGLE_QUOTE", "SLASH", "DOLLAR", 
		"SCOLON", "COMMA", "ASSIGN", "LPAR", "RPAR", "LSBRAC", "RSBRAC", "QMARK", 
		"PLUS", "MINUS", "VBAR", "UPARR", "AMP", "LTOP", "LTEOP", "GTOP", "GTEOP", 
		"LSHOP", "RSHOP", "MULOP", "DOT", "HMARK", "LBRAC", "RBRAC", "EXCLM", 
		"DECNUM", "REALNUM", "BLOCK_COMMENT", "LINE_COMMENT", "NOTEQ", "P_DEFINE", 
		"P_ELSE", "P_ELSEIF", "P_ENDIF", "P_IF", "P_IFDEF", "P_IFNDEF", "P_INCLIB", 
		"P_INCLUDE", "P_LINE", "P_PRAGMA", "P_REQUIRE", "P_UNDEF", "P_DINCLUDE", 
		"END_ASM", "ABS", "ACS", "AND", "ALIGN", "ASC", "ASM", "ASN", "AS", "AT", 
		"ATN", "ATTR", "BAND", "BNOT", "BOR", "BXOR", "BEEP", "BOLD", "BORDER", 
		"BRIGHT", "BYREF", "BYTE", "BYVAL", "CAST", "CLEAR", "CHR", "CIRCLE", 
		"CLS", "CODE", "CONST", "CONTINUE", "COS", "CSRLIN", "DECLARE", "DIM", 
		"DO", "DATA", "DRAW", "ELSE", "ELSEIF", "END", "EXIT", "EXP", "FASTCALL", 
		"FIXED", "FLASH", "FLOAT", "FOR", "FUNCTION", "GETKEY", "GETKEYSCANCODE", 
		"GO", "GOTO", "GOSUB", "HEX", "HEX16", "IF", "IN", "INK", "INKEY", "INPUT", 
		"INT", "INTEGER", "INVERSE", "ITALIC", "LBOUND", "LCASE", "LET", "LEN", 
		"LN", "LOAD", "LONG", "LOOP", "MOD", "MULTIKEYS", "NEXT", "NOT", "OR", 
		"OVER", "OUT", "PAPER", "PAUSE", "PEEK", "PI", "PLOT", "POINT", "POKE", 
		"POS", "PRINT", "PRINT42", "PRINTAT42", "PRINT64", "PRINTAT64", "RANDOMIZE", 
		"READ", "REM", "RESTORE", "RETURN", "RND", "SAVE", "SCREEN", "SGN", "SHL", 
		"SHR", "SIN", "SQR", "STDCALL", "STEP", "STOP", "STR", "STRING", "SUB", 
		"TAB", "TAN", "THEN", "TO", "UBOUND", "UBYTE", "UCASE", "UINTEGER", "ULONG", 
		"UNTIL", "VAL", "VERIFY", "WEND", "WHILE", "XOR", "HEXNUM", "BINNUM", 
		"IDENTIFIER", "IDSTART", "IDCONT", "ZXB_STRING", "ZXB_FSTRING", "LINE_END", 
		"ErrorCharacter"
	};
	public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames);

	[System.Obsolete("Use Vocabulary instead.")]
	public static readonly string[] tokenNames = GenerateTokenNames(DefaultVocabulary, _SymbolicNames.Length);

	private static string[] GenerateTokenNames(IVocabulary vocabulary, int length) {
		string[] tokenNames = new string[length];
		for (int i = 0; i < tokenNames.Length; i++) {
			tokenNames[i] = vocabulary.GetLiteralName(i);
			if (tokenNames[i] == null) {
				tokenNames[i] = vocabulary.GetSymbolicName(i);
			}

			if (tokenNames[i] == null) {
				tokenNames[i] = "<INVALID>";
			}
		}

		return tokenNames;
	}

	[System.Obsolete("Use IRecognizer.Vocabulary instead.")]
	public override string[] TokenNames
	{
		get
		{
			return tokenNames;
		}
	}

	[NotNull]
	public override IVocabulary Vocabulary
	{
		get
		{
			return DefaultVocabulary;
		}
	}

	public override string GrammarFileName { get { return "ZxBasic.g4"; } }

	public override string[] RuleNames { get { return ruleNames; } }

	public override string[] ModeNames { get { return modeNames; } }

	public override string SerializedAtn { get { return _serializedATN; } }

	public static readonly string _serializedATN =
		"\x3\xAF6F\x8320\x479D\xB75C\x4880\x1605\x191C\xAB37\x2\xBD\x6A8\b\x1\x4"+
		"\x2\t\x2\x4\x3\t\x3\x4\x4\t\x4\x4\x5\t\x5\x4\x6\t\x6\x4\a\t\a\x4\b\t\b"+
		"\x4\t\t\t\x4\n\t\n\x4\v\t\v\x4\f\t\f\x4\r\t\r\x4\xE\t\xE\x4\xF\t\xF\x4"+
		"\x10\t\x10\x4\x11\t\x11\x4\x12\t\x12\x4\x13\t\x13\x4\x14\t\x14\x4\x15"+
		"\t\x15\x4\x16\t\x16\x4\x17\t\x17\x4\x18\t\x18\x4\x19\t\x19\x4\x1A\t\x1A"+
		"\x4\x1B\t\x1B\x4\x1C\t\x1C\x4\x1D\t\x1D\x4\x1E\t\x1E\x4\x1F\t\x1F\x4 "+
		"\t \x4!\t!\x4\"\t\"\x4#\t#\x4$\t$\x4%\t%\x4&\t&\x4\'\t\'\x4(\t(\x4)\t"+
		")\x4*\t*\x4+\t+\x4,\t,\x4-\t-\x4.\t.\x4/\t/\x4\x30\t\x30\x4\x31\t\x31"+
		"\x4\x32\t\x32\x4\x33\t\x33\x4\x34\t\x34\x4\x35\t\x35\x4\x36\t\x36\x4\x37"+
		"\t\x37\x4\x38\t\x38\x4\x39\t\x39\x4:\t:\x4;\t;\x4<\t<\x4=\t=\x4>\t>\x4"+
		"?\t?\x4@\t@\x4\x41\t\x41\x4\x42\t\x42\x4\x43\t\x43\x4\x44\t\x44\x4\x45"+
		"\t\x45\x4\x46\t\x46\x4G\tG\x4H\tH\x4I\tI\x4J\tJ\x4K\tK\x4L\tL\x4M\tM\x4"+
		"N\tN\x4O\tO\x4P\tP\x4Q\tQ\x4R\tR\x4S\tS\x4T\tT\x4U\tU\x4V\tV\x4W\tW\x4"+
		"X\tX\x4Y\tY\x4Z\tZ\x4[\t[\x4\\\t\\\x4]\t]\x4^\t^\x4_\t_\x4`\t`\x4\x61"+
		"\t\x61\x4\x62\t\x62\x4\x63\t\x63\x4\x64\t\x64\x4\x65\t\x65\x4\x66\t\x66"+
		"\x4g\tg\x4h\th\x4i\ti\x4j\tj\x4k\tk\x4l\tl\x4m\tm\x4n\tn\x4o\to\x4p\t"+
		"p\x4q\tq\x4r\tr\x4s\ts\x4t\tt\x4u\tu\x4v\tv\x4w\tw\x4x\tx\x4y\ty\x4z\t"+
		"z\x4{\t{\x4|\t|\x4}\t}\x4~\t~\x4\x7F\t\x7F\x4\x80\t\x80\x4\x81\t\x81\x4"+
		"\x82\t\x82\x4\x83\t\x83\x4\x84\t\x84\x4\x85\t\x85\x4\x86\t\x86\x4\x87"+
		"\t\x87\x4\x88\t\x88\x4\x89\t\x89\x4\x8A\t\x8A\x4\x8B\t\x8B\x4\x8C\t\x8C"+
		"\x4\x8D\t\x8D\x4\x8E\t\x8E\x4\x8F\t\x8F\x4\x90\t\x90\x4\x91\t\x91\x4\x92"+
		"\t\x92\x4\x93\t\x93\x4\x94\t\x94\x4\x95\t\x95\x4\x96\t\x96\x4\x97\t\x97"+
		"\x4\x98\t\x98\x4\x99\t\x99\x4\x9A\t\x9A\x4\x9B\t\x9B\x4\x9C\t\x9C\x4\x9D"+
		"\t\x9D\x4\x9E\t\x9E\x4\x9F\t\x9F\x4\xA0\t\xA0\x4\xA1\t\xA1\x4\xA2\t\xA2"+
		"\x4\xA3\t\xA3\x4\xA4\t\xA4\x4\xA5\t\xA5\x4\xA6\t\xA6\x4\xA7\t\xA7\x4\xA8"+
		"\t\xA8\x4\xA9\t\xA9\x4\xAA\t\xAA\x4\xAB\t\xAB\x4\xAC\t\xAC\x4\xAD\t\xAD"+
		"\x4\xAE\t\xAE\x4\xAF\t\xAF\x4\xB0\t\xB0\x4\xB1\t\xB1\x4\xB2\t\xB2\x4\xB3"+
		"\t\xB3\x4\xB4\t\xB4\x4\xB5\t\xB5\x4\xB6\t\xB6\x4\xB7\t\xB7\x4\xB8\t\xB8"+
		"\x4\xB9\t\xB9\x4\xBA\t\xBA\x4\xBB\t\xBB\x4\xBC\t\xBC\x4\xBD\t\xBD\x4\xBE"+
		"\t\xBE\x4\xBF\t\xBF\x4\xC0\t\xC0\x4\xC1\t\xC1\x4\xC2\t\xC2\x4\xC3\t\xC3"+
		"\x4\xC4\t\xC4\x4\xC5\t\xC5\x4\xC6\t\xC6\x4\xC7\t\xC7\x4\xC8\t\xC8\x4\xC9"+
		"\t\xC9\x4\xCA\t\xCA\x4\xCB\t\xCB\x4\xCC\t\xCC\x4\xCD\t\xCD\x4\xCE\t\xCE"+
		"\x4\xCF\t\xCF\x4\xD0\t\xD0\x4\xD1\t\xD1\x4\xD2\t\xD2\x4\xD3\t\xD3\x4\xD4"+
		"\t\xD4\x4\xD5\t\xD5\x4\xD6\t\xD6\x4\xD7\t\xD7\x4\xD8\t\xD8\x4\xD9\t\xD9"+
		"\x4\xDA\t\xDA\x4\xDB\t\xDB\x4\xDC\t\xDC\x4\xDD\t\xDD\x4\xDE\t\xDE\x4\xDF"+
		"\t\xDF\x4\xE0\t\xE0\x3\x2\x6\x2\x1C3\n\x2\r\x2\xE\x2\x1C4\x3\x2\x3\x2"+
		"\x3\x3\x3\x3\x3\x4\x3\x4\x3\x5\x3\x5\x3\x6\x3\x6\x3\a\x3\a\x3\b\x3\b\x3"+
		"\t\x3\t\x3\n\x3\n\x3\v\x3\v\x3\f\x3\f\x3\r\x3\r\x3\xE\x3\xE\x3\xF\x3\xF"+
		"\x3\x10\x3\x10\x3\x11\x3\x11\x3\x12\x3\x12\x3\x13\x3\x13\x3\x14\x3\x14"+
		"\x3\x15\x3\x15\x3\x16\x3\x16\x3\x17\x3\x17\x3\x17\x3\x18\x3\x18\x3\x19"+
		"\x3\x19\x3\x19\x3\x1A\x3\x1A\x3\x1A\x3\x1B\x3\x1B\x3\x1B\x3\x1C\x3\x1C"+
		"\x3\x1D\x3\x1D\x3\x1E\x3\x1E\x3\x1F\x3\x1F\x3 \x3 \x3!\x3!\x3\"\x3\"\a"+
		"\"\x20D\n\"\f\"\xE\"\x210\v\"\x3#\a#\x213\n#\f#\xE#\x216\v#\x3#\x3#\x6"+
		"#\x21A\n#\r#\xE#\x21B\x3#\x5#\x21F\n#\x3#\x6#\x222\n#\r#\xE#\x223\x3#"+
		"\x5#\x227\n#\x3$\x3$\x3$\a$\x22C\n$\f$\xE$\x22F\v$\x3$\x3$\x3$\x3%\x3"+
		"%\x5%\x236\n%\x3%\a%\x239\n%\f%\xE%\x23C\v%\x3&\x3&\x3&\x3\'\x3\'\x3\'"+
		"\x3\'\x3\'\x3\'\x3\'\x3\'\x3(\x3(\x3(\x3(\x3(\x3(\x3)\x3)\x3)\x3)\x3)"+
		"\x3)\x3)\x3)\x3*\x3*\x3*\x3*\x3*\x3*\x3*\x3+\x3+\x3+\x3+\x3,\x3,\x3,\x3"+
		",\x3,\x3,\x3,\x3-\x3-\x3-\x3-\x3-\x3-\x3-\x3-\x3.\x3.\x3.\x3.\x3.\x3."+
		"\x3.\x3.\x3/\x3/\x3/\x3/\x3/\x3/\x3/\x3/\x3/\x3\x30\x3\x30\x3\x30\x3\x30"+
		"\x3\x30\x3\x30\x3\x31\x3\x31\x3\x31\x3\x31\x3\x31\x3\x31\x3\x31\x3\x31"+
		"\x3\x32\x3\x32\x3\x32\x3\x32\x3\x32\x3\x32\x3\x32\x3\x32\x3\x32\x3\x33"+
		"\x3\x33\x3\x33\x3\x33\x3\x33\x3\x33\x3\x33\x3\x34\x3\x34\x3\x34\x3\x34"+
		"\x3\x34\x3\x34\x3\x34\x3\x34\x3\x34\x3\x35\x3\x35\x3\x35\x3\x35\a\x35"+
		"\x2AD\n\x35\f\x35\xE\x35\x2B0\v\x35\x3\x35\x3\x35\x3\x35\x3\x35\x3\x36"+
		"\x3\x36\x3\x36\x3\x36\x3\x37\x3\x37\x3\x37\x3\x37\x3\x38\x3\x38\x3\x38"+
		"\x3\x38\x3\x39\x3\x39\x3\x39\x3\x39\x3\x39\x3\x39\x3:\x3:\x3:\x3:\x3;"+
		"\x3;\x3;\x3;\x3<\x3<\x3<\x3<\x3=\x3=\x3=\x3>\x3>\x3>\x3?\x3?\x3?\x3?\x3"+
		"@\x3@\x3@\x3@\x3@\x3\x41\x3\x41\x3\x41\x3\x41\x3\x41\x3\x42\x3\x42\x3"+
		"\x42\x3\x42\x3\x42\x3\x43\x3\x43\x3\x43\x3\x43\x3\x44\x3\x44\x3\x44\x3"+
		"\x44\x3\x44\x3\x45\x3\x45\x3\x45\x3\x45\x3\x45\x3\x46\x3\x46\x3\x46\x3"+
		"\x46\x3\x46\x3G\x3G\x3G\x3G\x3G\x3G\x3G\x3H\x3H\x3H\x3H\x3H\x3H\x3H\x3"+
		"I\x3I\x3I\x3I\x3I\x3I\x3J\x3J\x3J\x3J\x3J\x3K\x3K\x3K\x3K\x3K\x3K\x3L"+
		"\x3L\x3L\x3L\x3L\x3M\x3M\x3M\x3M\x3M\x3M\x3N\x3N\x3N\x3N\x5N\x32E\nN\x3"+
		"O\x3O\x3O\x3O\x3O\x3O\x3O\x3P\x3P\x3P\x3P\x3Q\x3Q\x3Q\x3Q\x3Q\x3R\x3R"+
		"\x3R\x3R\x3R\x3R\x3S\x3S\x3S\x3S\x3S\x3S\x3S\x3S\x3S\x3T\x3T\x3T\x3T\x3"+
		"U\x3U\x3U\x3U\x3U\x3U\x3U\x3V\x3V\x3V\x3V\x3V\x3V\x3V\x3V\x3W\x3W\x3W"+
		"\x3W\x3X\x3X\x3X\x3Y\x3Y\x3Y\x3Y\x3Y\x3Z\x3Z\x3Z\x3Z\x3Z\x3[\x3[\x3[\x3"+
		"[\x3[\x3\\\x3\\\x3\\\x3\\\x3\\\x3\\\x3\\\x3]\x3]\x3]\x3]\x3^\x3^\x3^\x3"+
		"^\x3^\x3_\x3_\x3_\x3_\x3`\x3`\x3`\x3`\x3`\x3`\x3`\x3`\x3`\x3\x61\x3\x61"+
		"\x3\x61\x3\x61\x3\x61\x3\x61\x3\x62\x3\x62\x3\x62\x3\x62\x3\x62\x3\x62"+
		"\x3\x63\x3\x63\x3\x63\x3\x63\x3\x63\x3\x63\x3\x64\x3\x64\x3\x64\x3\x64"+
		"\x3\x65\x3\x65\x3\x65\x3\x65\x3\x65\x3\x65\x3\x65\x3\x65\x3\x65\x3\x66"+
		"\x3\x66\x3\x66\x3\x66\x3\x66\x3\x66\x3\x66\x3g\x3g\x3g\x3g\x3g\x3g\x3"+
		"g\x3g\x3g\x3g\x3g\x3g\x3g\x3g\x3g\x3h\x3h\x3h\x3i\x3i\x3i\x3i\x3i\x3i"+
		"\x3i\ai\x3D4\ni\fi\xEi\x3D7\vi\x3i\x3i\x5i\x3DB\ni\x3j\x3j\x3j\x3j\x3"+
		"j\x3j\x3j\x3j\aj\x3E5\nj\fj\xEj\x3E8\vj\x3j\x3j\x5j\x3EC\nj\x3k\x3k\x3"+
		"k\x3k\x3l\x3l\x3l\x3l\x3l\x3l\x3m\x3m\x3m\x3n\x3n\x3n\x3o\x3o\x3o\x3o"+
		"\x3p\x3p\x3p\x3p\x3p\x3p\x5p\x408\np\x3q\x3q\x3q\x3q\x3q\x3q\x3r\x3r\x3"+
		"r\x3r\x3s\x3s\x3s\x3s\x3s\x3s\x3s\x3s\x3t\x3t\x3t\x3t\x3t\x3t\x3t\x3t"+
		"\x3u\x3u\x3u\x3u\x3u\x3u\x3u\x3v\x3v\x3v\x3v\x3v\x3v\x3v\x3w\x3w\x3w\x3"+
		"w\x3w\x3w\x3x\x3x\x3x\x3x\x3y\x3y\x3y\x3y\x3z\x3z\x3z\x3{\x3{\x3{\x3{"+
		"\x3{\x3|\x3|\x3|\x3|\x3|\x3}\x3}\x3}\x3}\x3}\x3~\x3~\x3~\x3~\x3\x7F\x3"+
		"\x7F\x3\x7F\x3\x7F\x3\x7F\x3\x7F\x3\x7F\x3\x7F\x3\x7F\x3\x7F\x3\x80\x3"+
		"\x80\x3\x80\x3\x80\x3\x80\x3\x81\x3\x81\x3\x81\x3\x81\x3\x82\x3\x82\x3"+
		"\x82\x3\x83\x3\x83\x3\x83\x3\x83\x3\x83\x3\x84\x3\x84\x3\x84\x3\x84\x3"+
		"\x85\x3\x85\x3\x85\x3\x85\x3\x85\x3\x85\x3\x86\x3\x86\x3\x86\x3\x86\x3"+
		"\x86\x3\x86\x3\x87\x3\x87\x3\x87\x3\x87\x3\x87\x3\x88\x3\x88\x3\x88\x3"+
		"\x89\x3\x89\x3\x89\x3\x89\x3\x89\x3\x8A\x3\x8A\x3\x8A\x3\x8A\x3\x8A\x3"+
		"\x8A\x3\x8B\x3\x8B\x3\x8B\x3\x8B\x3\x8B\x3\x8C\x3\x8C\x3\x8C\x3\x8C\x3"+
		"\x8D\x3\x8D\x3\x8D\x3\x8D\x3\x8D\x3\x8D\x3\x8E\x3\x8E\x3\x8E\x3\x8E\x3"+
		"\x8E\x3\x8E\x3\x8E\x3\x8E\x3\x8F\x3\x8F\x3\x8F\x3\x8F\x3\x8F\x3\x8F\x3"+
		"\x8F\x3\x8F\x3\x8F\x3\x8F\x3\x90\x3\x90\x3\x90\x3\x90\x3\x90\x3\x90\x3"+
		"\x90\x3\x90\x3\x91\x3\x91\x3\x91\x3\x91\x3\x91\x3\x91\x3\x91\x3\x91\x3"+
		"\x91\x3\x91\x3\x92\x3\x92\x3\x92\x3\x92\x3\x92\x3\x92\x3\x92\x3\x92\x3"+
		"\x92\x3\x92\x3\x93\x3\x93\x3\x93\x3\x93\x3\x93\x3\x94\x3\x94\x3\x94\x3"+
		"\x94\x3\x95\x3\x95\x3\x95\x3\x95\x3\x95\x3\x95\x3\x95\x3\x95\x3\x96\x3"+
		"\x96\x3\x96\x3\x96\x3\x96\x3\x96\x3\x96\x3\x97\x3\x97\x3\x97\x3\x97\x3"+
		"\x98\x3\x98\x3\x98\x3\x98\x3\x98\x3\x99\x3\x99\x3\x99\x3\x99\x3\x99\x3"+
		"\x99\x3\x99\x3\x9A\x3\x9A\x3\x9A\x3\x9A\x3\x9B\x3\x9B\x3\x9B\x3\x9B\x3"+
		"\x9B\x5\x9B\x502\n\x9B\x3\x9C\x3\x9C\x3\x9C\x3\x9C\x3\x9C\x5\x9C\x509"+
		"\n\x9C\x3\x9D\x3\x9D\x3\x9D\x3\x9D\x3\x9E\x3\x9E\x3\x9E\x3\x9E\x3\x9F"+
		"\x3\x9F\x3\x9F\x3\x9F\x3\x9F\x3\x9F\x3\x9F\x3\x9F\x3\xA0\x3\xA0\x3\xA0"+
		"\x3\xA0\x3\xA0\x3\xA1\x3\xA1\x3\xA1\x3\xA1\x3\xA1\x3\xA2\x3\xA2\x3\xA2"+
		"\x3\xA2\x5\xA2\x529\n\xA2\x3\xA3\x3\xA3\x3\xA3\x3\xA3\x3\xA3\x3\xA3\x3"+
		"\xA3\x3\xA4\x3\xA4\x3\xA4\x3\xA4\x3\xA5\x3\xA5\x3\xA5\x3\xA5\x3\xA6\x3"+
		"\xA6\x3\xA6\x3\xA6\x3\xA7\x3\xA7\x3\xA7\x3\xA7\x3\xA7\x3\xA8\x3\xA8\x3"+
		"\xA8\x3\xA9\x3\xA9\x3\xA9\x3\xA9\x3\xA9\x3\xA9\x3\xA9\x3\xAA\x3\xAA\x3"+
		"\xAA\x3\xAA\x3\xAA\x3\xAA\x3\xAB\x3\xAB\x3\xAB\x3\xAB\x3\xAB\x3\xAB\x3"+
		"\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAD\x3"+
		"\xAD\x3\xAD\x3\xAD\x3\xAD\x3\xAD\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3"+
		"\xAE\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3"+
		"\xB0\x3\xB0\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB2\x3\xB2\x3\xB2\x3"+
		"\xB2\x3\xB2\x3\xB2\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB4\x3\xB4\x3\xB4\x5"+
		"\xB4\x58B\n\xB4\x3\xB4\x5\xB4\x58E\n\xB4\x3\xB4\x5\xB4\x591\n\xB4\x3\xB4"+
		"\x3\xB4\x5\xB4\x595\n\xB4\x3\xB4\x5\xB4\x598\n\xB4\x3\xB4\x5\xB4\x59B"+
		"\n\xB4\x3\xB4\x5\xB4\x59E\n\xB4\x3\xB4\x3\xB4\x5\xB4\x5A2\n\xB4\x3\xB5"+
		"\x3\xB5\x3\xB5\x5\xB5\x5A7\n\xB5\x3\xB5\x5\xB5\x5AA\n\xB5\x3\xB5\x5\xB5"+
		"\x5AD\n\xB5\x3\xB5\x5\xB5\x5B0\n\xB5\x3\xB5\x5\xB5\x5B3\n\xB5\x3\xB5\x5"+
		"\xB5\x5B6\n\xB5\x3\xB5\x5\xB5\x5B9\n\xB5\x3\xB5\x5\xB5\x5BC\n\xB5\x3\xB5"+
		"\x5\xB5\x5BF\n\xB5\x3\xB5\x5\xB5\x5C2\n\xB5\x3\xB5\x5\xB5\x5C5\n\xB5\x3"+
		"\xB5\x5\xB5\x5C8\n\xB5\x3\xB5\x5\xB5\x5CB\n\xB5\x3\xB5\x5\xB5\x5CE\n\xB5"+
		"\x3\xB5\x5\xB5\x5D1\n\xB5\x3\xB5\x3\xB5\x5\xB5\x5D5\n\xB5\x3\xB5\x5\xB5"+
		"\x5D8\n\xB5\x3\xB5\x5\xB5\x5DB\n\xB5\x3\xB5\x5\xB5\x5DE\n\xB5\x3\xB5\x5"+
		"\xB5\x5E1\n\xB5\x3\xB5\x5\xB5\x5E4\n\xB5\x3\xB5\x5\xB5\x5E7\n\xB5\x3\xB5"+
		"\x5\xB5\x5EA\n\xB5\x3\xB5\x5\xB5\x5ED\n\xB5\x3\xB5\x5\xB5\x5F0\n\xB5\x3"+
		"\xB5\x5\xB5\x5F3\n\xB5\x3\xB5\x5\xB5\x5F6\n\xB5\x3\xB5\x5\xB5\x5F9\n\xB5"+
		"\x3\xB5\x5\xB5\x5FC\n\xB5\x3\xB5\x5\xB5\x5FF\n\xB5\x3\xB5\x3\xB5\x5\xB5"+
		"\x603\n\xB5\x3\xB6\x3\xB6\a\xB6\x607\n\xB6\f\xB6\xE\xB6\x60A\v\xB6\x3"+
		"\xB7\x3\xB7\x3\xB8\x3\xB8\x3\xB9\x3\xB9\a\xB9\x612\n\xB9\f\xB9\xE\xB9"+
		"\x615\v\xB9\x3\xB9\x3\xB9\x3\xBA\x3\xBA\a\xBA\x61B\n\xBA\f\xBA\xE\xBA"+
		"\x61E\v\xBA\x3\xBA\x3\xBA\x3\xBB\x5\xBB\x623\n\xBB\x3\xBB\x3\xBB\x3\xBC"+
		"\x3\xBC\x3\xBD\x3\xBD\x3\xBE\x3\xBE\x5\xBE\x62D\n\xBE\x3\xBF\x3\xBF\x3"+
		"\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3"+
		"\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3"+
		"\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x5\xBF\x64C\n\xBF\x3\xC0"+
		"\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x5\xC0"+
		"\x658\n\xC0\x3\xC1\x3\xC1\x3\xC2\x3\xC2\x3\xC3\x3\xC3\x3\xC4\x3\xC4\x3"+
		"\xC5\x3\xC5\x3\xC6\x3\xC6\x3\xC7\x3\xC7\x3\xC8\x3\xC8\x3\xC9\x3\xC9\x3"+
		"\xCA\x3\xCA\x3\xCB\x3\xCB\x3\xCC\x3\xCC\x3\xCD\x3\xCD\x3\xCE\x3\xCE\x3"+
		"\xCF\x3\xCF\x3\xD0\x3\xD0\x3\xD1\x3\xD1\x3\xD2\x3\xD2\x3\xD3\x3\xD3\x3"+
		"\xD4\x3\xD4\x3\xD5\x3\xD5\x3\xD6\x3\xD6\x3\xD7\x3\xD7\x3\xD8\x3\xD8\x3"+
		"\xD9\x3\xD9\x3\xDA\x3\xDA\x3\xDB\x5\xDB\x68F\n\xDB\x3\xDC\x3\xDC\x3\xDD"+
		"\x3\xDD\x5\xDD\x695\n\xDD\x3\xDE\x3\xDE\x5\xDE\x699\n\xDE\x3\xDF\x3\xDF"+
		"\x5\xDF\x69D\n\xDF\x3\xDF\x6\xDF\x6A0\n\xDF\r\xDF\xE\xDF\x6A1\x3\xE0\x3"+
		"\xE0\x3\xE0\x5\xE0\x6A7\n\xE0\x3\x22D\x2\x2\xE1\x3\x2\x3\x5\x2\x4\a\x2"+
		"\x5\t\x2\x6\v\x2\a\r\x2\b\xF\x2\t\x11\x2\n\x13\x2\v\x15\x2\f\x17\x2\r"+
		"\x19\x2\xE\x1B\x2\xF\x1D\x2\x10\x1F\x2\x11!\x2\x12#\x2\x13%\x2\x14\'\x2"+
		"\x15)\x2\x16+\x2\x17-\x2\x18/\x2\x19\x31\x2\x1A\x33\x2\x1B\x35\x2\x1C"+
		"\x37\x2\x1D\x39\x2\x1E;\x2\x1F=\x2 ?\x2!\x41\x2\"\x43\x2#\x45\x2$G\x2"+
		"%I\x2&K\x2\'M\x2(O\x2)Q\x2*S\x2+U\x2,W\x2-Y\x2.[\x2/]\x2\x30_\x2\x31\x61"+
		"\x2\x32\x63\x2\x33\x65\x2\x34g\x2\x35i\x2\x36k\x2\x37m\x2\x38o\x2\x39"+
		"q\x2:s\x2;u\x2<w\x2=y\x2>{\x2?}\x2@\x7F\x2\x41\x81\x2\x42\x83\x2\x43\x85"+
		"\x2\x44\x87\x2\x45\x89\x2\x46\x8B\x2G\x8D\x2H\x8F\x2I\x91\x2J\x93\x2K"+
		"\x95\x2L\x97\x2M\x99\x2N\x9B\x2O\x9D\x2P\x9F\x2Q\xA1\x2R\xA3\x2S\xA5\x2"+
		"T\xA7\x2U\xA9\x2V\xAB\x2W\xAD\x2X\xAF\x2Y\xB1\x2Z\xB3\x2[\xB5\x2\\\xB7"+
		"\x2]\xB9\x2^\xBB\x2_\xBD\x2`\xBF\x2\x61\xC1\x2\x62\xC3\x2\x63\xC5\x2\x64"+
		"\xC7\x2\x65\xC9\x2\x66\xCB\x2g\xCD\x2h\xCF\x2i\xD1\x2j\xD3\x2k\xD5\x2"+
		"l\xD7\x2m\xD9\x2n\xDB\x2o\xDD\x2p\xDF\x2q\xE1\x2r\xE3\x2s\xE5\x2t\xE7"+
		"\x2u\xE9\x2v\xEB\x2w\xED\x2x\xEF\x2y\xF1\x2z\xF3\x2{\xF5\x2|\xF7\x2}\xF9"+
		"\x2~\xFB\x2\x7F\xFD\x2\x80\xFF\x2\x81\x101\x2\x82\x103\x2\x83\x105\x2"+
		"\x84\x107\x2\x85\x109\x2\x86\x10B\x2\x87\x10D\x2\x88\x10F\x2\x89\x111"+
		"\x2\x8A\x113\x2\x8B\x115\x2\x8C\x117\x2\x8D\x119\x2\x8E\x11B\x2\x8F\x11D"+
		"\x2\x90\x11F\x2\x91\x121\x2\x92\x123\x2\x93\x125\x2\x94\x127\x2\x95\x129"+
		"\x2\x96\x12B\x2\x97\x12D\x2\x98\x12F\x2\x99\x131\x2\x9A\x133\x2\x9B\x135"+
		"\x2\x9C\x137\x2\x9D\x139\x2\x9E\x13B\x2\x9F\x13D\x2\xA0\x13F\x2\xA1\x141"+
		"\x2\xA2\x143\x2\xA3\x145\x2\xA4\x147\x2\xA5\x149\x2\xA6\x14B\x2\xA7\x14D"+
		"\x2\xA8\x14F\x2\xA9\x151\x2\xAA\x153\x2\xAB\x155\x2\xAC\x157\x2\xAD\x159"+
		"\x2\xAE\x15B\x2\xAF\x15D\x2\xB0\x15F\x2\xB1\x161\x2\xB2\x163\x2\xB3\x165"+
		"\x2\xB4\x167\x2\xB5\x169\x2\xB6\x16B\x2\xB7\x16D\x2\xB8\x16F\x2\xB9\x171"+
		"\x2\xBA\x173\x2\xBB\x175\x2\xBC\x177\x2\xBD\x179\x2\x2\x17B\x2\x2\x17D"+
		"\x2\x2\x17F\x2\x2\x181\x2\x2\x183\x2\x2\x185\x2\x2\x187\x2\x2\x189\x2"+
		"\x2\x18B\x2\x2\x18D\x2\x2\x18F\x2\x2\x191\x2\x2\x193\x2\x2\x195\x2\x2"+
		"\x197\x2\x2\x199\x2\x2\x19B\x2\x2\x19D\x2\x2\x19F\x2\x2\x1A1\x2\x2\x1A3"+
		"\x2\x2\x1A5\x2\x2\x1A7\x2\x2\x1A9\x2\x2\x1AB\x2\x2\x1AD\x2\x2\x1AF\x2"+
		"\x2\x1B1\x2\x2\x1B3\x2\x2\x1B5\x2\x2\x1B7\x2\x2\x1B9\x2\x2\x1BB\x2\x2"+
		"\x1BD\x2\x2\x1BF\x2\x2\x3\x2%\x4\x2\v\v\"\"\x3\x2\x32;\x4\x2JJjj\x4\x2"+
		"\x44\x44\x64\x64\x5\x2\x43\\\x61\x61\x63|\a\x2&&\x32;\x43\\\x61\x61\x63"+
		"|\a\x2\f\f\xF\xF$$\x87\x87\x202A\x202B\x6\x2\f\f\xF\xF\x87\x87\x202A\x202B"+
		"\x4\x2\x43\x43\x63\x63\x4\x2\x45\x45\x65\x65\x4\x2\x46\x46\x66\x66\x4"+
		"\x2GGgg\x4\x2HHhh\x4\x2IIii\x4\x2KKkk\x4\x2LLll\x4\x2MMmm\x4\x2NNnn\x4"+
		"\x2OOoo\x4\x2PPpp\x4\x2QQqq\x4\x2RRrr\x4\x2SSss\x4\x2TTtt\x4\x2UUuu\x4"+
		"\x2VVvv\x4\x2WWww\x4\x2XXxx\x4\x2YYyy\x4\x2ZZzz\x4\x2[[{{\x4\x2\\\\||"+
		"\x5\x2\x32;\x43H\x63h\x3\x2\x32\x39\x4\x2--//\x6D7\x2\x3\x3\x2\x2\x2\x2"+
		"\x5\x3\x2\x2\x2\x2\a\x3\x2\x2\x2\x2\t\x3\x2\x2\x2\x2\v\x3\x2\x2\x2\x2"+
		"\r\x3\x2\x2\x2\x2\xF\x3\x2\x2\x2\x2\x11\x3\x2\x2\x2\x2\x13\x3\x2\x2\x2"+
		"\x2\x15\x3\x2\x2\x2\x2\x17\x3\x2\x2\x2\x2\x19\x3\x2\x2\x2\x2\x1B\x3\x2"+
		"\x2\x2\x2\x1D\x3\x2\x2\x2\x2\x1F\x3\x2\x2\x2\x2!\x3\x2\x2\x2\x2#\x3\x2"+
		"\x2\x2\x2%\x3\x2\x2\x2\x2\'\x3\x2\x2\x2\x2)\x3\x2\x2\x2\x2+\x3\x2\x2\x2"+
		"\x2-\x3\x2\x2\x2\x2/\x3\x2\x2\x2\x2\x31\x3\x2\x2\x2\x2\x33\x3\x2\x2\x2"+
		"\x2\x35\x3\x2\x2\x2\x2\x37\x3\x2\x2\x2\x2\x39\x3\x2\x2\x2\x2;\x3\x2\x2"+
		"\x2\x2=\x3\x2\x2\x2\x2?\x3\x2\x2\x2\x2\x41\x3\x2\x2\x2\x2\x43\x3\x2\x2"+
		"\x2\x2\x45\x3\x2\x2\x2\x2G\x3\x2\x2\x2\x2I\x3\x2\x2\x2\x2K\x3\x2\x2\x2"+
		"\x2M\x3\x2\x2\x2\x2O\x3\x2\x2\x2\x2Q\x3\x2\x2\x2\x2S\x3\x2\x2\x2\x2U\x3"+
		"\x2\x2\x2\x2W\x3\x2\x2\x2\x2Y\x3\x2\x2\x2\x2[\x3\x2\x2\x2\x2]\x3\x2\x2"+
		"\x2\x2_\x3\x2\x2\x2\x2\x61\x3\x2\x2\x2\x2\x63\x3\x2\x2\x2\x2\x65\x3\x2"+
		"\x2\x2\x2g\x3\x2\x2\x2\x2i\x3\x2\x2\x2\x2k\x3\x2\x2\x2\x2m\x3\x2\x2\x2"+
		"\x2o\x3\x2\x2\x2\x2q\x3\x2\x2\x2\x2s\x3\x2\x2\x2\x2u\x3\x2\x2\x2\x2w\x3"+
		"\x2\x2\x2\x2y\x3\x2\x2\x2\x2{\x3\x2\x2\x2\x2}\x3\x2\x2\x2\x2\x7F\x3\x2"+
		"\x2\x2\x2\x81\x3\x2\x2\x2\x2\x83\x3\x2\x2\x2\x2\x85\x3\x2\x2\x2\x2\x87"+
		"\x3\x2\x2\x2\x2\x89\x3\x2\x2\x2\x2\x8B\x3\x2\x2\x2\x2\x8D\x3\x2\x2\x2"+
		"\x2\x8F\x3\x2\x2\x2\x2\x91\x3\x2\x2\x2\x2\x93\x3\x2\x2\x2\x2\x95\x3\x2"+
		"\x2\x2\x2\x97\x3\x2\x2\x2\x2\x99\x3\x2\x2\x2\x2\x9B\x3\x2\x2\x2\x2\x9D"+
		"\x3\x2\x2\x2\x2\x9F\x3\x2\x2\x2\x2\xA1\x3\x2\x2\x2\x2\xA3\x3\x2\x2\x2"+
		"\x2\xA5\x3\x2\x2\x2\x2\xA7\x3\x2\x2\x2\x2\xA9\x3\x2\x2\x2\x2\xAB\x3\x2"+
		"\x2\x2\x2\xAD\x3\x2\x2\x2\x2\xAF\x3\x2\x2\x2\x2\xB1\x3\x2\x2\x2\x2\xB3"+
		"\x3\x2\x2\x2\x2\xB5\x3\x2\x2\x2\x2\xB7\x3\x2\x2\x2\x2\xB9\x3\x2\x2\x2"+
		"\x2\xBB\x3\x2\x2\x2\x2\xBD\x3\x2\x2\x2\x2\xBF\x3\x2\x2\x2\x2\xC1\x3\x2"+
		"\x2\x2\x2\xC3\x3\x2\x2\x2\x2\xC5\x3\x2\x2\x2\x2\xC7\x3\x2\x2\x2\x2\xC9"+
		"\x3\x2\x2\x2\x2\xCB\x3\x2\x2\x2\x2\xCD\x3\x2\x2\x2\x2\xCF\x3\x2\x2\x2"+
		"\x2\xD1\x3\x2\x2\x2\x2\xD3\x3\x2\x2\x2\x2\xD5\x3\x2\x2\x2\x2\xD7\x3\x2"+
		"\x2\x2\x2\xD9\x3\x2\x2\x2\x2\xDB\x3\x2\x2\x2\x2\xDD\x3\x2\x2\x2\x2\xDF"+
		"\x3\x2\x2\x2\x2\xE1\x3\x2\x2\x2\x2\xE3\x3\x2\x2\x2\x2\xE5\x3\x2\x2\x2"+
		"\x2\xE7\x3\x2\x2\x2\x2\xE9\x3\x2\x2\x2\x2\xEB\x3\x2\x2\x2\x2\xED\x3\x2"+
		"\x2\x2\x2\xEF\x3\x2\x2\x2\x2\xF1\x3\x2\x2\x2\x2\xF3\x3\x2\x2\x2\x2\xF5"+
		"\x3\x2\x2\x2\x2\xF7\x3\x2\x2\x2\x2\xF9\x3\x2\x2\x2\x2\xFB\x3\x2\x2\x2"+
		"\x2\xFD\x3\x2\x2\x2\x2\xFF\x3\x2\x2\x2\x2\x101\x3\x2\x2\x2\x2\x103\x3"+
		"\x2\x2\x2\x2\x105\x3\x2\x2\x2\x2\x107\x3\x2\x2\x2\x2\x109\x3\x2\x2\x2"+
		"\x2\x10B\x3\x2\x2\x2\x2\x10D\x3\x2\x2\x2\x2\x10F\x3\x2\x2\x2\x2\x111\x3"+
		"\x2\x2\x2\x2\x113\x3\x2\x2\x2\x2\x115\x3\x2\x2\x2\x2\x117\x3\x2\x2\x2"+
		"\x2\x119\x3\x2\x2\x2\x2\x11B\x3\x2\x2\x2\x2\x11D\x3\x2\x2\x2\x2\x11F\x3"+
		"\x2\x2\x2\x2\x121\x3\x2\x2\x2\x2\x123\x3\x2\x2\x2\x2\x125\x3\x2\x2\x2"+
		"\x2\x127\x3\x2\x2\x2\x2\x129\x3\x2\x2\x2\x2\x12B\x3\x2\x2\x2\x2\x12D\x3"+
		"\x2\x2\x2\x2\x12F\x3\x2\x2\x2\x2\x131\x3\x2\x2\x2\x2\x133\x3\x2\x2\x2"+
		"\x2\x135\x3\x2\x2\x2\x2\x137\x3\x2\x2\x2\x2\x139\x3\x2\x2\x2\x2\x13B\x3"+
		"\x2\x2\x2\x2\x13D\x3\x2\x2\x2\x2\x13F\x3\x2\x2\x2\x2\x141\x3\x2\x2\x2"+
		"\x2\x143\x3\x2\x2\x2\x2\x145\x3\x2\x2\x2\x2\x147\x3\x2\x2\x2\x2\x149\x3"+
		"\x2\x2\x2\x2\x14B\x3\x2\x2\x2\x2\x14D\x3\x2\x2\x2\x2\x14F\x3\x2\x2\x2"+
		"\x2\x151\x3\x2\x2\x2\x2\x153\x3\x2\x2\x2\x2\x155\x3\x2\x2\x2\x2\x157\x3"+
		"\x2\x2\x2\x2\x159\x3\x2\x2\x2\x2\x15B\x3\x2\x2\x2\x2\x15D\x3\x2\x2\x2"+
		"\x2\x15F\x3\x2\x2\x2\x2\x161\x3\x2\x2\x2\x2\x163\x3\x2\x2\x2\x2\x165\x3"+
		"\x2\x2\x2\x2\x167\x3\x2\x2\x2\x2\x169\x3\x2\x2\x2\x2\x16B\x3\x2\x2\x2"+
		"\x2\x16D\x3\x2\x2\x2\x2\x16F\x3\x2\x2\x2\x2\x171\x3\x2\x2\x2\x2\x173\x3"+
		"\x2\x2\x2\x2\x175\x3\x2\x2\x2\x2\x177\x3\x2\x2\x2\x3\x1C2\x3\x2\x2\x2"+
		"\x5\x1C8\x3\x2\x2\x2\a\x1CA\x3\x2\x2\x2\t\x1CC\x3\x2\x2\x2\v\x1CE\x3\x2"+
		"\x2\x2\r\x1D0\x3\x2\x2\x2\xF\x1D2\x3\x2\x2\x2\x11\x1D4\x3\x2\x2\x2\x13"+
		"\x1D6\x3\x2\x2\x2\x15\x1D8\x3\x2\x2\x2\x17\x1DA\x3\x2\x2\x2\x19\x1DC\x3"+
		"\x2\x2\x2\x1B\x1DE\x3\x2\x2\x2\x1D\x1E0\x3\x2\x2\x2\x1F\x1E2\x3\x2\x2"+
		"\x2!\x1E4\x3\x2\x2\x2#\x1E6\x3\x2\x2\x2%\x1E8\x3\x2\x2\x2\'\x1EA\x3\x2"+
		"\x2\x2)\x1EC\x3\x2\x2\x2+\x1EE\x3\x2\x2\x2-\x1F0\x3\x2\x2\x2/\x1F3\x3"+
		"\x2\x2\x2\x31\x1F5\x3\x2\x2\x2\x33\x1F8\x3\x2\x2\x2\x35\x1FB\x3\x2\x2"+
		"\x2\x37\x1FE\x3\x2\x2\x2\x39\x200\x3\x2\x2\x2;\x202\x3\x2\x2\x2=\x204"+
		"\x3\x2\x2\x2?\x206\x3\x2\x2\x2\x41\x208\x3\x2\x2\x2\x43\x20A\x3\x2\x2"+
		"\x2\x45\x226\x3\x2\x2\x2G\x228\x3\x2\x2\x2I\x235\x3\x2\x2\x2K\x23D\x3"+
		"\x2\x2\x2M\x240\x3\x2\x2\x2O\x248\x3\x2\x2\x2Q\x24E\x3\x2\x2\x2S\x256"+
		"\x3\x2\x2\x2U\x25D\x3\x2\x2\x2W\x261\x3\x2\x2\x2Y\x268\x3\x2\x2\x2[\x270"+
		"\x3\x2\x2\x2]\x278\x3\x2\x2\x2_\x281\x3\x2\x2\x2\x61\x287\x3\x2\x2\x2"+
		"\x63\x28F\x3\x2\x2\x2\x65\x298\x3\x2\x2\x2g\x29F\x3\x2\x2\x2i\x2A8\x3"+
		"\x2\x2\x2k\x2B5\x3\x2\x2\x2m\x2B9\x3\x2\x2\x2o\x2BD\x3\x2\x2\x2q\x2C1"+
		"\x3\x2\x2\x2s\x2C7\x3\x2\x2\x2u\x2CB\x3\x2\x2\x2w\x2CF\x3\x2\x2\x2y\x2D3"+
		"\x3\x2\x2\x2{\x2D6\x3\x2\x2\x2}\x2D9\x3\x2\x2\x2\x7F\x2DD\x3\x2\x2\x2"+
		"\x81\x2E2\x3\x2\x2\x2\x83\x2E7\x3\x2\x2\x2\x85\x2EC\x3\x2\x2\x2\x87\x2F0"+
		"\x3\x2\x2\x2\x89\x2F5\x3\x2\x2\x2\x8B\x2FA\x3\x2\x2\x2\x8D\x2FF\x3\x2"+
		"\x2\x2\x8F\x306\x3\x2\x2\x2\x91\x30D\x3\x2\x2\x2\x93\x313\x3\x2\x2\x2"+
		"\x95\x318\x3\x2\x2\x2\x97\x31E\x3\x2\x2\x2\x99\x323\x3\x2\x2\x2\x9B\x329"+
		"\x3\x2\x2\x2\x9D\x32F\x3\x2\x2\x2\x9F\x336\x3\x2\x2\x2\xA1\x33A\x3\x2"+
		"\x2\x2\xA3\x33F\x3\x2\x2\x2\xA5\x345\x3\x2\x2\x2\xA7\x34E\x3\x2\x2\x2"+
		"\xA9\x352\x3\x2\x2\x2\xAB\x359\x3\x2\x2\x2\xAD\x361\x3\x2\x2\x2\xAF\x365"+
		"\x3\x2\x2\x2\xB1\x368\x3\x2\x2\x2\xB3\x36D\x3\x2\x2\x2\xB5\x372\x3\x2"+
		"\x2\x2\xB7\x377\x3\x2\x2\x2\xB9\x37E\x3\x2\x2\x2\xBB\x382\x3\x2\x2\x2"+
		"\xBD\x387\x3\x2\x2\x2\xBF\x38B\x3\x2\x2\x2\xC1\x394\x3\x2\x2\x2\xC3\x39A"+
		"\x3\x2\x2\x2\xC5\x3A0\x3\x2\x2\x2\xC7\x3A6\x3\x2\x2\x2\xC9\x3AA\x3\x2"+
		"\x2\x2\xCB\x3B3\x3\x2\x2\x2\xCD\x3BA\x3\x2\x2\x2\xCF\x3C9\x3\x2\x2\x2"+
		"\xD1\x3DA\x3\x2\x2\x2\xD3\x3EB\x3\x2\x2\x2\xD5\x3ED\x3\x2\x2\x2\xD7\x3F1"+
		"\x3\x2\x2\x2\xD9\x3F7\x3\x2\x2\x2\xDB\x3FA\x3\x2\x2\x2\xDD\x3FD\x3\x2"+
		"\x2\x2\xDF\x401\x3\x2\x2\x2\xE1\x409\x3\x2\x2\x2\xE3\x40F\x3\x2\x2\x2"+
		"\xE5\x413\x3\x2\x2\x2\xE7\x41B\x3\x2\x2\x2\xE9\x423\x3\x2\x2\x2\xEB\x42A"+
		"\x3\x2\x2\x2\xED\x431\x3\x2\x2\x2\xEF\x437\x3\x2\x2\x2\xF1\x43B\x3\x2"+
		"\x2\x2\xF3\x43F\x3\x2\x2\x2\xF5\x442\x3\x2\x2\x2\xF7\x447\x3\x2\x2\x2"+
		"\xF9\x44C\x3\x2\x2\x2\xFB\x451\x3\x2\x2\x2\xFD\x455\x3\x2\x2\x2\xFF\x45F"+
		"\x3\x2\x2\x2\x101\x464\x3\x2\x2\x2\x103\x468\x3\x2\x2\x2\x105\x46B\x3"+
		"\x2\x2\x2\x107\x470\x3\x2\x2\x2\x109\x474\x3\x2\x2\x2\x10B\x47A\x3\x2"+
		"\x2\x2\x10D\x480\x3\x2\x2\x2\x10F\x485\x3\x2\x2\x2\x111\x488\x3\x2\x2"+
		"\x2\x113\x48D\x3\x2\x2\x2\x115\x493\x3\x2\x2\x2\x117\x498\x3\x2\x2\x2"+
		"\x119\x49C\x3\x2\x2\x2\x11B\x4A2\x3\x2\x2\x2\x11D\x4AA\x3\x2\x2\x2\x11F"+
		"\x4B4\x3\x2\x2\x2\x121\x4BC\x3\x2\x2\x2\x123\x4C6\x3\x2\x2\x2\x125\x4D0"+
		"\x3\x2\x2\x2\x127\x4D5\x3\x2\x2\x2\x129\x4D9\x3\x2\x2\x2\x12B\x4E1\x3"+
		"\x2\x2\x2\x12D\x4E8\x3\x2\x2\x2\x12F\x4EC\x3\x2\x2\x2\x131\x4F1\x3\x2"+
		"\x2\x2\x133\x4F8\x3\x2\x2\x2\x135\x501\x3\x2\x2\x2\x137\x508\x3\x2\x2"+
		"\x2\x139\x50A\x3\x2\x2\x2\x13B\x50E\x3\x2\x2\x2\x13D\x512\x3\x2\x2\x2"+
		"\x13F\x51A\x3\x2\x2\x2\x141\x51F\x3\x2\x2\x2\x143\x524\x3\x2\x2\x2\x145"+
		"\x52A\x3\x2\x2\x2\x147\x531\x3\x2\x2\x2\x149\x535\x3\x2\x2\x2\x14B\x539"+
		"\x3\x2\x2\x2\x14D\x53D\x3\x2\x2\x2\x14F\x542\x3\x2\x2\x2\x151\x545\x3"+
		"\x2\x2\x2\x153\x54C\x3\x2\x2\x2\x155\x552\x3\x2\x2\x2\x157\x558\x3\x2"+
		"\x2\x2\x159\x561\x3\x2\x2\x2\x15B\x567\x3\x2\x2\x2\x15D\x56D\x3\x2\x2"+
		"\x2\x15F\x571\x3\x2\x2\x2\x161\x578\x3\x2\x2\x2\x163\x57D\x3\x2\x2\x2"+
		"\x165\x583\x3\x2\x2\x2\x167\x5A1\x3\x2\x2\x2\x169\x602\x3\x2\x2\x2\x16B"+
		"\x604\x3\x2\x2\x2\x16D\x60B\x3\x2\x2\x2\x16F\x60D\x3\x2\x2\x2\x171\x60F"+
		"\x3\x2\x2\x2\x173\x618\x3\x2\x2\x2\x175\x622\x3\x2\x2\x2\x177\x626\x3"+
		"\x2\x2\x2\x179\x628\x3\x2\x2\x2\x17B\x62C\x3\x2\x2\x2\x17D\x64B\x3\x2"+
		"\x2\x2\x17F\x657\x3\x2\x2\x2\x181\x659\x3\x2\x2\x2\x183\x65B\x3\x2\x2"+
		"\x2\x185\x65D\x3\x2\x2\x2\x187\x65F\x3\x2\x2\x2\x189\x661\x3\x2\x2\x2"+
		"\x18B\x663\x3\x2\x2\x2\x18D\x665\x3\x2\x2\x2\x18F\x667\x3\x2\x2\x2\x191"+
		"\x669\x3\x2\x2\x2\x193\x66B\x3\x2\x2\x2\x195\x66D\x3\x2\x2\x2\x197\x66F"+
		"\x3\x2\x2\x2\x199\x671\x3\x2\x2\x2\x19B\x673\x3\x2\x2\x2\x19D\x675\x3"+
		"\x2\x2\x2\x19F\x677\x3\x2\x2\x2\x1A1\x679\x3\x2\x2\x2\x1A3\x67B\x3\x2"+
		"\x2\x2\x1A5\x67D\x3\x2\x2\x2\x1A7\x67F\x3\x2\x2\x2\x1A9\x681\x3\x2\x2"+
		"\x2\x1AB\x683\x3\x2\x2\x2\x1AD\x685\x3\x2\x2\x2\x1AF\x687\x3\x2\x2\x2"+
		"\x1B1\x689\x3\x2\x2\x2\x1B3\x68B\x3\x2\x2\x2\x1B5\x68E\x3\x2\x2\x2\x1B7"+
		"\x690\x3\x2\x2\x2\x1B9\x694\x3\x2\x2\x2\x1BB\x696\x3\x2\x2\x2\x1BD\x69A"+
		"\x3\x2\x2\x2\x1BF\x6A6\x3\x2\x2\x2\x1C1\x1C3\t\x2\x2\x2\x1C2\x1C1\x3\x2"+
		"\x2\x2\x1C3\x1C4\x3\x2\x2\x2\x1C4\x1C2\x3\x2\x2\x2\x1C4\x1C5\x3\x2\x2"+
		"\x2\x1C5\x1C6\x3\x2\x2\x2\x1C6\x1C7\b\x2\x2\x2\x1C7\x4\x3\x2\x2\x2\x1C8"+
		"\x1C9\x5\x1BF\xE0\x2\x1C9\x6\x3\x2\x2\x2\x1CA\x1CB\a<\x2\x2\x1CB\b\x3"+
		"\x2\x2\x2\x1CC\x1CD\a\x61\x2\x2\x1CD\n\x3\x2\x2\x2\x1CE\x1CF\a)\x2\x2"+
		"\x1CF\f\x3\x2\x2\x2\x1D0\x1D1\a\x31\x2\x2\x1D1\xE\x3\x2\x2\x2\x1D2\x1D3"+
		"\a&\x2\x2\x1D3\x10\x3\x2\x2\x2\x1D4\x1D5\a=\x2\x2\x1D5\x12\x3\x2\x2\x2"+
		"\x1D6\x1D7\a.\x2\x2\x1D7\x14\x3\x2\x2\x2\x1D8\x1D9\a?\x2\x2\x1D9\x16\x3"+
		"\x2\x2\x2\x1DA\x1DB\a*\x2\x2\x1DB\x18\x3\x2\x2\x2\x1DC\x1DD\a+\x2\x2\x1DD"+
		"\x1A\x3\x2\x2\x2\x1DE\x1DF\a]\x2\x2\x1DF\x1C\x3\x2\x2\x2\x1E0\x1E1\a_"+
		"\x2\x2\x1E1\x1E\x3\x2\x2\x2\x1E2\x1E3\a\x41\x2\x2\x1E3 \x3\x2\x2\x2\x1E4"+
		"\x1E5\a-\x2\x2\x1E5\"\x3\x2\x2\x2\x1E6\x1E7\a/\x2\x2\x1E7$\x3\x2\x2\x2"+
		"\x1E8\x1E9\a~\x2\x2\x1E9&\x3\x2\x2\x2\x1EA\x1EB\a`\x2\x2\x1EB(\x3\x2\x2"+
		"\x2\x1EC\x1ED\a(\x2\x2\x1ED*\x3\x2\x2\x2\x1EE\x1EF\a>\x2\x2\x1EF,\x3\x2"+
		"\x2\x2\x1F0\x1F1\a>\x2\x2\x1F1\x1F2\a?\x2\x2\x1F2.\x3\x2\x2\x2\x1F3\x1F4"+
		"\a@\x2\x2\x1F4\x30\x3\x2\x2\x2\x1F5\x1F6\a@\x2\x2\x1F6\x1F7\a?\x2\x2\x1F7"+
		"\x32\x3\x2\x2\x2\x1F8\x1F9\a>\x2\x2\x1F9\x1FA\a>\x2\x2\x1FA\x34\x3\x2"+
		"\x2\x2\x1FB\x1FC\a@\x2\x2\x1FC\x1FD\a@\x2\x2\x1FD\x36\x3\x2\x2\x2\x1FE"+
		"\x1FF\a,\x2\x2\x1FF\x38\x3\x2\x2\x2\x200\x201\a\x30\x2\x2\x201:\x3\x2"+
		"\x2\x2\x202\x203\a%\x2\x2\x203<\x3\x2\x2\x2\x204\x205\a}\x2\x2\x205>\x3"+
		"\x2\x2\x2\x206\x207\a\x7F\x2\x2\x207@\x3\x2\x2\x2\x208\x209\a#\x2\x2\x209"+
		"\x42\x3\x2\x2\x2\x20A\x20E\x5\x1B9\xDD\x2\x20B\x20D\x5\x1B9\xDD\x2\x20C"+
		"\x20B\x3\x2\x2\x2\x20D\x210\x3\x2\x2\x2\x20E\x20C\x3\x2\x2\x2\x20E\x20F"+
		"\x3\x2\x2\x2\x20F\x44\x3\x2\x2\x2\x210\x20E\x3\x2\x2\x2\x211\x213\t\x3"+
		"\x2\x2\x212\x211\x3\x2\x2\x2\x213\x216\x3\x2\x2\x2\x214\x212\x3\x2\x2"+
		"\x2\x214\x215\x3\x2\x2\x2\x215\x217\x3\x2\x2\x2\x216\x214\x3\x2\x2\x2"+
		"\x217\x219\a\x30\x2\x2\x218\x21A\t\x3\x2\x2\x219\x218\x3\x2\x2\x2\x21A"+
		"\x21B\x3\x2\x2\x2\x21B\x219\x3\x2\x2\x2\x21B\x21C\x3\x2\x2\x2\x21C\x21E"+
		"\x3\x2\x2\x2\x21D\x21F\x5\x1BD\xDF\x2\x21E\x21D\x3\x2\x2\x2\x21E\x21F"+
		"\x3\x2\x2\x2\x21F\x227\x3\x2\x2\x2\x220\x222\t\x3\x2\x2\x221\x220\x3\x2"+
		"\x2\x2\x222\x223\x3\x2\x2\x2\x223\x221\x3\x2\x2\x2\x223\x224\x3\x2\x2"+
		"\x2\x224\x225\x3\x2\x2\x2\x225\x227\x5\x1BD\xDF\x2\x226\x214\x3\x2\x2"+
		"\x2\x226\x221\x3\x2\x2\x2\x227\x46\x3\x2\x2\x2\x228\x229\x5\r\a\x2\x229"+
		"\x22D\x5\v\x6\x2\x22A\x22C\v\x2\x2\x2\x22B\x22A\x3\x2\x2\x2\x22C\x22F"+
		"\x3\x2\x2\x2\x22D\x22E\x3\x2\x2\x2\x22D\x22B\x3\x2\x2\x2\x22E\x230\x3"+
		"\x2\x2\x2\x22F\x22D\x3\x2\x2\x2\x230\x231\x5\v\x6\x2\x231\x232\x5\r\a"+
		"\x2\x232H\x3\x2\x2\x2\x233\x236\x5\x127\x94\x2\x234\x236\x5\v\x6\x2\x235"+
		"\x233\x3\x2\x2\x2\x235\x234\x3\x2\x2\x2\x236\x23A\x3\x2\x2\x2\x237\x239"+
		"\x5\x179\xBD\x2\x238\x237\x3\x2\x2\x2\x239\x23C\x3\x2\x2\x2\x23A\x238"+
		"\x3\x2\x2\x2\x23A\x23B\x3\x2\x2\x2\x23BJ\x3\x2\x2\x2\x23C\x23A\x3\x2\x2"+
		"\x2\x23D\x23E\a>\x2\x2\x23E\x23F\a@\x2\x2\x23FL\x3\x2\x2\x2\x240\x241"+
		"\x5;\x1E\x2\x241\x242\x5\x187\xC4\x2\x242\x243\x5\x189\xC5\x2\x243\x244"+
		"\x5\x18B\xC6\x2\x244\x245\x5\x191\xC9\x2\x245\x246\x5\x19B\xCE\x2\x246"+
		"\x247\x5\x189\xC5\x2\x247N\x3\x2\x2\x2\x248\x249\x5;\x1E\x2\x249\x24A"+
		"\x5\x189\xC5\x2\x24A\x24B\x5\x197\xCC\x2\x24B\x24C\x5\x1A5\xD3\x2\x24C"+
		"\x24D\x5\x189\xC5\x2\x24DP\x3\x2\x2\x2\x24E\x24F\x5;\x1E\x2\x24F\x250"+
		"\x5\x189\xC5\x2\x250\x251\x5\x197\xCC\x2\x251\x252\x5\x1A5\xD3\x2\x252"+
		"\x253\x5\x189\xC5\x2\x253\x254\x5\x191\xC9\x2\x254\x255\x5\x18B\xC6\x2"+
		"\x255R\x3\x2\x2\x2\x256\x257\x5;\x1E\x2\x257\x258\x5\x189\xC5\x2\x258"+
		"\x259\x5\x19B\xCE\x2\x259\x25A\x5\x187\xC4\x2\x25A\x25B\x5\x191\xC9\x2"+
		"\x25B\x25C\x5\x18B\xC6\x2\x25CT\x3\x2\x2\x2\x25D\x25E\x5;\x1E\x2\x25E"+
		"\x25F\x5\x191\xC9\x2\x25F\x260\x5\x18B\xC6\x2\x260V\x3\x2\x2\x2\x261\x262"+
		"\x5;\x1E\x2\x262\x263\x5\x191\xC9\x2\x263\x264\x5\x18B\xC6\x2\x264\x265"+
		"\x5\x187\xC4\x2\x265\x266\x5\x189\xC5\x2\x266\x267\x5\x18B\xC6\x2\x267"+
		"X\x3\x2\x2\x2\x268\x269\x5;\x1E\x2\x269\x26A\x5\x191\xC9\x2\x26A\x26B"+
		"\x5\x18B\xC6\x2\x26B\x26C\x5\x19B\xCE\x2\x26C\x26D\x5\x187\xC4\x2\x26D"+
		"\x26E\x5\x189\xC5\x2\x26E\x26F\x5\x18B\xC6\x2\x26FZ\x3\x2\x2\x2\x270\x271"+
		"\x5;\x1E\x2\x271\x272\x5\x191\xC9\x2\x272\x273\x5\x19B\xCE\x2\x273\x274"+
		"\x5\x185\xC3\x2\x274\x275\x5\x197\xCC\x2\x275\x276\x5\x191\xC9\x2\x276"+
		"\x277\x5\x183\xC2\x2\x277\\\x3\x2\x2\x2\x278\x279\x5;\x1E\x2\x279\x27A"+
		"\x5\x191\xC9\x2\x27A\x27B\x5\x19B\xCE\x2\x27B\x27C\x5\x185\xC3\x2\x27C"+
		"\x27D\x5\x197\xCC\x2\x27D\x27E\x5\x1A9\xD5\x2\x27E\x27F\x5\x187\xC4\x2"+
		"\x27F\x280\x5\x189\xC5\x2\x280^\x3\x2\x2\x2\x281\x282\x5;\x1E\x2\x282"+
		"\x283\x5\x197\xCC\x2\x283\x284\x5\x191\xC9\x2\x284\x285\x5\x19B\xCE\x2"+
		"\x285\x286\x5\x189\xC5\x2\x286`\x3\x2\x2\x2\x287\x288\x5;\x1E\x2\x288"+
		"\x289\x5\x19F\xD0\x2\x289\x28A\x5\x1A3\xD2\x2\x28A\x28B\x5\x181\xC1\x2"+
		"\x28B\x28C\x5\x18D\xC7\x2\x28C\x28D\x5\x199\xCD\x2\x28D\x28E\x5\x181\xC1"+
		"\x2\x28E\x62\x3\x2\x2\x2\x28F\x290\x5;\x1E\x2\x290\x291\x5\x1A3\xD2\x2"+
		"\x291\x292\x5\x189\xC5\x2\x292\x293\x5\x1A1\xD1\x2\x293\x294\x5\x1A9\xD5"+
		"\x2\x294\x295\x5\x191\xC9\x2\x295\x296\x5\x1A3\xD2\x2\x296\x297\x5\x189"+
		"\xC5\x2\x297\x64\x3\x2\x2\x2\x298\x299\x5;\x1E\x2\x299\x29A\x5\x1A9\xD5"+
		"\x2\x29A\x29B\x5\x19B\xCE\x2\x29B\x29C\x5\x187\xC4\x2\x29C\x29D\x5\x189"+
		"\xC5\x2\x29D\x29E\x5\x18B\xC6\x2\x29E\x66\x3\x2\x2\x2\x29F\x2A0\x5\xF"+
		"\b\x2\x2A0\x2A1\x5\x191\xC9\x2\x2A1\x2A2\x5\x19B\xCE\x2\x2A2\x2A3\x5\x185"+
		"\xC3\x2\x2A3\x2A4\x5\x197\xCC\x2\x2A4\x2A5\x5\x1A9\xD5\x2\x2A5\x2A6\x5"+
		"\x187\xC4\x2\x2A6\x2A7\x5\x189\xC5\x2\x2A7h\x3\x2\x2\x2\x2A8\x2A9\x5\x189"+
		"\xC5\x2\x2A9\x2AA\x5\x19B\xCE\x2\x2AA\x2AE\x5\x187\xC4\x2\x2AB\x2AD\x5"+
		"\x3\x2\x2\x2AC\x2AB\x3\x2\x2\x2\x2AD\x2B0\x3\x2\x2\x2\x2AE\x2AC\x3\x2"+
		"\x2\x2\x2AE\x2AF\x3\x2\x2\x2\x2AF\x2B1\x3\x2\x2\x2\x2B0\x2AE\x3\x2\x2"+
		"\x2\x2B1\x2B2\x5\x181\xC1\x2\x2B2\x2B3\x5\x1A5\xD3\x2\x2B3\x2B4\x5\x199"+
		"\xCD\x2\x2B4j\x3\x2\x2\x2\x2B5\x2B6\x5\x181\xC1\x2\x2B6\x2B7\x5\x183\xC2"+
		"\x2\x2B7\x2B8\x5\x1A5\xD3\x2\x2B8l\x3\x2\x2\x2\x2B9\x2BA\x5\x181\xC1\x2"+
		"\x2BA\x2BB\x5\x185\xC3\x2\x2BB\x2BC\x5\x1A5\xD3\x2\x2BCn\x3\x2\x2\x2\x2BD"+
		"\x2BE\x5\x181\xC1\x2\x2BE\x2BF\x5\x19B\xCE\x2\x2BF\x2C0\x5\x187\xC4\x2"+
		"\x2C0p\x3\x2\x2\x2\x2C1\x2C2\x5\x181\xC1\x2\x2C2\x2C3\x5\x197\xCC\x2\x2C3"+
		"\x2C4\x5\x191\xC9\x2\x2C4\x2C5\x5\x18D\xC7\x2\x2C5\x2C6\x5\x19B\xCE\x2"+
		"\x2C6r\x3\x2\x2\x2\x2C7\x2C8\x5\x181\xC1\x2\x2C8\x2C9\x5\x1A5\xD3\x2\x2C9"+
		"\x2CA\x5\x185\xC3\x2\x2CAt\x3\x2\x2\x2\x2CB\x2CC\x5\x181\xC1\x2\x2CC\x2CD"+
		"\x5\x1A5\xD3\x2\x2CD\x2CE\x5\x199\xCD\x2\x2CEv\x3\x2\x2\x2\x2CF\x2D0\x5"+
		"\x181\xC1\x2\x2D0\x2D1\x5\x1A5\xD3\x2\x2D1\x2D2\x5\x19B\xCE\x2\x2D2x\x3"+
		"\x2\x2\x2\x2D3\x2D4\x5\x181\xC1\x2\x2D4\x2D5\x5\x1A5\xD3\x2\x2D5z\x3\x2"+
		"\x2\x2\x2D6\x2D7\x5\x181\xC1\x2\x2D7\x2D8\x5\x1A7\xD4\x2\x2D8|\x3\x2\x2"+
		"\x2\x2D9\x2DA\x5\x181\xC1\x2\x2DA\x2DB\x5\x1A7\xD4\x2\x2DB\x2DC\x5\x19B"+
		"\xCE\x2\x2DC~\x3\x2\x2\x2\x2DD\x2DE\x5\x181\xC1\x2\x2DE\x2DF\x5\x1A7\xD4"+
		"\x2\x2DF\x2E0\x5\x1A7\xD4\x2\x2E0\x2E1\x5\x1A3\xD2\x2\x2E1\x80\x3\x2\x2"+
		"\x2\x2E2\x2E3\x5\x183\xC2\x2\x2E3\x2E4\x5\x181\xC1\x2\x2E4\x2E5\x5\x19B"+
		"\xCE\x2\x2E5\x2E6\x5\x187\xC4\x2\x2E6\x82\x3\x2\x2\x2\x2E7\x2E8\x5\x183"+
		"\xC2\x2\x2E8\x2E9\x5\x19B\xCE\x2\x2E9\x2EA\x5\x19D\xCF\x2\x2EA\x2EB\x5"+
		"\x1A7\xD4\x2\x2EB\x84\x3\x2\x2\x2\x2EC\x2ED\x5\x183\xC2\x2\x2ED\x2EE\x5"+
		"\x19D\xCF\x2\x2EE\x2EF\x5\x1A3\xD2\x2\x2EF\x86\x3\x2\x2\x2\x2F0\x2F1\x5"+
		"\x183\xC2\x2\x2F1\x2F2\x5\x1AF\xD8\x2\x2F2\x2F3\x5\x19D\xCF\x2\x2F3\x2F4"+
		"\x5\x1A3\xD2\x2\x2F4\x88\x3\x2\x2\x2\x2F5\x2F6\x5\x183\xC2\x2\x2F6\x2F7"+
		"\x5\x189\xC5\x2\x2F7\x2F8\x5\x189\xC5\x2\x2F8\x2F9\x5\x19F\xD0\x2\x2F9"+
		"\x8A\x3\x2\x2\x2\x2FA\x2FB\x5\x183\xC2\x2\x2FB\x2FC\x5\x19D\xCF\x2\x2FC"+
		"\x2FD\x5\x197\xCC\x2\x2FD\x2FE\x5\x187\xC4\x2\x2FE\x8C\x3\x2\x2\x2\x2FF"+
		"\x300\x5\x183\xC2\x2\x300\x301\x5\x19D\xCF\x2\x301\x302\x5\x1A3\xD2\x2"+
		"\x302\x303\x5\x187\xC4\x2\x303\x304\x5\x189\xC5\x2\x304\x305\x5\x1A3\xD2"+
		"\x2\x305\x8E\x3\x2\x2\x2\x306\x307\x5\x183\xC2\x2\x307\x308\x5\x1A3\xD2"+
		"\x2\x308\x309\x5\x191\xC9\x2\x309\x30A\x5\x18D\xC7\x2\x30A\x30B\x5\x18F"+
		"\xC8\x2\x30B\x30C\x5\x1A7\xD4\x2\x30C\x90\x3\x2\x2\x2\x30D\x30E\x5\x183"+
		"\xC2\x2\x30E\x30F\x5\x1B1\xD9\x2\x30F\x310\x5\x1A3\xD2\x2\x310\x311\x5"+
		"\x189\xC5\x2\x311\x312\x5\x18B\xC6\x2\x312\x92\x3\x2\x2\x2\x313\x314\x5"+
		"\x183\xC2\x2\x314\x315\x5\x1B1\xD9\x2\x315\x316\x5\x1A7\xD4\x2\x316\x317"+
		"\x5\x189\xC5\x2\x317\x94\x3\x2\x2\x2\x318\x319\x5\x183\xC2\x2\x319\x31A"+
		"\x5\x1B1\xD9\x2\x31A\x31B\x5\x1AB\xD6\x2\x31B\x31C\x5\x181\xC1\x2\x31C"+
		"\x31D\x5\x197\xCC\x2\x31D\x96\x3\x2\x2\x2\x31E\x31F\x5\x185\xC3\x2\x31F"+
		"\x320\x5\x181\xC1\x2\x320\x321\x5\x1A5\xD3\x2\x321\x322\x5\x1A7\xD4\x2"+
		"\x322\x98\x3\x2\x2\x2\x323\x324\x5\x185\xC3\x2\x324\x325\x5\x197\xCC\x2"+
		"\x325\x326\x5\x189\xC5\x2\x326\x327\x5\x181\xC1\x2\x327\x328\x5\x1A3\xD2"+
		"\x2\x328\x9A\x3\x2\x2\x2\x329\x32A\x5\x185\xC3\x2\x32A\x32B\x5\x18F\xC8"+
		"\x2\x32B\x32D\x5\x1A3\xD2\x2\x32C\x32E\x5\xF\b\x2\x32D\x32C\x3\x2\x2\x2"+
		"\x32D\x32E\x3\x2\x2\x2\x32E\x9C\x3\x2\x2\x2\x32F\x330\x5\x185\xC3\x2\x330"+
		"\x331\x5\x191\xC9\x2\x331\x332\x5\x1A3\xD2\x2\x332\x333\x5\x185\xC3\x2"+
		"\x333\x334\x5\x197\xCC\x2\x334\x335\x5\x189\xC5\x2\x335\x9E\x3\x2\x2\x2"+
		"\x336\x337\x5\x185\xC3\x2\x337\x338\x5\x197\xCC\x2\x338\x339\x5\x1A5\xD3"+
		"\x2\x339\xA0\x3\x2\x2\x2\x33A\x33B\x5\x185\xC3\x2\x33B\x33C\x5\x19D\xCF"+
		"\x2\x33C\x33D\x5\x187\xC4\x2\x33D\x33E\x5\x189\xC5\x2\x33E\xA2\x3\x2\x2"+
		"\x2\x33F\x340\x5\x185\xC3\x2\x340\x341\x5\x19D\xCF\x2\x341\x342\x5\x19B"+
		"\xCE\x2\x342\x343\x5\x1A5\xD3\x2\x343\x344\x5\x1A7\xD4\x2\x344\xA4\x3"+
		"\x2\x2\x2\x345\x346\x5\x185\xC3\x2\x346\x347\x5\x19D\xCF\x2\x347\x348"+
		"\x5\x19B\xCE\x2\x348\x349\x5\x1A7\xD4\x2\x349\x34A\x5\x191\xC9\x2\x34A"+
		"\x34B\x5\x19B\xCE\x2\x34B\x34C\x5\x1A9\xD5\x2\x34C\x34D\x5\x189\xC5\x2"+
		"\x34D\xA6\x3\x2\x2\x2\x34E\x34F\x5\x185\xC3\x2\x34F\x350\x5\x19D\xCF\x2"+
		"\x350\x351\x5\x1A5\xD3\x2\x351\xA8\x3\x2\x2\x2\x352\x353\x5\x185\xC3\x2"+
		"\x353\x354\x5\x1A5\xD3\x2\x354\x355\x5\x1A3\xD2\x2\x355\x356\x5\x197\xCC"+
		"\x2\x356\x357\x5\x191\xC9\x2\x357\x358\x5\x19B\xCE\x2\x358\xAA\x3\x2\x2"+
		"\x2\x359\x35A\x5\x187\xC4\x2\x35A\x35B\x5\x189\xC5\x2\x35B\x35C\x5\x185"+
		"\xC3\x2\x35C\x35D\x5\x197\xCC\x2\x35D\x35E\x5\x181\xC1\x2\x35E\x35F\x5"+
		"\x1A3\xD2\x2\x35F\x360\x5\x189\xC5\x2\x360\xAC\x3\x2\x2\x2\x361\x362\x5"+
		"\x187\xC4\x2\x362\x363\x5\x191\xC9\x2\x363\x364\x5\x199\xCD\x2\x364\xAE"+
		"\x3\x2\x2\x2\x365\x366\x5\x187\xC4\x2\x366\x367\x5\x19D\xCF\x2\x367\xB0"+
		"\x3\x2\x2\x2\x368\x369\x5\x187\xC4\x2\x369\x36A\x5\x181\xC1\x2\x36A\x36B"+
		"\x5\x1A7\xD4\x2\x36B\x36C\x5\x181\xC1\x2\x36C\xB2\x3\x2\x2\x2\x36D\x36E"+
		"\x5\x187\xC4\x2\x36E\x36F\x5\x1A3\xD2\x2\x36F\x370\x5\x181\xC1\x2\x370"+
		"\x371\x5\x1AD\xD7\x2\x371\xB4\x3\x2\x2\x2\x372\x373\x5\x189\xC5\x2\x373"+
		"\x374\x5\x197\xCC\x2\x374\x375\x5\x1A5\xD3\x2\x375\x376\x5\x189\xC5\x2"+
		"\x376\xB6\x3\x2\x2\x2\x377\x378\x5\x189\xC5\x2\x378\x379\x5\x197\xCC\x2"+
		"\x379\x37A\x5\x1A5\xD3\x2\x37A\x37B\x5\x189\xC5\x2\x37B\x37C\x5\x191\xC9"+
		"\x2\x37C\x37D\x5\x18B\xC6\x2\x37D\xB8\x3\x2\x2\x2\x37E\x37F\x5\x189\xC5"+
		"\x2\x37F\x380\x5\x19B\xCE\x2\x380\x381\x5\x187\xC4\x2\x381\xBA\x3\x2\x2"+
		"\x2\x382\x383\x5\x189\xC5\x2\x383\x384\x5\x1AF\xD8\x2\x384\x385\x5\x191"+
		"\xC9\x2\x385\x386\x5\x1A7\xD4\x2\x386\xBC\x3\x2\x2\x2\x387\x388\x5\x189"+
		"\xC5\x2\x388\x389\x5\x1AF\xD8\x2\x389\x38A\x5\x19F\xD0\x2\x38A\xBE\x3"+
		"\x2\x2\x2\x38B\x38C\x5\x18B\xC6\x2\x38C\x38D\x5\x181\xC1\x2\x38D\x38E"+
		"\x5\x1A5\xD3\x2\x38E\x38F\x5\x1A7\xD4\x2\x38F\x390\x5\x185\xC3\x2\x390"+
		"\x391\x5\x181\xC1\x2\x391\x392\x5\x197\xCC\x2\x392\x393\x5\x197\xCC\x2"+
		"\x393\xC0\x3\x2\x2\x2\x394\x395\x5\x18B\xC6\x2\x395\x396\x5\x191\xC9\x2"+
		"\x396\x397\x5\x1AF\xD8\x2\x397\x398\x5\x189\xC5\x2\x398\x399\x5\x187\xC4"+
		"\x2\x399\xC2\x3\x2\x2\x2\x39A\x39B\x5\x18B\xC6\x2\x39B\x39C\x5\x197\xCC"+
		"\x2\x39C\x39D\x5\x181\xC1\x2\x39D\x39E\x5\x1A5\xD3\x2\x39E\x39F\x5\x18F"+
		"\xC8\x2\x39F\xC4\x3\x2\x2\x2\x3A0\x3A1\x5\x18B\xC6\x2\x3A1\x3A2\x5\x197"+
		"\xCC\x2\x3A2\x3A3\x5\x19D\xCF\x2\x3A3\x3A4\x5\x181\xC1\x2\x3A4\x3A5\x5"+
		"\x1A7\xD4\x2\x3A5\xC6\x3\x2\x2\x2\x3A6\x3A7\x5\x18B\xC6\x2\x3A7\x3A8\x5"+
		"\x19D\xCF\x2\x3A8\x3A9\x5\x1A3\xD2\x2\x3A9\xC8\x3\x2\x2\x2\x3AA\x3AB\x5"+
		"\x18B\xC6\x2\x3AB\x3AC\x5\x1A9\xD5\x2\x3AC\x3AD\x5\x19B\xCE\x2\x3AD\x3AE"+
		"\x5\x185\xC3\x2\x3AE\x3AF\x5\x1A7\xD4\x2\x3AF\x3B0\x5\x191\xC9\x2\x3B0"+
		"\x3B1\x5\x19D\xCF\x2\x3B1\x3B2\x5\x19B\xCE\x2\x3B2\xCA\x3\x2\x2\x2\x3B3"+
		"\x3B4\x5\x18D\xC7\x2\x3B4\x3B5\x5\x189\xC5\x2\x3B5\x3B6\x5\x1A7\xD4\x2"+
		"\x3B6\x3B7\x5\x195\xCB\x2\x3B7\x3B8\x5\x189\xC5\x2\x3B8\x3B9\x5\x1B1\xD9"+
		"\x2\x3B9\xCC\x3\x2\x2\x2\x3BA\x3BB\x5\x18D\xC7\x2\x3BB\x3BC\x5\x189\xC5"+
		"\x2\x3BC\x3BD\x5\x1A7\xD4\x2\x3BD\x3BE\x5\x195\xCB\x2\x3BE\x3BF\x5\x189"+
		"\xC5\x2\x3BF\x3C0\x5\x1B1\xD9\x2\x3C0\x3C1\x5\x1A5\xD3\x2\x3C1\x3C2\x5"+
		"\x185\xC3\x2\x3C2\x3C3\x5\x181\xC1\x2\x3C3\x3C4\x5\x19B\xCE\x2\x3C4\x3C5"+
		"\x5\x185\xC3\x2\x3C5\x3C6\x5\x19D\xCF\x2\x3C6\x3C7\x5\x187\xC4\x2\x3C7"+
		"\x3C8\x5\x189\xC5\x2\x3C8\xCE\x3\x2\x2\x2\x3C9\x3CA\x5\x18D\xC7\x2\x3CA"+
		"\x3CB\x5\x19D\xCF\x2\x3CB\xD0\x3\x2\x2\x2\x3CC\x3CD\x5\x18D\xC7\x2\x3CD"+
		"\x3CE\x5\x19D\xCF\x2\x3CE\x3CF\x5\x1A7\xD4\x2\x3CF\x3D0\x5\x19D\xCF\x2"+
		"\x3D0\x3DB\x3\x2\x2\x2\x3D1\x3D5\x5\xCFh\x2\x3D2\x3D4\x5\x3\x2\x2\x3D3"+
		"\x3D2\x3\x2\x2\x2\x3D4\x3D7\x3\x2\x2\x2\x3D5\x3D3\x3\x2\x2\x2\x3D5\x3D6"+
		"\x3\x2\x2\x2\x3D6\x3D8\x3\x2\x2\x2\x3D7\x3D5\x3\x2\x2\x2\x3D8\x3D9\x5"+
		"\x14F\xA8\x2\x3D9\x3DB\x3\x2\x2\x2\x3DA\x3CC\x3\x2\x2\x2\x3DA\x3D1\x3"+
		"\x2\x2\x2\x3DB\xD2\x3\x2\x2\x2\x3DC\x3DD\x5\x18D\xC7\x2\x3DD\x3DE\x5\x19D"+
		"\xCF\x2\x3DE\x3DF\x5\x1A5\xD3\x2\x3DF\x3E0\x5\x1A9\xD5\x2\x3E0\x3E1\x5"+
		"\x183\xC2\x2\x3E1\x3EC\x3\x2\x2\x2\x3E2\x3E6\x5\xCFh\x2\x3E3\x3E5\x5\x3"+
		"\x2\x2\x3E4\x3E3\x3\x2\x2\x2\x3E5\x3E8\x3\x2\x2\x2\x3E6\x3E4\x3\x2\x2"+
		"\x2\x3E6\x3E7\x3\x2\x2\x2\x3E7\x3E9\x3\x2\x2\x2\x3E8\x3E6\x3\x2\x2\x2"+
		"\x3E9\x3EA\x5\x147\xA4\x2\x3EA\x3EC\x3\x2\x2\x2\x3EB\x3DC\x3\x2\x2\x2"+
		"\x3EB\x3E2\x3\x2\x2\x2\x3EC\xD4\x3\x2\x2\x2\x3ED\x3EE\x5\x18F\xC8\x2\x3EE"+
		"\x3EF\x5\x189\xC5\x2\x3EF\x3F0\x5\x1AF\xD8\x2\x3F0\xD6\x3\x2\x2\x2\x3F1"+
		"\x3F2\x5\x18F\xC8\x2\x3F2\x3F3\x5\x189\xC5\x2\x3F3\x3F4\x5\x1AF\xD8\x2"+
		"\x3F4\x3F5\a\x33\x2\x2\x3F5\x3F6\a\x38\x2\x2\x3F6\xD8\x3\x2\x2\x2\x3F7"+
		"\x3F8\x5\x191\xC9\x2\x3F8\x3F9\x5\x18B\xC6\x2\x3F9\xDA\x3\x2\x2\x2\x3FA"+
		"\x3FB\x5\x191\xC9\x2\x3FB\x3FC\x5\x19B\xCE\x2\x3FC\xDC\x3\x2\x2\x2\x3FD"+
		"\x3FE\x5\x191\xC9\x2\x3FE\x3FF\x5\x19B\xCE\x2\x3FF\x400\x5\x195\xCB\x2"+
		"\x400\xDE\x3\x2\x2\x2\x401\x402\x5\x191\xC9\x2\x402\x403\x5\x19B\xCE\x2"+
		"\x403\x404\x5\x195\xCB\x2\x404\x405\x5\x189\xC5\x2\x405\x407\x5\x1B1\xD9"+
		"\x2\x406\x408\x5\xF\b\x2\x407\x406\x3\x2\x2\x2\x407\x408\x3\x2\x2\x2\x408"+
		"\xE0\x3\x2\x2\x2\x409\x40A\x5\x191\xC9\x2\x40A\x40B\x5\x19B\xCE\x2\x40B"+
		"\x40C\x5\x19F\xD0\x2\x40C\x40D\x5\x1A9\xD5\x2\x40D\x40E\x5\x1A7\xD4\x2"+
		"\x40E\xE2\x3\x2\x2\x2\x40F\x410\x5\x191\xC9\x2\x410\x411\x5\x19B\xCE\x2"+
		"\x411\x412\x5\x1A7\xD4\x2\x412\xE4\x3\x2\x2\x2\x413\x414\x5\x191\xC9\x2"+
		"\x414\x415\x5\x19B\xCE\x2\x415\x416\x5\x1A7\xD4\x2\x416\x417\x5\x189\xC5"+
		"\x2\x417\x418\x5\x18D\xC7\x2\x418\x419\x5\x189\xC5\x2\x419\x41A\x5\x1A3"+
		"\xD2\x2\x41A\xE6\x3\x2\x2\x2\x41B\x41C\x5\x191\xC9\x2\x41C\x41D\x5\x19B"+
		"\xCE\x2\x41D\x41E\x5\x1AB\xD6\x2\x41E\x41F\x5\x189\xC5\x2\x41F\x420\x5"+
		"\x1A3\xD2\x2\x420\x421\x5\x1A5\xD3\x2\x421\x422\x5\x189\xC5\x2\x422\xE8"+
		"\x3\x2\x2\x2\x423\x424\x5\x191\xC9\x2\x424\x425\x5\x1A7\xD4\x2\x425\x426"+
		"\x5\x181\xC1\x2\x426\x427\x5\x197\xCC\x2\x427\x428\x5\x191\xC9\x2\x428"+
		"\x429\x5\x185\xC3\x2\x429\xEA\x3\x2\x2\x2\x42A\x42B\x5\x197\xCC\x2\x42B"+
		"\x42C\x5\x183\xC2\x2\x42C\x42D\x5\x19D\xCF\x2\x42D\x42E\x5\x1A9\xD5\x2"+
		"\x42E\x42F\x5\x19B\xCE\x2\x42F\x430\x5\x187\xC4\x2\x430\xEC\x3\x2\x2\x2"+
		"\x431\x432\x5\x197\xCC\x2\x432\x433\x5\x185\xC3\x2\x433\x434\x5\x181\xC1"+
		"\x2\x434\x435\x5\x1A5\xD3\x2\x435\x436\x5\x189\xC5\x2\x436\xEE\x3\x2\x2"+
		"\x2\x437\x438\x5\x197\xCC\x2\x438\x439\x5\x189\xC5\x2\x439\x43A\x5\x1A7"+
		"\xD4\x2\x43A\xF0\x3\x2\x2\x2\x43B\x43C\x5\x197\xCC\x2\x43C\x43D\x5\x189"+
		"\xC5\x2\x43D\x43E\x5\x19B\xCE\x2\x43E\xF2\x3\x2\x2\x2\x43F\x440\x5\x197"+
		"\xCC\x2\x440\x441\x5\x19B\xCE\x2\x441\xF4\x3\x2\x2\x2\x442\x443\x5\x197"+
		"\xCC\x2\x443\x444\x5\x19D\xCF\x2\x444\x445\x5\x181\xC1\x2\x445\x446\x5"+
		"\x187\xC4\x2\x446\xF6\x3\x2\x2\x2\x447\x448\x5\x197\xCC\x2\x448\x449\x5"+
		"\x19D\xCF\x2\x449\x44A\x5\x19B\xCE\x2\x44A\x44B\x5\x18D\xC7\x2\x44B\xF8"+
		"\x3\x2\x2\x2\x44C\x44D\x5\x197\xCC\x2\x44D\x44E\x5\x19D\xCF\x2\x44E\x44F"+
		"\x5\x19D\xCF\x2\x44F\x450\x5\x19F\xD0\x2\x450\xFA\x3\x2\x2\x2\x451\x452"+
		"\x5\x199\xCD\x2\x452\x453\x5\x19D\xCF\x2\x453\x454\x5\x187\xC4\x2\x454"+
		"\xFC\x3\x2\x2\x2\x455\x456\x5\x199\xCD\x2\x456\x457\x5\x1A9\xD5\x2\x457"+
		"\x458\x5\x197\xCC\x2\x458\x459\x5\x1A7\xD4\x2\x459\x45A\x5\x191\xC9\x2"+
		"\x45A\x45B\x5\x195\xCB\x2\x45B\x45C\x5\x189\xC5\x2\x45C\x45D\x5\x1B1\xD9"+
		"\x2\x45D\x45E\x5\x1A5\xD3\x2\x45E\xFE\x3\x2\x2\x2\x45F\x460\x5\x19B\xCE"+
		"\x2\x460\x461\x5\x189\xC5\x2\x461\x462\x5\x1AF\xD8\x2\x462\x463\x5\x1A7"+
		"\xD4\x2\x463\x100\x3\x2\x2\x2\x464\x465\x5\x19B\xCE\x2\x465\x466\x5\x19D"+
		"\xCF\x2\x466\x467\x5\x1A7\xD4\x2\x467\x102\x3\x2\x2\x2\x468\x469\x5\x19D"+
		"\xCF\x2\x469\x46A\x5\x1A3\xD2\x2\x46A\x104\x3\x2\x2\x2\x46B\x46C\x5\x19D"+
		"\xCF\x2\x46C\x46D\x5\x1AB\xD6\x2\x46D\x46E\x5\x189\xC5\x2\x46E\x46F\x5"+
		"\x1A3\xD2\x2\x46F\x106\x3\x2\x2\x2\x470\x471\x5\x19D\xCF\x2\x471\x472"+
		"\x5\x1A9\xD5\x2\x472\x473\x5\x1A7\xD4\x2\x473\x108\x3\x2\x2\x2\x474\x475"+
		"\x5\x19F\xD0\x2\x475\x476\x5\x181\xC1\x2\x476\x477\x5\x19F\xD0\x2\x477"+
		"\x478\x5\x189\xC5\x2\x478\x479\x5\x1A3\xD2\x2\x479\x10A\x3\x2\x2\x2\x47A"+
		"\x47B\x5\x19F\xD0\x2\x47B\x47C\x5\x181\xC1\x2\x47C\x47D\x5\x1A9\xD5\x2"+
		"\x47D\x47E\x5\x1A5\xD3\x2\x47E\x47F\x5\x189\xC5\x2\x47F\x10C\x3\x2\x2"+
		"\x2\x480\x481\x5\x19F\xD0\x2\x481\x482\x5\x189\xC5\x2\x482\x483\x5\x189"+
		"\xC5\x2\x483\x484\x5\x195\xCB\x2\x484\x10E\x3\x2\x2\x2\x485\x486\x5\x19F"+
		"\xD0\x2\x486\x487\x5\x191\xC9\x2\x487\x110\x3\x2\x2\x2\x488\x489\x5\x19F"+
		"\xD0\x2\x489\x48A\x5\x197\xCC\x2\x48A\x48B\x5\x19D\xCF\x2\x48B\x48C\x5"+
		"\x1A7\xD4\x2\x48C\x112\x3\x2\x2\x2\x48D\x48E\x5\x19F\xD0\x2\x48E\x48F"+
		"\x5\x19D\xCF\x2\x48F\x490\x5\x191\xC9\x2\x490\x491\x5\x19B\xCE\x2\x491"+
		"\x492\x5\x1A7\xD4\x2\x492\x114\x3\x2\x2\x2\x493\x494\x5\x19F\xD0\x2\x494"+
		"\x495\x5\x19D\xCF\x2\x495\x496\x5\x195\xCB\x2\x496\x497\x5\x189\xC5\x2"+
		"\x497\x116\x3\x2\x2\x2\x498\x499\x5\x19F\xD0\x2\x499\x49A\x5\x19D\xCF"+
		"\x2\x49A\x49B\x5\x1A5\xD3\x2\x49B\x118\x3\x2\x2\x2\x49C\x49D\x5\x19F\xD0"+
		"\x2\x49D\x49E\x5\x1A3\xD2\x2\x49E\x49F\x5\x191\xC9\x2\x49F\x4A0\x5\x19B"+
		"\xCE\x2\x4A0\x4A1\x5\x1A7\xD4\x2\x4A1\x11A\x3\x2\x2\x2\x4A2\x4A3\x5\x19F"+
		"\xD0\x2\x4A3\x4A4\x5\x1A3\xD2\x2\x4A4\x4A5\x5\x191\xC9\x2\x4A5\x4A6\x5"+
		"\x19B\xCE\x2\x4A6\x4A7\x5\x1A7\xD4\x2\x4A7\x4A8\a\x36\x2\x2\x4A8\x4A9"+
		"\a\x34\x2\x2\x4A9\x11C\x3\x2\x2\x2\x4AA\x4AB\x5\x19F\xD0\x2\x4AB\x4AC"+
		"\x5\x1A3\xD2\x2\x4AC\x4AD\x5\x191\xC9\x2\x4AD\x4AE\x5\x19B\xCE\x2\x4AE"+
		"\x4AF\x5\x1A7\xD4\x2\x4AF\x4B0\x5\x181\xC1\x2\x4B0\x4B1\x5\x1A7\xD4\x2"+
		"\x4B1\x4B2\a\x36\x2\x2\x4B2\x4B3\a\x34\x2\x2\x4B3\x11E\x3\x2\x2\x2\x4B4"+
		"\x4B5\x5\x19F\xD0\x2\x4B5\x4B6\x5\x1A3\xD2\x2\x4B6\x4B7\x5\x191\xC9\x2"+
		"\x4B7\x4B8\x5\x19B\xCE\x2\x4B8\x4B9\x5\x1A7\xD4\x2\x4B9\x4BA\a\x38\x2"+
		"\x2\x4BA\x4BB\a\x36\x2\x2\x4BB\x120\x3\x2\x2\x2\x4BC\x4BD\x5\x19F\xD0"+
		"\x2\x4BD\x4BE\x5\x1A3\xD2\x2\x4BE\x4BF\x5\x191\xC9\x2\x4BF\x4C0\x5\x19B"+
		"\xCE\x2\x4C0\x4C1\x5\x1A7\xD4\x2\x4C1\x4C2\x5\x181\xC1\x2\x4C2\x4C3\x5"+
		"\x1A7\xD4\x2\x4C3\x4C4\a\x38\x2\x2\x4C4\x4C5\a\x36\x2\x2\x4C5\x122\x3"+
		"\x2\x2\x2\x4C6\x4C7\x5\x1A3\xD2\x2\x4C7\x4C8\x5\x181\xC1\x2\x4C8\x4C9"+
		"\x5\x19B\xCE\x2\x4C9\x4CA\x5\x187\xC4\x2\x4CA\x4CB\x5\x19D\xCF\x2\x4CB"+
		"\x4CC\x5\x199\xCD\x2\x4CC\x4CD\x5\x191\xC9\x2\x4CD\x4CE\x5\x1B3\xDA\x2"+
		"\x4CE\x4CF\x5\x189\xC5\x2\x4CF\x124\x3\x2\x2\x2\x4D0\x4D1\x5\x1A3\xD2"+
		"\x2\x4D1\x4D2\x5\x189\xC5\x2\x4D2\x4D3\x5\x181\xC1\x2\x4D3\x4D4\x5\x187"+
		"\xC4\x2\x4D4\x126\x3\x2\x2\x2\x4D5\x4D6\x5\x1A3\xD2\x2\x4D6\x4D7\x5\x189"+
		"\xC5\x2\x4D7\x4D8\x5\x199\xCD\x2\x4D8\x128\x3\x2\x2\x2\x4D9\x4DA\x5\x1A3"+
		"\xD2\x2\x4DA\x4DB\x5\x189\xC5\x2\x4DB\x4DC\x5\x1A5\xD3\x2\x4DC\x4DD\x5"+
		"\x1A7\xD4\x2\x4DD\x4DE\x5\x19D\xCF\x2\x4DE\x4DF\x5\x1A3\xD2\x2\x4DF\x4E0"+
		"\x5\x189\xC5\x2\x4E0\x12A\x3\x2\x2\x2\x4E1\x4E2\x5\x1A3\xD2\x2\x4E2\x4E3"+
		"\x5\x189\xC5\x2\x4E3\x4E4\x5\x1A7\xD4\x2\x4E4\x4E5\x5\x1A9\xD5\x2\x4E5"+
		"\x4E6\x5\x1A3\xD2\x2\x4E6\x4E7\x5\x19B\xCE\x2\x4E7\x12C\x3\x2\x2\x2\x4E8"+
		"\x4E9\x5\x1A3\xD2\x2\x4E9\x4EA\x5\x19B\xCE\x2\x4EA\x4EB\x5\x187\xC4\x2"+
		"\x4EB\x12E\x3\x2\x2\x2\x4EC\x4ED\x5\x1A5\xD3\x2\x4ED\x4EE\x5\x181\xC1"+
		"\x2\x4EE\x4EF\x5\x1AB\xD6\x2\x4EF\x4F0\x5\x189\xC5\x2\x4F0\x130\x3\x2"+
		"\x2\x2\x4F1\x4F2\x5\x1A5\xD3\x2\x4F2\x4F3\x5\x185\xC3\x2\x4F3\x4F4\x5"+
		"\x1A3\xD2\x2\x4F4\x4F5\x5\x189\xC5\x2\x4F5\x4F6\x5\x189\xC5\x2\x4F6\x4F7"+
		"\x5\x19B\xCE\x2\x4F7\x132\x3\x2\x2\x2\x4F8\x4F9\x5\x1A5\xD3\x2\x4F9\x4FA"+
		"\x5\x18D\xC7\x2\x4FA\x4FB\x5\x19B\xCE\x2\x4FB\x134\x3\x2\x2\x2\x4FC\x4FD"+
		"\x5\x1A5\xD3\x2\x4FD\x4FE\x5\x18F\xC8\x2\x4FE\x4FF\x5\x197\xCC\x2\x4FF"+
		"\x502\x3\x2\x2\x2\x500\x502\x5\x33\x1A\x2\x501\x4FC\x3\x2\x2\x2\x501\x500"+
		"\x3\x2\x2\x2\x502\x136\x3\x2\x2\x2\x503\x504\x5\x1A5\xD3\x2\x504\x505"+
		"\x5\x18F\xC8\x2\x505\x506\x5\x1A3\xD2\x2\x506\x509\x3\x2\x2\x2\x507\x509"+
		"\x5\x35\x1B\x2\x508\x503\x3\x2\x2\x2\x508\x507\x3\x2\x2\x2\x509\x138\x3"+
		"\x2\x2\x2\x50A\x50B\x5\x1A5\xD3\x2\x50B\x50C\x5\x191\xC9\x2\x50C\x50D"+
		"\x5\x19B\xCE\x2\x50D\x13A\x3\x2\x2\x2\x50E\x50F\x5\x1A5\xD3\x2\x50F\x510"+
		"\x5\x1A1\xD1\x2\x510\x511\x5\x1A3\xD2\x2\x511\x13C\x3\x2\x2\x2\x512\x513"+
		"\x5\x1A5\xD3\x2\x513\x514\x5\x1A7\xD4\x2\x514\x515\x5\x187\xC4\x2\x515"+
		"\x516\x5\x185\xC3\x2\x516\x517\x5\x181\xC1\x2\x517\x518\x5\x197\xCC\x2"+
		"\x518\x519\x5\x197\xCC\x2\x519\x13E\x3\x2\x2\x2\x51A\x51B\x5\x1A5\xD3"+
		"\x2\x51B\x51C\x5\x1A7\xD4\x2\x51C\x51D\x5\x189\xC5\x2\x51D\x51E\x5\x19F"+
		"\xD0\x2\x51E\x140\x3\x2\x2\x2\x51F\x520\x5\x1A5\xD3\x2\x520\x521\x5\x1A7"+
		"\xD4\x2\x521\x522\x5\x19D\xCF\x2\x522\x523\x5\x19F\xD0\x2\x523\x142\x3"+
		"\x2\x2\x2\x524\x525\x5\x1A5\xD3\x2\x525\x526\x5\x1A7\xD4\x2\x526\x528"+
		"\x5\x1A3\xD2\x2\x527\x529\x5\xF\b\x2\x528\x527\x3\x2\x2\x2\x528\x529\x3"+
		"\x2\x2\x2\x529\x144\x3\x2\x2\x2\x52A\x52B\x5\x1A5\xD3\x2\x52B\x52C\x5"+
		"\x1A7\xD4\x2\x52C\x52D\x5\x1A3\xD2\x2\x52D\x52E\x5\x191\xC9\x2\x52E\x52F"+
		"\x5\x19B\xCE\x2\x52F\x530\x5\x18D\xC7\x2\x530\x146\x3\x2\x2\x2\x531\x532"+
		"\x5\x1A5\xD3\x2\x532\x533\x5\x1A9\xD5\x2\x533\x534\x5\x183\xC2\x2\x534"+
		"\x148\x3\x2\x2\x2\x535\x536\x5\x1A7\xD4\x2\x536\x537\x5\x181\xC1\x2\x537"+
		"\x538\x5\x183\xC2\x2\x538\x14A\x3\x2\x2\x2\x539\x53A\x5\x1A7\xD4\x2\x53A"+
		"\x53B\x5\x181\xC1\x2\x53B\x53C\x5\x19B\xCE\x2\x53C\x14C\x3\x2\x2\x2\x53D"+
		"\x53E\x5\x1A7\xD4\x2\x53E\x53F\x5\x18F\xC8\x2\x53F\x540\x5\x189\xC5\x2"+
		"\x540\x541\x5\x19B\xCE\x2\x541\x14E\x3\x2\x2\x2\x542\x543\x5\x1A7\xD4"+
		"\x2\x543\x544\x5\x19D\xCF\x2\x544\x150\x3\x2\x2\x2\x545\x546\x5\x1A9\xD5"+
		"\x2\x546\x547\x5\x183\xC2\x2\x547\x548\x5\x19D\xCF\x2\x548\x549\x5\x1A9"+
		"\xD5\x2\x549\x54A\x5\x19B\xCE\x2\x54A\x54B\x5\x187\xC4\x2\x54B\x152\x3"+
		"\x2\x2\x2\x54C\x54D\x5\x1A9\xD5\x2\x54D\x54E\x5\x183\xC2\x2\x54E\x54F"+
		"\x5\x1B1\xD9\x2\x54F\x550\x5\x1A7\xD4\x2\x550\x551\x5\x189\xC5\x2\x551"+
		"\x154\x3\x2\x2\x2\x552\x553\x5\x1A9\xD5\x2\x553\x554\x5\x185\xC3\x2\x554"+
		"\x555\x5\x181\xC1\x2\x555\x556\x5\x1A5\xD3\x2\x556\x557\x5\x189\xC5\x2"+
		"\x557\x156\x3\x2\x2\x2\x558\x559\x5\x1A9\xD5\x2\x559\x55A\x5\x191\xC9"+
		"\x2\x55A\x55B\x5\x19B\xCE\x2\x55B\x55C\x5\x1A7\xD4\x2\x55C\x55D\x5\x189"+
		"\xC5\x2\x55D\x55E\x5\x18D\xC7\x2\x55E\x55F\x5\x189\xC5\x2\x55F\x560\x5"+
		"\x1A3\xD2\x2\x560\x158\x3\x2\x2\x2\x561\x562\x5\x1A9\xD5\x2\x562\x563"+
		"\x5\x197\xCC\x2\x563\x564\x5\x19D\xCF\x2\x564\x565\x5\x19B\xCE\x2\x565"+
		"\x566\x5\x18D\xC7\x2\x566\x15A\x3\x2\x2\x2\x567\x568\x5\x1A9\xD5\x2\x568"+
		"\x569\x5\x19B\xCE\x2\x569\x56A\x5\x1A7\xD4\x2\x56A\x56B\x5\x191\xC9\x2"+
		"\x56B\x56C\x5\x197\xCC\x2\x56C\x15C\x3\x2\x2\x2\x56D\x56E\x5\x1AB\xD6"+
		"\x2\x56E\x56F\x5\x181\xC1\x2\x56F\x570\x5\x197\xCC\x2\x570\x15E\x3\x2"+
		"\x2\x2\x571\x572\x5\x1AB\xD6\x2\x572\x573\x5\x189\xC5\x2\x573\x574\x5"+
		"\x1A3\xD2\x2\x574\x575\x5\x191\xC9\x2\x575\x576\x5\x18B\xC6\x2\x576\x577"+
		"\x5\x1B1\xD9\x2\x577\x160\x3\x2\x2\x2\x578\x579\x5\x1AD\xD7\x2\x579\x57A"+
		"\x5\x189\xC5\x2\x57A\x57B\x5\x19B\xCE\x2\x57B\x57C\x5\x187\xC4\x2\x57C"+
		"\x162\x3\x2\x2\x2\x57D\x57E\x5\x1AD\xD7\x2\x57E\x57F\x5\x18F\xC8\x2\x57F"+
		"\x580\x5\x191\xC9\x2\x580\x581\x5\x197\xCC\x2\x581\x582\x5\x189\xC5\x2"+
		"\x582\x164\x3\x2\x2\x2\x583\x584\x5\x1AF\xD8\x2\x584\x585\x5\x19D\xCF"+
		"\x2\x585\x586\x5\x1A3\xD2\x2\x586\x166\x3\x2\x2\x2\x587\x588\a&\x2\x2"+
		"\x588\x58A\x5\x1B5\xDB\x2\x589\x58B\x5\x1B5\xDB\x2\x58A\x589\x3\x2\x2"+
		"\x2\x58A\x58B\x3\x2\x2\x2\x58B\x58D\x3\x2\x2\x2\x58C\x58E\x5\x1B5\xDB"+
		"\x2\x58D\x58C\x3\x2\x2\x2\x58D\x58E\x3\x2\x2\x2\x58E\x590\x3\x2\x2\x2"+
		"\x58F\x591\x5\x1B5\xDB\x2\x590\x58F\x3\x2\x2\x2\x590\x591\x3\x2\x2\x2"+
		"\x591\x5A2\x3\x2\x2\x2\x592\x594\x5\x1B9\xDD\x2\x593\x595\x5\x1B5\xDB"+
		"\x2\x594\x593\x3\x2\x2\x2\x594\x595\x3\x2\x2\x2\x595\x597\x3\x2\x2\x2"+
		"\x596\x598\x5\x1B5\xDB\x2\x597\x596\x3\x2\x2\x2\x597\x598\x3\x2\x2\x2"+
		"\x598\x59A\x3\x2\x2\x2\x599\x59B\x5\x1B5\xDB\x2\x59A\x599\x3\x2\x2\x2"+
		"\x59A\x59B\x3\x2\x2\x2\x59B\x59D\x3\x2\x2\x2\x59C\x59E\x5\x1B5\xDB\x2"+
		"\x59D\x59C\x3\x2\x2\x2\x59D\x59E\x3\x2\x2\x2\x59E\x59F\x3\x2\x2\x2\x59F"+
		"\x5A0\t\x4\x2\x2\x5A0\x5A2\x3\x2\x2\x2\x5A1\x587\x3\x2\x2\x2\x5A1\x592"+
		"\x3\x2\x2\x2\x5A2\x168\x3\x2\x2\x2\x5A3\x5A4\a\'\x2\x2\x5A4\x5A6\x5\x1BB"+
		"\xDE\x2\x5A5\x5A7\x5\x1BB\xDE\x2\x5A6\x5A5\x3\x2\x2\x2\x5A6\x5A7\x3\x2"+
		"\x2\x2\x5A7\x5A9\x3\x2\x2\x2\x5A8\x5AA\x5\x1BB\xDE\x2\x5A9\x5A8\x3\x2"+
		"\x2\x2\x5A9\x5AA\x3\x2\x2\x2\x5AA\x5AC\x3\x2\x2\x2\x5AB\x5AD\x5\x1BB\xDE"+
		"\x2\x5AC\x5AB\x3\x2\x2\x2\x5AC\x5AD\x3\x2\x2\x2\x5AD\x5AF\x3\x2\x2\x2"+
		"\x5AE\x5B0\x5\x1BB\xDE\x2\x5AF\x5AE\x3\x2\x2\x2\x5AF\x5B0\x3\x2\x2\x2"+
		"\x5B0\x5B2\x3\x2\x2\x2\x5B1\x5B3\x5\x1BB\xDE\x2\x5B2\x5B1\x3\x2\x2\x2"+
		"\x5B2\x5B3\x3\x2\x2\x2\x5B3\x5B5\x3\x2\x2\x2\x5B4\x5B6\x5\x1BB\xDE\x2"+
		"\x5B5\x5B4\x3\x2\x2\x2\x5B5\x5B6\x3\x2\x2\x2\x5B6\x5B8\x3\x2\x2\x2\x5B7"+
		"\x5B9\x5\x1BB\xDE\x2\x5B8\x5B7\x3\x2\x2\x2\x5B8\x5B9\x3\x2\x2\x2\x5B9"+
		"\x5BB\x3\x2\x2\x2\x5BA\x5BC\x5\x1BB\xDE\x2\x5BB\x5BA\x3\x2\x2\x2\x5BB"+
		"\x5BC\x3\x2\x2\x2\x5BC\x5BE\x3\x2\x2\x2\x5BD\x5BF\x5\x1BB\xDE\x2\x5BE"+
		"\x5BD\x3\x2\x2\x2\x5BE\x5BF\x3\x2\x2\x2\x5BF\x5C1\x3\x2\x2\x2\x5C0\x5C2"+
		"\x5\x1BB\xDE\x2\x5C1\x5C0\x3\x2\x2\x2\x5C1\x5C2\x3\x2\x2\x2\x5C2\x5C4"+
		"\x3\x2\x2\x2\x5C3\x5C5\x5\x1BB\xDE\x2\x5C4\x5C3\x3\x2\x2\x2\x5C4\x5C5"+
		"\x3\x2\x2\x2\x5C5\x5C7\x3\x2\x2\x2\x5C6\x5C8\x5\x1BB\xDE\x2\x5C7\x5C6"+
		"\x3\x2\x2\x2\x5C7\x5C8\x3\x2\x2\x2\x5C8\x5CA\x3\x2\x2\x2\x5C9\x5CB\x5"+
		"\x1BB\xDE\x2\x5CA\x5C9\x3\x2\x2\x2\x5CA\x5CB\x3\x2\x2\x2\x5CB\x5CD\x3"+
		"\x2\x2\x2\x5CC\x5CE\x5\x1BB\xDE\x2\x5CD\x5CC\x3\x2\x2\x2\x5CD\x5CE\x3"+
		"\x2\x2\x2\x5CE\x5D0\x3\x2\x2\x2\x5CF\x5D1\x5\x1BB\xDE\x2\x5D0\x5CF\x3"+
		"\x2\x2\x2\x5D0\x5D1\x3\x2\x2\x2\x5D1\x603\x3\x2\x2\x2\x5D2\x5D4\x5\x1BB"+
		"\xDE\x2\x5D3\x5D5\x5\x1BB\xDE\x2\x5D4\x5D3\x3\x2\x2\x2\x5D4\x5D5\x3\x2"+
		"\x2\x2\x5D5\x5D7\x3\x2\x2\x2\x5D6\x5D8\x5\x1BB\xDE\x2\x5D7\x5D6\x3\x2"+
		"\x2\x2\x5D7\x5D8\x3\x2\x2\x2\x5D8\x5DA\x3\x2\x2\x2\x5D9\x5DB\x5\x1BB\xDE"+
		"\x2\x5DA\x5D9\x3\x2\x2\x2\x5DA\x5DB\x3\x2\x2\x2\x5DB\x5DD\x3\x2\x2\x2"+
		"\x5DC\x5DE\x5\x1BB\xDE\x2\x5DD\x5DC\x3\x2\x2\x2\x5DD\x5DE\x3\x2\x2\x2"+
		"\x5DE\x5E0\x3\x2\x2\x2\x5DF\x5E1\x5\x1BB\xDE\x2\x5E0\x5DF\x3\x2\x2\x2"+
		"\x5E0\x5E1\x3\x2\x2\x2\x5E1\x5E3\x3\x2\x2\x2\x5E2\x5E4\x5\x1BB\xDE\x2"+
		"\x5E3\x5E2\x3\x2\x2\x2\x5E3\x5E4\x3\x2\x2\x2\x5E4\x5E6\x3\x2\x2\x2\x5E5"+
		"\x5E7\x5\x1BB\xDE\x2\x5E6\x5E5\x3\x2\x2\x2\x5E6\x5E7\x3\x2\x2\x2\x5E7"+
		"\x5E9\x3\x2\x2\x2\x5E8\x5EA\x5\x1BB\xDE\x2\x5E9\x5E8\x3\x2\x2\x2\x5E9"+
		"\x5EA\x3\x2\x2\x2\x5EA\x5EC\x3\x2\x2\x2\x5EB\x5ED\x5\x1BB\xDE\x2\x5EC"+
		"\x5EB\x3\x2\x2\x2\x5EC\x5ED\x3\x2\x2\x2\x5ED\x5EF\x3\x2\x2\x2\x5EE\x5F0"+
		"\x5\x1BB\xDE\x2\x5EF\x5EE\x3\x2\x2\x2\x5EF\x5F0\x3\x2\x2\x2\x5F0\x5F2"+
		"\x3\x2\x2\x2\x5F1\x5F3\x5\x1BB\xDE\x2\x5F2\x5F1\x3\x2\x2\x2\x5F2\x5F3"+
		"\x3\x2\x2\x2\x5F3\x5F5\x3\x2\x2\x2\x5F4\x5F6\x5\x1BB\xDE\x2\x5F5\x5F4"+
		"\x3\x2\x2\x2\x5F5\x5F6\x3\x2\x2\x2\x5F6\x5F8\x3\x2\x2\x2\x5F7\x5F9\x5"+
		"\x1BB\xDE\x2\x5F8\x5F7\x3\x2\x2\x2\x5F8\x5F9\x3\x2\x2\x2\x5F9\x5FB\x3"+
		"\x2\x2\x2\x5FA\x5FC\x5\x1BB\xDE\x2\x5FB\x5FA\x3\x2\x2\x2\x5FB\x5FC\x3"+
		"\x2\x2\x2\x5FC\x5FE\x3\x2\x2\x2\x5FD\x5FF\x5\x1BB\xDE\x2\x5FE\x5FD\x3"+
		"\x2\x2\x2\x5FE\x5FF\x3\x2\x2\x2\x5FF\x600\x3\x2\x2\x2\x600\x601\t\x5\x2"+
		"\x2\x601\x603\x3\x2\x2\x2\x602\x5A3\x3\x2\x2\x2\x602\x5D2\x3\x2\x2\x2"+
		"\x603\x16A\x3\x2\x2\x2\x604\x608\x5\x16D\xB7\x2\x605\x607\x5\x16F\xB8"+
		"\x2\x606\x605\x3\x2\x2\x2\x607\x60A\x3\x2\x2\x2\x608\x606\x3\x2\x2\x2"+
		"\x608\x609\x3\x2\x2\x2\x609\x16C\x3\x2\x2\x2\x60A\x608\x3\x2\x2\x2\x60B"+
		"\x60C\t\x6\x2\x2\x60C\x16E\x3\x2\x2\x2\x60D\x60E\t\a\x2\x2\x60E\x170\x3"+
		"\x2\x2\x2\x60F\x613\a$\x2\x2\x610\x612\n\b\x2\x2\x611\x610\x3\x2\x2\x2"+
		"\x612\x615\x3\x2\x2\x2\x613\x611\x3\x2\x2\x2\x613\x614\x3\x2\x2\x2\x614"+
		"\x616\x3\x2\x2\x2\x615\x613\x3\x2\x2\x2\x616\x617\a$\x2\x2\x617\x172\x3"+
		"\x2\x2\x2\x618\x61C\a>\x2\x2\x619\x61B\n\b\x2\x2\x61A\x619\x3\x2\x2\x2"+
		"\x61B\x61E\x3\x2\x2\x2\x61C\x61A\x3\x2\x2\x2\x61C\x61D\x3\x2\x2\x2\x61D"+
		"\x61F\x3\x2\x2\x2\x61E\x61C\x3\x2\x2\x2\x61F\x620\a@\x2\x2\x620\x174\x3"+
		"\x2\x2\x2\x621\x623\x5\t\x5\x2\x622\x621\x3\x2\x2\x2\x622\x623\x3\x2\x2"+
		"\x2\x623\x624\x3\x2\x2\x2\x624\x625\x5\x1BF\xE0\x2\x625\x176\x3\x2\x2"+
		"\x2\x626\x627\v\x2\x2\x2\x627\x178\x3\x2\x2\x2\x628\x629\n\t\x2\x2\x629"+
		"\x17A\x3\x2\x2\x2\x62A\x62D\x5\x17D\xBF\x2\x62B\x62D\x5\x17F\xC0\x2\x62C"+
		"\x62A\x3\x2\x2\x2\x62C\x62B\x3\x2\x2\x2\x62D\x17C\x3\x2\x2\x2\x62E\x62F"+
		"\a^\x2\x2\x62F\x64C\ak\x2\x2\x630\x631\a^\x2\x2\x631\x64C\ar\x2\x2\x632"+
		"\x633\a^\x2\x2\x633\x64C\ah\x2\x2\x634\x635\a^\x2\x2\x635\x64C\a\x64\x2"+
		"\x2\x636\x637\a^\x2\x2\x637\x64C\aK\x2\x2\x638\x639\a^\x2\x2\x639\x64C"+
		"\aq\x2\x2\x63A\x63B\a^\x2\x2\x63B\x64C\a\x63\x2\x2\x63C\x63D\a^\x2\x2"+
		"\x63D\x64C\av\x2\x2\x63E\x63F\a^\x2\x2\x63F\x64C\aR\x2\x2\x640\x641\a"+
		"^\x2\x2\x641\x64C\a\x45\x2\x2\x642\x643\a^\x2\x2\x643\x64C\a)\x2\x2\x644"+
		"\x645\a^\x2\x2\x645\x64C\a$\x2\x2\x646\x647\a^\x2\x2\x647\x64C\a^\x2\x2"+
		"\x648\x649\a^\x2\x2\x649\x64C\a\x32\x2\x2\x64A\x64C\a^\x2\x2\x64B\x62E"+
		"\x3\x2\x2\x2\x64B\x630\x3\x2\x2\x2\x64B\x632\x3\x2\x2\x2\x64B\x634\x3"+
		"\x2\x2\x2\x64B\x636\x3\x2\x2\x2\x64B\x638\x3\x2\x2\x2\x64B\x63A\x3\x2"+
		"\x2\x2\x64B\x63C\x3\x2\x2\x2\x64B\x63E\x3\x2\x2\x2\x64B\x640\x3\x2\x2"+
		"\x2\x64B\x642\x3\x2\x2\x2\x64B\x644\x3\x2\x2\x2\x64B\x646\x3\x2\x2\x2"+
		"\x64B\x648\x3\x2\x2\x2\x64B\x64A\x3\x2\x2\x2\x64C\x17E\x3\x2\x2\x2\x64D"+
		"\x64E\a^\x2\x2\x64E\x64F\az\x2\x2\x64F\x650\x3\x2\x2\x2\x650\x658\x5\x1B5"+
		"\xDB\x2\x651\x652\a^\x2\x2\x652\x653\az\x2\x2\x653\x654\x3\x2\x2\x2\x654"+
		"\x655\x5\x1B5\xDB\x2\x655\x656\x5\x1B5\xDB\x2\x656\x658\x3\x2\x2\x2\x657"+
		"\x64D\x3\x2\x2\x2\x657\x651\x3\x2\x2\x2\x658\x180\x3\x2\x2\x2\x659\x65A"+
		"\t\n\x2\x2\x65A\x182\x3\x2\x2\x2\x65B\x65C\t\x5\x2\x2\x65C\x184\x3\x2"+
		"\x2\x2\x65D\x65E\t\v\x2\x2\x65E\x186\x3\x2\x2\x2\x65F\x660\t\f\x2\x2\x660"+
		"\x188\x3\x2\x2\x2\x661\x662\t\r\x2\x2\x662\x18A\x3\x2\x2\x2\x663\x664"+
		"\t\xE\x2\x2\x664\x18C\x3\x2\x2\x2\x665\x666\t\xF\x2\x2\x666\x18E\x3\x2"+
		"\x2\x2\x667\x668\t\x4\x2\x2\x668\x190\x3\x2\x2\x2\x669\x66A\t\x10\x2\x2"+
		"\x66A\x192\x3\x2\x2\x2\x66B\x66C\t\x11\x2\x2\x66C\x194\x3\x2\x2\x2\x66D"+
		"\x66E\t\x12\x2\x2\x66E\x196\x3\x2\x2\x2\x66F\x670\t\x13\x2\x2\x670\x198"+
		"\x3\x2\x2\x2\x671\x672\t\x14\x2\x2\x672\x19A\x3\x2\x2\x2\x673\x674\t\x15"+
		"\x2\x2\x674\x19C\x3\x2\x2\x2\x675\x676\t\x16\x2\x2\x676\x19E\x3\x2\x2"+
		"\x2\x677\x678\t\x17\x2\x2\x678\x1A0\x3\x2\x2\x2\x679\x67A\t\x18\x2\x2"+
		"\x67A\x1A2\x3\x2\x2\x2\x67B\x67C\t\x19\x2\x2\x67C\x1A4\x3\x2\x2\x2\x67D"+
		"\x67E\t\x1A\x2\x2\x67E\x1A6\x3\x2\x2\x2\x67F\x680\t\x1B\x2\x2\x680\x1A8"+
		"\x3\x2\x2\x2\x681\x682\t\x1C\x2\x2\x682\x1AA\x3\x2\x2\x2\x683\x684\t\x1D"+
		"\x2\x2\x684\x1AC\x3\x2\x2\x2\x685\x686\t\x1E\x2\x2\x686\x1AE\x3\x2\x2"+
		"\x2\x687\x688\t\x1F\x2\x2\x688\x1B0\x3\x2\x2\x2\x689\x68A\t \x2\x2\x68A"+
		"\x1B2\x3\x2\x2\x2\x68B\x68C\t!\x2\x2\x68C\x1B4\x3\x2\x2\x2\x68D\x68F\t"+
		"\"\x2\x2\x68E\x68D\x3\x2\x2\x2\x68F\x1B6\x3\x2\x2\x2\x690\x691\t#\x2\x2"+
		"\x691\x1B8\x3\x2\x2\x2\x692\x695\x5\x1B7\xDC\x2\x693\x695\x4:;\x2\x694"+
		"\x692\x3\x2\x2\x2\x694\x693\x3\x2\x2\x2\x695\x1BA\x3\x2\x2\x2\x696\x698"+
		"\x4\x32\x33\x2\x697\x699\a\x61\x2\x2\x698\x697\x3\x2\x2\x2\x698\x699\x3"+
		"\x2\x2\x2\x699\x1BC\x3\x2\x2\x2\x69A\x69C\t\r\x2\x2\x69B\x69D\t$\x2\x2"+
		"\x69C\x69B\x3\x2\x2\x2\x69C\x69D\x3\x2\x2\x2\x69D\x69F\x3\x2\x2\x2\x69E"+
		"\x6A0\t\x3\x2\x2\x69F\x69E\x3\x2\x2\x2\x6A0\x6A1\x3\x2\x2\x2\x6A1\x69F"+
		"\x3\x2\x2\x2\x6A1\x6A2\x3\x2\x2\x2\x6A2\x1BE\x3\x2\x2\x2\x6A3\x6A4\a\xF"+
		"\x2\x2\x6A4\x6A7\a\f\x2\x2\x6A5\x6A7\t\t\x2\x2\x6A6\x6A3\x3\x2\x2\x2\x6A6"+
		"\x6A5\x3\x2\x2\x2\x6A7\x1C0\x3\x2\x2\x2K\x2\x1C4\x20E\x214\x21B\x21E\x223"+
		"\x226\x22D\x235\x23A\x2AE\x32D\x3D5\x3DA\x3E6\x3EB\x407\x501\x508\x528"+
		"\x58A\x58D\x590\x594\x597\x59A\x59D\x5A1\x5A6\x5A9\x5AC\x5AF\x5B2\x5B5"+
		"\x5B8\x5BB\x5BE\x5C1\x5C4\x5C7\x5CA\x5CD\x5D0\x5D4\x5D7\x5DA\x5DD\x5E0"+
		"\x5E3\x5E6\x5E9\x5EC\x5EF\x5F2\x5F5\x5F8\x5FB\x5FE\x602\x608\x613\x61C"+
		"\x622\x62C\x64B\x657\x68E\x694\x698\x69C\x6A1\x6A6\x3\x2\x3\x2";
	public static readonly ATN _ATN =
		new ATNDeserializer().Deserialize(_serializedATN.ToCharArray());
}
} // namespace Spect.Net.BasicParser.Generated


<|start_filename|>v2/Assembler/Spect.Net.Assembler/SyntaxTree/Expressions/IdentifierNode.cs<|end_filename|>
using System.Text;
using Spect.Net.Assembler.Generated;

namespace Spect.Net.Assembler.SyntaxTree.Expressions
{
    /// <summary>
    /// This node represents an identifier as an expression
    /// </summary>
    public sealed class IdentifierNode : ExpressionNode
    {
        /// <summary>
        /// Signs if identifier evaluation should start at the global scope.
        /// </summary>
        public bool StartFromGlobal { get; set; }

        /// <summary>
        /// The name of the symbol
        /// </summary>
        public string SymbolName { get; set; }

        /// <summary>
        /// This property signs if an expression is ready to be evaluated,
        /// namely, all subexpression values are known
        /// </summary>
        /// <param name="evalContext">Evaluation context</param>
        /// <returns>True, if the expression is ready; otherwise, false</returns>
        public override bool ReadyToEvaluate(IEvaluationContext evalContext)
        {
            var result = evalContext.GetSymbolValue(SymbolName, StartFromGlobal).ExprValue != null;
            if (!result)
            {
                AddError(FullSymbolName);
            }
            return result;
        }

        /// <summary>
        /// Retrieves the value of the expression
        /// </summary>
        /// <param name="evalContext">Evaluation context</param>
        /// <returns>Evaluated expression value</returns>
        public override ExpressionValue Evaluate(IEvaluationContext evalContext)
        {
            var (exprValue, usageInfo) = evalContext.GetSymbolValue(SymbolName, StartFromGlobal);
            if (exprValue != null)
            {
                if (usageInfo != null)
                {
                    usageInfo.IsUsed = true;
                }
                return exprValue;
            }
            AddError(FullSymbolName);
            return ExpressionValue.NonEvaluated;
        }

        /// <summary>
        /// Gets the full name of the symbol
        /// </summary>
        public string FullSymbolName
        {
            get
            {
                var sb = new StringBuilder();
                if (StartFromGlobal) sb.Append("::");
                sb.Append(SymbolName);
                return sb.ToString();
            }
        }

        public IdentifierNode(Z80AsmParser.SymbolContext context) : base(context)
        {
            StartFromGlobal = context.GetChild(0).GetText() == "::";
            SymbolName = context.IDENTIFIER()?.GetText();
        }
    }
}

<|start_filename|>v2/Core/Spect.Net.Wpf/Providers/AudioWaveProvider.cs<|end_filename|>
﻿using Spect.Net.SpectrumEmu.Abstraction.Configuration;
using Spect.Net.SpectrumEmu.Abstraction.Devices;
using Spect.Net.SpectrumEmu.Abstraction.Providers;
using Spect.Net.Wpf.Audio;

namespace Spect.Net.Wpf.Providers
{
    /// <summary>
    /// Type of the audio provider
    /// </summary>
    public enum AudioProviderType
    {
        Beeper = 1,
        Psg 
    }

    /// <summary>
    /// This renderer renders the ear bit pulses into an MME wave form
    /// </summary>
    public class AudioWaveProvider: VmComponentProviderBase, ISoundProvider, ISampleProvider
    {
        /// <summary>
        /// Number of sound frames buffered
        /// </summary>
        public const int FRAMES_BUFFERED = 50;
        public const int FRAMES_DELAYED = 2;

        private IAudioConfiguration _audioPars;
        private float[] _waveBuffer;
        private int _bufferLength;
        private int _frameCount;
        private long _writeIndex;
        private long _readIndex;
        private IWavePlayer _waveOut;

        /// <summary>
        /// Type of the audio provider
        /// </summary>
        public AudioProviderType Type { get; }

        /// <summary>
        /// Initializes the provider with the specified name
        /// </summary>
        public AudioWaveProvider(AudioProviderType type = AudioProviderType.Beeper)
        {
            Type = type;
        }

        /// <summary>
        /// Signs that the provider has been attached to the Spectrum virtual machine
        /// </summary>
        public override void OnAttachedToVm(ISpectrumVm hostVm)
        {
            base.OnAttachedToVm(hostVm);
            Reset();
        }

        /// <summary>
        /// Resets the renderer device
        /// </summary>
        public override void Reset()
        {
            try
            {
                _waveOut?.Dispose();
            }
            catch
            {
                // --- We ignore this exception deliberately
            }
            _audioPars = Type == AudioProviderType.Beeper
                ? HostVm.AudioConfiguration :
                HostVm.SoundConfiguration;
            WaveFormat = WaveFormat.CreateIeeeFloatWaveFormat(_audioPars.AudioSampleRate, 1);
            _waveOut = null;
            _bufferLength = (_audioPars.SamplesPerFrame + 1) * FRAMES_BUFFERED;
            _waveBuffer = new float[_bufferLength];
            _frameCount = 0;
            _writeIndex = 0;
            _readIndex = 0;
        }

        /// <summary>
        /// Adds the specified set of pulse samples to the sound
        /// </summary>
        /// <param name="samples">
        /// Array of sound samples (values between 0.0F and 1.0F)
        /// </param>
        public void AddSoundFrame(float[] samples)
        {
            if (_waveOut == null) return;
            foreach (var sample in samples)
            {
                _waveBuffer[_writeIndex++] = sample;
                if (_writeIndex >= _bufferLength) _writeIndex = 0;
            }
        }

        /// <summary>
        /// Gets the WaveFormat of this Sample Provider.
        /// </summary>
        /// <value>The wave format.</value>
        public WaveFormat WaveFormat { get; private set; }

        /// <summary>
        /// Fill the specified buffer with 32 bit floating point samples
        /// </summary>
        /// <param name="buffer">The buffer to fill with samples.</param>
        /// <param name="offset">Offset into buffer</param>
        /// <param name="count">The number of samples to read</param>
        /// <returns>the number of samples written to the buffer.</returns>
        public int Read(float[] buffer, int offset, int count)
        {
            // --- We set up the initial buffer content for desired latency
            if (_frameCount <= FRAMES_DELAYED)
            {
                for (var i = 0; i < count; i++)
                {
                    buffer[offset++] = 0.0F;
                }
            }
            else
            {
                // --- We use the real samples
                for (var i = 0; i < count; i++)
                {
                    buffer[offset++] = _waveBuffer[_readIndex++];
                    if (_readIndex >= _bufferLength) _readIndex = 0;
                }
            }
            _frameCount++;
            return count;
        }

        public void PlaySound()
        {
            if (_waveOut == null)
            {
                SetupSound();
                _waveOut.Volume = 1.0F;
                _waveOut?.Play();
            }

        }

        public void PauseSound()
        {
            _waveOut?.Pause();            
        }

        public void KillSound()
        {
            if (_waveOut == null) return;

            _waveOut.Volume = 0.0F;
            _waveOut.Stop();
            _waveOut.Dispose();
            _waveOut = null;
        }

        private void SetupSound()
        {
            Reset();
            _waveOut = new WaveOut
            {
                DesiredLatency = 100,
            };
            _waveOut.Init(this);
            _waveOut.Volume = 1.0F;
        }
    }
}

<|start_filename|>v2/Assembler/Spect.Net.Assembler/Generated/Z80AsmLexer.cs<|end_filename|>
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     ANTLR Version: 4.6.4
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

// Generated from C:\Users\dotne\source\repos\spectnetide\v2\Assembler\AntlrZ80AsmParserGenerator\ParserGenerator\Z80Asm.g4 by ANTLR 4.6.4

// Unreachable code detected
#pragma warning disable 0162
// The variable '...' is assigned but its value is never used
#pragma warning disable 0219
// Missing XML comment for publicly visible type or member '...'
#pragma warning disable 1591
// Ambiguous reference in cref attribute
#pragma warning disable 419

namespace Spect.Net.Assembler.Generated {
using Antlr4.Runtime;
using Antlr4.Runtime.Atn;
using Antlr4.Runtime.Misc;
using DFA = Antlr4.Runtime.Dfa.DFA;

[System.CodeDom.Compiler.GeneratedCode("ANTLR", "4.6.4")]
[System.CLSCompliant(false)]
public partial class Z80AsmLexer : Lexer {
	public const int
		WS=1, BLCOMMENT=2, COMMENT=3, NEWLINE=4, COLON=5, DCOLON=6, SCOLON=7, 
		COMSEP=8, COMMA=9, ASSIGN=10, LPAR=11, RPAR=12, LSBRAC=13, RSBRAC=14, 
		QMARK=15, PLUS=16, MINUS=17, VBAR=18, UPARR=19, AMP=20, EQOP=21, CIEQOP=22, 
		NEQOP=23, CINEQOP=24, LTOP=25, LTEOP=26, GTOP=27, GTEOP=28, LSHOP=29, 
		RSHOP=30, MULOP=31, DIVOP=32, MODOP=33, MINOP=34, MAXOP=35, TILDE=36, 
		LDBRAC=37, RDBRAC=38, EXCLM=39, DOT=40, GOESTO=41, A=42, B=43, C=44, D=45, 
		E=46, H=47, L=48, I=49, R=50, XL=51, XH=52, YL=53, YH=54, BC=55, DE=56, 
		HL=57, SP=58, IX=59, IY=60, AF=61, AF_=62, Z=63, NZ=64, NC=65, PO=66, 
		PE=67, P=68, M=69, NOP=70, RLCA=71, RRCA=72, RLA=73, RRA=74, DAA=75, CPL=76, 
		SCF=77, CCF=78, HALT=79, RET=80, EXX=81, DI=82, EI=83, NEG=84, RETN=85, 
		RETI=86, RLD=87, RRD=88, LDI=89, CPI=90, INI=91, OUTI=92, LDD=93, CPD=94, 
		IND=95, OUTD=96, LDIR=97, CPIR=98, INIR=99, OTIR=100, LDDR=101, CPDR=102, 
		INDR=103, OTDR=104, LD=105, INC=106, DEC=107, EX=108, ADD=109, ADC=110, 
		SUB=111, SBC=112, AND=113, XOR=114, OR=115, CP=116, DJNZ=117, JR=118, 
		JP=119, CALL=120, RST=121, PUSH=122, POP=123, IN=124, OUT=125, IM=126, 
		RLC=127, RRC=128, RL=129, RR=130, SLA=131, SRA=132, SLL=133, SRL=134, 
		BIT=135, RES=136, SET=137, SWAPNIB=138, MUL=139, POPX=140, MIRROR=141, 
		TEST=142, NEXTREG=143, OUTINB=144, LDIX=145, LDIRX=146, LDDX=147, LDDRX=148, 
		PIXELDN=149, PIXELAD=150, SETAE=151, LDPIRX=152, LDIRSCALE=153, IFDEF=154, 
		IFNDEF=155, ENDIF=156, ELSE=157, DEFINE=158, UNDEF=159, INCLUDE=160, IF=161, 
		IFMOD=162, IFNMOD=163, LINEDIR=164, ORGPRAG=165, BANKPRAG=166, XORGPR=167, 
		ENTPRAG=168, XENTPRAG=169, EQUPRAG=170, VARPRAG=171, DISPRAG=172, DBPRAG=173, 
		DWPRAG=174, DMPRAG=175, DNPRAG=176, DHPRAG=177, DGXPRAG=178, DGPRAG=179, 
		DCPRAG=180, SKIPRAG=181, EXTPRAG=182, DSPRAG=183, FBPRAG=184, FWPRAG=185, 
		MODPRAG=186, IOPTPRAG=187, ALGPRAG=188, TRACE=189, TRACEHEX=190, RNDSEED=191, 
		ERRORPR=192, INCBIN=193, COMPAREBIN=194, ZXBPRAG=195, MACRO=196, ENDMACRO=197, 
		PROC=198, ENDPROC=199, LOOP=200, ENDLOOP=201, REPEAT=202, UNTIL=203, WHILE=204, 
		ENDWHILE=205, IFSTMT=206, IFUSED=207, IFNUSED=208, ELIF=209, ELSESTMT=210, 
		ENDIFSTMT=211, FOR=212, TO=213, STEP=214, FORNEXT=215, NEXT=216, BREAK=217, 
		CONTINUE=218, MODULE=219, ENDMOD=220, STRUCT=221, ENDST=222, LOCAL=223, 
		SINGLETON=224, TEXTOF=225, LTEXTOF=226, HREG=227, LREG=228, DEF=229, ISREG8=230, 
		ISREG8STD=231, ISREG8SPEC=232, ISREG8IDX=233, ISREG16=234, ISREG16STD=235, 
		ISREG16IDX=236, ISREGINDIRECT=237, ISCPORT=238, ISINDEXEDADDR=239, ISCONDITION=240, 
		ISEXPR=241, ISREGA=242, ISREGAF=243, ISREGB=244, ISREGC=245, ISREGBC=246, 
		ISREGD=247, ISREGE=248, ISREGDE=249, ISREGH=250, ISREGL=251, ISREGHL=252, 
		ISREGI=253, ISREGR=254, ISREGSP=255, ISREGXH=256, ISREGXL=257, ISREGIX=258, 
		ISREGYH=259, ISREGYL=260, ISREGIY=261, HEXNUM=262, BINNUM=263, OCTNUM=264, 
		DECNUM=265, CURADDR=266, REALNUM=267, CHAR=268, STRING=269, BOOLLIT=270, 
		TRUE=271, FALSE=272, CURCNT=273, IDENTIFIER=274, IDSTART=275, IDCONT=276, 
		NONEARG=277, ErrorCharacter=278;
	public static string[] modeNames = {
		"DEFAULT_MODE"
	};

	public static readonly string[] ruleNames = {
		"WS", "BLCOMMENT", "COMMENT", "NEWLINE", "COLON", "DCOLON", "SCOLON", 
		"COMSEP", "COMMA", "ASSIGN", "LPAR", "RPAR", "LSBRAC", "RSBRAC", "QMARK", 
		"PLUS", "MINUS", "VBAR", "UPARR", "AMP", "EQOP", "CIEQOP", "NEQOP", "CINEQOP", 
		"LTOP", "LTEOP", "GTOP", "GTEOP", "LSHOP", "RSHOP", "MULOP", "DIVOP", 
		"MODOP", "MINOP", "MAXOP", "TILDE", "LDBRAC", "RDBRAC", "EXCLM", "DOT", 
		"GOESTO", "A", "B", "C", "D", "E", "H", "L", "I", "R", "XL", "XH", "YL", 
		"YH", "BC", "DE", "HL", "SP", "IX", "IY", "AF", "AF_", "Z", "NZ", "NC", 
		"PO", "PE", "P", "M", "NOP", "RLCA", "RRCA", "RLA", "RRA", "DAA", "CPL", 
		"SCF", "CCF", "HALT", "RET", "EXX", "DI", "EI", "NEG", "RETN", "RETI", 
		"RLD", "RRD", "LDI", "CPI", "INI", "OUTI", "LDD", "CPD", "IND", "OUTD", 
		"LDIR", "CPIR", "INIR", "OTIR", "LDDR", "CPDR", "INDR", "OTDR", "LD", 
		"INC", "DEC", "EX", "ADD", "ADC", "SUB", "SBC", "AND", "XOR", "OR", "CP", 
		"DJNZ", "JR", "JP", "CALL", "RST", "PUSH", "POP", "IN", "OUT", "IM", "RLC", 
		"RRC", "RL", "RR", "SLA", "SRA", "SLL", "SRL", "BIT", "RES", "SET", "SWAPNIB", 
		"MUL", "POPX", "MIRROR", "TEST", "NEXTREG", "OUTINB", "LDIX", "LDIRX", 
		"LDDX", "LDDRX", "PIXELDN", "PIXELAD", "SETAE", "LDPIRX", "LDIRSCALE", 
		"IFDEF", "IFNDEF", "ENDIF", "ELSE", "DEFINE", "UNDEF", "INCLUDE", "IF", 
		"IFMOD", "IFNMOD", "LINEDIR", "ORGPRAG", "BANKPRAG", "XORGPR", "ENTPRAG", 
		"XENTPRAG", "EQUPRAG", "VARPRAG", "DISPRAG", "DBPRAG", "DWPRAG", "DMPRAG", 
		"DNPRAG", "DHPRAG", "DGXPRAG", "DGPRAG", "DCPRAG", "SKIPRAG", "EXTPRAG", 
		"DSPRAG", "FBPRAG", "FWPRAG", "MODPRAG", "IOPTPRAG", "ALGPRAG", "TRACE", 
		"TRACEHEX", "RNDSEED", "ERRORPR", "INCBIN", "COMPAREBIN", "ZXBPRAG", "MACRO", 
		"ENDMACRO", "PROC", "ENDPROC", "LOOP", "ENDLOOP", "REPEAT", "UNTIL", "WHILE", 
		"ENDWHILE", "IFSTMT", "IFUSED", "IFNUSED", "ELIF", "ELSESTMT", "ENDIFSTMT", 
		"FOR", "TO", "STEP", "FORNEXT", "NEXT", "BREAK", "CONTINUE", "MODULE", 
		"ENDMOD", "STRUCT", "ENDST", "LOCAL", "SINGLETON", "TEXTOF", "LTEXTOF", 
		"HREG", "LREG", "DEF", "ISREG8", "ISREG8STD", "ISREG8SPEC", "ISREG8IDX", 
		"ISREG16", "ISREG16STD", "ISREG16IDX", "ISREGINDIRECT", "ISCPORT", "ISINDEXEDADDR", 
		"ISCONDITION", "ISEXPR", "ISREGA", "ISREGAF", "ISREGB", "ISREGC", "ISREGBC", 
		"ISREGD", "ISREGE", "ISREGDE", "ISREGH", "ISREGL", "ISREGHL", "ISREGI", 
		"ISREGR", "ISREGSP", "ISREGXH", "ISREGXL", "ISREGIX", "ISREGYH", "ISREGYL", 
		"ISREGIY", "HEXNUM", "BINNUM", "OCTNUM", "DECNUM", "CURADDR", "REALNUM", 
		"CHAR", "STRING", "BOOLLIT", "TRUE", "FALSE", "CURCNT", "IDENTIFIER", 
		"IDSTART", "IDCONT", "NONEARG", "ErrorCharacter", "CommonCharacter", "SimpleEscapeSequence", 
		"HexEscapeSequence", "HexDigit", "OctDigit", "Digit", "BinDigit", "ExponentPart"
	};


	public Z80AsmLexer(ICharStream input)
		: base(input)
	{
		_interp = new LexerATNSimulator(this,_ATN);
	}

	private static readonly string[] _LiteralNames = {
		null, null, null, null, null, "':'", "'::'", "';'", "'//'", "','", "'='", 
		"'('", "')'", "'['", "']'", "'?'", "'+'", "'-'", "'|'", "'^'", "'&'", 
		"'=='", "'==='", "'!='", "'!=='", "'<'", "'<='", "'>'", "'>='", "'<<'", 
		"'>>'", "'*'", "'/'", "'%'", "'<?'", "'>?'", "'~'", "'{{'", "'}}'", "'!'", 
		"'.'", "'->'", null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, "'#ifdef'", "'#ifndef'", "'#endif'", 
		"'#else'", "'#define'", "'#undef'", "'#include'", "'#if'", "'#ifmod'", 
		"'#ifnmod'", "'#line'", null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, null, null, null, 
		null, null, null, null, null, null, null, null, null, "'$'", null, null, 
		null, null, null, null, null, null, null, null, "'$<none>$'"
	};
	private static readonly string[] _SymbolicNames = {
		null, "WS", "BLCOMMENT", "COMMENT", "NEWLINE", "COLON", "DCOLON", "SCOLON", 
		"COMSEP", "COMMA", "ASSIGN", "LPAR", "RPAR", "LSBRAC", "RSBRAC", "QMARK", 
		"PLUS", "MINUS", "VBAR", "UPARR", "AMP", "EQOP", "CIEQOP", "NEQOP", "CINEQOP", 
		"LTOP", "LTEOP", "GTOP", "GTEOP", "LSHOP", "RSHOP", "MULOP", "DIVOP", 
		"MODOP", "MINOP", "MAXOP", "TILDE", "LDBRAC", "RDBRAC", "EXCLM", "DOT", 
		"GOESTO", "A", "B", "C", "D", "E", "H", "L", "I", "R", "XL", "XH", "YL", 
		"YH", "BC", "DE", "HL", "SP", "IX", "IY", "AF", "AF_", "Z", "NZ", "NC", 
		"PO", "PE", "P", "M", "NOP", "RLCA", "RRCA", "RLA", "RRA", "DAA", "CPL", 
		"SCF", "CCF", "HALT", "RET", "EXX", "DI", "EI", "NEG", "RETN", "RETI", 
		"RLD", "RRD", "LDI", "CPI", "INI", "OUTI", "LDD", "CPD", "IND", "OUTD", 
		"LDIR", "CPIR", "INIR", "OTIR", "LDDR", "CPDR", "INDR", "OTDR", "LD", 
		"INC", "DEC", "EX", "ADD", "ADC", "SUB", "SBC", "AND", "XOR", "OR", "CP", 
		"DJNZ", "JR", "JP", "CALL", "RST", "PUSH", "POP", "IN", "OUT", "IM", "RLC", 
		"RRC", "RL", "RR", "SLA", "SRA", "SLL", "SRL", "BIT", "RES", "SET", "SWAPNIB", 
		"MUL", "POPX", "MIRROR", "TEST", "NEXTREG", "OUTINB", "LDIX", "LDIRX", 
		"LDDX", "LDDRX", "PIXELDN", "PIXELAD", "SETAE", "LDPIRX", "LDIRSCALE", 
		"IFDEF", "IFNDEF", "ENDIF", "ELSE", "DEFINE", "UNDEF", "INCLUDE", "IF", 
		"IFMOD", "IFNMOD", "LINEDIR", "ORGPRAG", "BANKPRAG", "XORGPR", "ENTPRAG", 
		"XENTPRAG", "EQUPRAG", "VARPRAG", "DISPRAG", "DBPRAG", "DWPRAG", "DMPRAG", 
		"DNPRAG", "DHPRAG", "DGXPRAG", "DGPRAG", "DCPRAG", "SKIPRAG", "EXTPRAG", 
		"DSPRAG", "FBPRAG", "FWPRAG", "MODPRAG", "IOPTPRAG", "ALGPRAG", "TRACE", 
		"TRACEHEX", "RNDSEED", "ERRORPR", "INCBIN", "COMPAREBIN", "ZXBPRAG", "MACRO", 
		"ENDMACRO", "PROC", "ENDPROC", "LOOP", "ENDLOOP", "REPEAT", "UNTIL", "WHILE", 
		"ENDWHILE", "IFSTMT", "IFUSED", "IFNUSED", "ELIF", "ELSESTMT", "ENDIFSTMT", 
		"FOR", "TO", "STEP", "FORNEXT", "NEXT", "BREAK", "CONTINUE", "MODULE", 
		"ENDMOD", "STRUCT", "ENDST", "LOCAL", "SINGLETON", "TEXTOF", "LTEXTOF", 
		"HREG", "LREG", "DEF", "ISREG8", "ISREG8STD", "ISREG8SPEC", "ISREG8IDX", 
		"ISREG16", "ISREG16STD", "ISREG16IDX", "ISREGINDIRECT", "ISCPORT", "ISINDEXEDADDR", 
		"ISCONDITION", "ISEXPR", "ISREGA", "ISREGAF", "ISREGB", "ISREGC", "ISREGBC", 
		"ISREGD", "ISREGE", "ISREGDE", "ISREGH", "ISREGL", "ISREGHL", "ISREGI", 
		"ISREGR", "ISREGSP", "ISREGXH", "ISREGXL", "ISREGIX", "ISREGYH", "ISREGYL", 
		"ISREGIY", "HEXNUM", "BINNUM", "OCTNUM", "DECNUM", "CURADDR", "REALNUM", 
		"CHAR", "STRING", "BOOLLIT", "TRUE", "FALSE", "CURCNT", "IDENTIFIER", 
		"IDSTART", "IDCONT", "NONEARG", "ErrorCharacter"
	};
	public static readonly IVocabulary DefaultVocabulary = new Vocabulary(_LiteralNames, _SymbolicNames);

	[System.Obsolete("Use Vocabulary instead.")]
	public static readonly string[] tokenNames = GenerateTokenNames(DefaultVocabulary, _SymbolicNames.Length);

	private static string[] GenerateTokenNames(IVocabulary vocabulary, int length) {
		string[] tokenNames = new string[length];
		for (int i = 0; i < tokenNames.Length; i++) {
			tokenNames[i] = vocabulary.GetLiteralName(i);
			if (tokenNames[i] == null) {
				tokenNames[i] = vocabulary.GetSymbolicName(i);
			}

			if (tokenNames[i] == null) {
				tokenNames[i] = "<INVALID>";
			}
		}

		return tokenNames;
	}

	[System.Obsolete("Use IRecognizer.Vocabulary instead.")]
	public override string[] TokenNames
	{
		get
		{
			return tokenNames;
		}
	}

	[NotNull]
	public override IVocabulary Vocabulary
	{
		get
		{
			return DefaultVocabulary;
		}
	}

	public override string GrammarFileName { get { return "Z80Asm.g4"; } }

	public override string[] RuleNames { get { return ruleNames; } }

	public override string[] ModeNames { get { return modeNames; } }

	public override string SerializedAtn { get { return _serializedATN; } }

	public static readonly string _serializedATN =
		"\x3\xAF6F\x8320\x479D\xB75C\x4880\x1605\x191C\xAB37\x2\x118\x10C3\b\x1"+
		"\x4\x2\t\x2\x4\x3\t\x3\x4\x4\t\x4\x4\x5\t\x5\x4\x6\t\x6\x4\a\t\a\x4\b"+
		"\t\b\x4\t\t\t\x4\n\t\n\x4\v\t\v\x4\f\t\f\x4\r\t\r\x4\xE\t\xE\x4\xF\t\xF"+
		"\x4\x10\t\x10\x4\x11\t\x11\x4\x12\t\x12\x4\x13\t\x13\x4\x14\t\x14\x4\x15"+
		"\t\x15\x4\x16\t\x16\x4\x17\t\x17\x4\x18\t\x18\x4\x19\t\x19\x4\x1A\t\x1A"+
		"\x4\x1B\t\x1B\x4\x1C\t\x1C\x4\x1D\t\x1D\x4\x1E\t\x1E\x4\x1F\t\x1F\x4 "+
		"\t \x4!\t!\x4\"\t\"\x4#\t#\x4$\t$\x4%\t%\x4&\t&\x4\'\t\'\x4(\t(\x4)\t"+
		")\x4*\t*\x4+\t+\x4,\t,\x4-\t-\x4.\t.\x4/\t/\x4\x30\t\x30\x4\x31\t\x31"+
		"\x4\x32\t\x32\x4\x33\t\x33\x4\x34\t\x34\x4\x35\t\x35\x4\x36\t\x36\x4\x37"+
		"\t\x37\x4\x38\t\x38\x4\x39\t\x39\x4:\t:\x4;\t;\x4<\t<\x4=\t=\x4>\t>\x4"+
		"?\t?\x4@\t@\x4\x41\t\x41\x4\x42\t\x42\x4\x43\t\x43\x4\x44\t\x44\x4\x45"+
		"\t\x45\x4\x46\t\x46\x4G\tG\x4H\tH\x4I\tI\x4J\tJ\x4K\tK\x4L\tL\x4M\tM\x4"+
		"N\tN\x4O\tO\x4P\tP\x4Q\tQ\x4R\tR\x4S\tS\x4T\tT\x4U\tU\x4V\tV\x4W\tW\x4"+
		"X\tX\x4Y\tY\x4Z\tZ\x4[\t[\x4\\\t\\\x4]\t]\x4^\t^\x4_\t_\x4`\t`\x4\x61"+
		"\t\x61\x4\x62\t\x62\x4\x63\t\x63\x4\x64\t\x64\x4\x65\t\x65\x4\x66\t\x66"+
		"\x4g\tg\x4h\th\x4i\ti\x4j\tj\x4k\tk\x4l\tl\x4m\tm\x4n\tn\x4o\to\x4p\t"+
		"p\x4q\tq\x4r\tr\x4s\ts\x4t\tt\x4u\tu\x4v\tv\x4w\tw\x4x\tx\x4y\ty\x4z\t"+
		"z\x4{\t{\x4|\t|\x4}\t}\x4~\t~\x4\x7F\t\x7F\x4\x80\t\x80\x4\x81\t\x81\x4"+
		"\x82\t\x82\x4\x83\t\x83\x4\x84\t\x84\x4\x85\t\x85\x4\x86\t\x86\x4\x87"+
		"\t\x87\x4\x88\t\x88\x4\x89\t\x89\x4\x8A\t\x8A\x4\x8B\t\x8B\x4\x8C\t\x8C"+
		"\x4\x8D\t\x8D\x4\x8E\t\x8E\x4\x8F\t\x8F\x4\x90\t\x90\x4\x91\t\x91\x4\x92"+
		"\t\x92\x4\x93\t\x93\x4\x94\t\x94\x4\x95\t\x95\x4\x96\t\x96\x4\x97\t\x97"+
		"\x4\x98\t\x98\x4\x99\t\x99\x4\x9A\t\x9A\x4\x9B\t\x9B\x4\x9C\t\x9C\x4\x9D"+
		"\t\x9D\x4\x9E\t\x9E\x4\x9F\t\x9F\x4\xA0\t\xA0\x4\xA1\t\xA1\x4\xA2\t\xA2"+
		"\x4\xA3\t\xA3\x4\xA4\t\xA4\x4\xA5\t\xA5\x4\xA6\t\xA6\x4\xA7\t\xA7\x4\xA8"+
		"\t\xA8\x4\xA9\t\xA9\x4\xAA\t\xAA\x4\xAB\t\xAB\x4\xAC\t\xAC\x4\xAD\t\xAD"+
		"\x4\xAE\t\xAE\x4\xAF\t\xAF\x4\xB0\t\xB0\x4\xB1\t\xB1\x4\xB2\t\xB2\x4\xB3"+
		"\t\xB3\x4\xB4\t\xB4\x4\xB5\t\xB5\x4\xB6\t\xB6\x4\xB7\t\xB7\x4\xB8\t\xB8"+
		"\x4\xB9\t\xB9\x4\xBA\t\xBA\x4\xBB\t\xBB\x4\xBC\t\xBC\x4\xBD\t\xBD\x4\xBE"+
		"\t\xBE\x4\xBF\t\xBF\x4\xC0\t\xC0\x4\xC1\t\xC1\x4\xC2\t\xC2\x4\xC3\t\xC3"+
		"\x4\xC4\t\xC4\x4\xC5\t\xC5\x4\xC6\t\xC6\x4\xC7\t\xC7\x4\xC8\t\xC8\x4\xC9"+
		"\t\xC9\x4\xCA\t\xCA\x4\xCB\t\xCB\x4\xCC\t\xCC\x4\xCD\t\xCD\x4\xCE\t\xCE"+
		"\x4\xCF\t\xCF\x4\xD0\t\xD0\x4\xD1\t\xD1\x4\xD2\t\xD2\x4\xD3\t\xD3\x4\xD4"+
		"\t\xD4\x4\xD5\t\xD5\x4\xD6\t\xD6\x4\xD7\t\xD7\x4\xD8\t\xD8\x4\xD9\t\xD9"+
		"\x4\xDA\t\xDA\x4\xDB\t\xDB\x4\xDC\t\xDC\x4\xDD\t\xDD\x4\xDE\t\xDE\x4\xDF"+
		"\t\xDF\x4\xE0\t\xE0\x4\xE1\t\xE1\x4\xE2\t\xE2\x4\xE3\t\xE3\x4\xE4\t\xE4"+
		"\x4\xE5\t\xE5\x4\xE6\t\xE6\x4\xE7\t\xE7\x4\xE8\t\xE8\x4\xE9\t\xE9\x4\xEA"+
		"\t\xEA\x4\xEB\t\xEB\x4\xEC\t\xEC\x4\xED\t\xED\x4\xEE\t\xEE\x4\xEF\t\xEF"+
		"\x4\xF0\t\xF0\x4\xF1\t\xF1\x4\xF2\t\xF2\x4\xF3\t\xF3\x4\xF4\t\xF4\x4\xF5"+
		"\t\xF5\x4\xF6\t\xF6\x4\xF7\t\xF7\x4\xF8\t\xF8\x4\xF9\t\xF9\x4\xFA\t\xFA"+
		"\x4\xFB\t\xFB\x4\xFC\t\xFC\x4\xFD\t\xFD\x4\xFE\t\xFE\x4\xFF\t\xFF\x4\x100"+
		"\t\x100\x4\x101\t\x101\x4\x102\t\x102\x4\x103\t\x103\x4\x104\t\x104\x4"+
		"\x105\t\x105\x4\x106\t\x106\x4\x107\t\x107\x4\x108\t\x108\x4\x109\t\x109"+
		"\x4\x10A\t\x10A\x4\x10B\t\x10B\x4\x10C\t\x10C\x4\x10D\t\x10D\x4\x10E\t"+
		"\x10E\x4\x10F\t\x10F\x4\x110\t\x110\x4\x111\t\x111\x4\x112\t\x112\x4\x113"+
		"\t\x113\x4\x114\t\x114\x4\x115\t\x115\x4\x116\t\x116\x4\x117\t\x117\x4"+
		"\x118\t\x118\x4\x119\t\x119\x4\x11A\t\x11A\x4\x11B\t\x11B\x4\x11C\t\x11C"+
		"\x4\x11D\t\x11D\x4\x11E\t\x11E\x4\x11F\t\x11F\x3\x2\x6\x2\x241\n\x2\r"+
		"\x2\xE\x2\x242\x3\x2\x3\x2\x3\x3\x3\x3\x3\x3\x3\x3\a\x3\x24B\n\x3\f\x3"+
		"\xE\x3\x24E\v\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x3\x4\x3\x4\x5\x4\x257"+
		"\n\x4\x3\x4\a\x4\x25A\n\x4\f\x4\xE\x4\x25D\v\x4\x3\x5\x5\x5\x260\n\x5"+
		"\x3\x5\x3\x5\x6\x5\x264\n\x5\r\x5\xE\x5\x265\x3\x6\x3\x6\x3\a\x3\a\x3"+
		"\a\x3\b\x3\b\x3\t\x3\t\x3\t\x3\n\x3\n\x3\v\x3\v\x3\f\x3\f\x3\r\x3\r\x3"+
		"\xE\x3\xE\x3\xF\x3\xF\x3\x10\x3\x10\x3\x11\x3\x11\x3\x12\x3\x12\x3\x13"+
		"\x3\x13\x3\x14\x3\x14\x3\x15\x3\x15\x3\x16\x3\x16\x3\x16\x3\x17\x3\x17"+
		"\x3\x17\x3\x17\x3\x18\x3\x18\x3\x18\x3\x19\x3\x19\x3\x19\x3\x19\x3\x1A"+
		"\x3\x1A\x3\x1B\x3\x1B\x3\x1B\x3\x1C\x3\x1C\x3\x1D\x3\x1D\x3\x1D\x3\x1E"+
		"\x3\x1E\x3\x1E\x3\x1F\x3\x1F\x3\x1F\x3 \x3 \x3!\x3!\x3\"\x3\"\x3#\x3#"+
		"\x3#\x3$\x3$\x3$\x3%\x3%\x3&\x3&\x3&\x3\'\x3\'\x3\'\x3(\x3(\x3)\x3)\x3"+
		"*\x3*\x3*\x3+\x3+\x3,\x3,\x3-\x3-\x3.\x3.\x3/\x3/\x3\x30\x3\x30\x3\x31"+
		"\x3\x31\x3\x32\x3\x32\x3\x33\x3\x33\x3\x34\x3\x34\x3\x34\x3\x34\x3\x34"+
		"\x3\x34\x3\x34\x3\x34\x3\x34\x3\x34\x3\x34\x3\x34\x3\x34\x5\x34\x2E2\n"+
		"\x34\x3\x35\x3\x35\x3\x35\x3\x35\x3\x35\x3\x35\x3\x35\x3\x35\x3\x35\x3"+
		"\x35\x3\x35\x3\x35\x3\x35\x5\x35\x2F1\n\x35\x3\x36\x3\x36\x3\x36\x3\x36"+
		"\x3\x36\x3\x36\x3\x36\x3\x36\x3\x36\x3\x36\x3\x36\x3\x36\x3\x36\x5\x36"+
		"\x300\n\x36\x3\x37\x3\x37\x3\x37\x3\x37\x3\x37\x3\x37\x3\x37\x3\x37\x3"+
		"\x37\x3\x37\x3\x37\x3\x37\x3\x37\x5\x37\x30F\n\x37\x3\x38\x3\x38\x3\x38"+
		"\x3\x38\x5\x38\x315\n\x38\x3\x39\x3\x39\x3\x39\x3\x39\x5\x39\x31B\n\x39"+
		"\x3:\x3:\x3:\x3:\x5:\x321\n:\x3;\x3;\x3;\x3;\x5;\x327\n;\x3<\x3<\x3<\x3"+
		"<\x5<\x32D\n<\x3=\x3=\x3=\x3=\x5=\x333\n=\x3>\x3>\x3>\x3>\x5>\x339\n>"+
		"\x3?\x3?\x3?\x3?\x3?\x3?\x5?\x341\n?\x3@\x3@\x3\x41\x3\x41\x3\x41\x3\x41"+
		"\x5\x41\x349\n\x41\x3\x42\x3\x42\x3\x42\x3\x42\x5\x42\x34F\n\x42\x3\x43"+
		"\x3\x43\x3\x43\x3\x43\x5\x43\x355\n\x43\x3\x44\x3\x44\x3\x44\x3\x44\x5"+
		"\x44\x35B\n\x44\x3\x45\x3\x45\x3\x46\x3\x46\x3G\x3G\x3G\x3G\x3G\x3G\x5"+
		"G\x367\nG\x3H\x3H\x3H\x3H\x3H\x3H\x3H\x3H\x5H\x371\nH\x3I\x3I\x3I\x3I"+
		"\x3I\x3I\x3I\x3I\x5I\x37B\nI\x3J\x3J\x3J\x3J\x3J\x3J\x5J\x383\nJ\x3K\x3"+
		"K\x3K\x3K\x3K\x3K\x5K\x38B\nK\x3L\x3L\x3L\x3L\x3L\x3L\x5L\x393\nL\x3M"+
		"\x3M\x3M\x3M\x3M\x3M\x5M\x39B\nM\x3N\x3N\x3N\x3N\x3N\x3N\x5N\x3A3\nN\x3"+
		"O\x3O\x3O\x3O\x3O\x3O\x5O\x3AB\nO\x3P\x3P\x3P\x3P\x3P\x3P\x3P\x3P\x5P"+
		"\x3B5\nP\x3Q\x3Q\x3Q\x3Q\x3Q\x3Q\x5Q\x3BD\nQ\x3R\x3R\x3R\x3R\x3R\x3R\x5"+
		"R\x3C5\nR\x3S\x3S\x3S\x3S\x5S\x3CB\nS\x3T\x3T\x3T\x3T\x5T\x3D1\nT\x3U"+
		"\x3U\x3U\x3U\x3U\x3U\x5U\x3D9\nU\x3V\x3V\x3V\x3V\x3V\x3V\x3V\x3V\x5V\x3E3"+
		"\nV\x3W\x3W\x3W\x3W\x3W\x3W\x3W\x3W\x5W\x3ED\nW\x3X\x3X\x3X\x3X\x3X\x3"+
		"X\x5X\x3F5\nX\x3Y\x3Y\x3Y\x3Y\x3Y\x3Y\x5Y\x3FD\nY\x3Z\x3Z\x3Z\x3Z\x3Z"+
		"\x3Z\x5Z\x405\nZ\x3[\x3[\x3[\x3[\x3[\x3[\x5[\x40D\n[\x3\\\x3\\\x3\\\x3"+
		"\\\x3\\\x3\\\x5\\\x415\n\\\x3]\x3]\x3]\x3]\x3]\x3]\x3]\x3]\x5]\x41F\n"+
		"]\x3^\x3^\x3^\x3^\x3^\x3^\x5^\x427\n^\x3_\x3_\x3_\x3_\x3_\x3_\x5_\x42F"+
		"\n_\x3`\x3`\x3`\x3`\x3`\x3`\x5`\x437\n`\x3\x61\x3\x61\x3\x61\x3\x61\x3"+
		"\x61\x3\x61\x3\x61\x3\x61\x5\x61\x441\n\x61\x3\x62\x3\x62\x3\x62\x3\x62"+
		"\x3\x62\x3\x62\x3\x62\x3\x62\x5\x62\x44B\n\x62\x3\x63\x3\x63\x3\x63\x3"+
		"\x63\x3\x63\x3\x63\x3\x63\x3\x63\x5\x63\x455\n\x63\x3\x64\x3\x64\x3\x64"+
		"\x3\x64\x3\x64\x3\x64\x3\x64\x3\x64\x5\x64\x45F\n\x64\x3\x65\x3\x65\x3"+
		"\x65\x3\x65\x3\x65\x3\x65\x3\x65\x3\x65\x5\x65\x469\n\x65\x3\x66\x3\x66"+
		"\x3\x66\x3\x66\x3\x66\x3\x66\x3\x66\x3\x66\x5\x66\x473\n\x66\x3g\x3g\x3"+
		"g\x3g\x3g\x3g\x3g\x3g\x5g\x47D\ng\x3h\x3h\x3h\x3h\x3h\x3h\x3h\x3h\x5h"+
		"\x487\nh\x3i\x3i\x3i\x3i\x3i\x3i\x3i\x3i\x5i\x491\ni\x3j\x3j\x3j\x3j\x5"+
		"j\x497\nj\x3k\x3k\x3k\x3k\x3k\x3k\x5k\x49F\nk\x3l\x3l\x3l\x3l\x3l\x3l"+
		"\x5l\x4A7\nl\x3m\x3m\x3m\x3m\x5m\x4AD\nm\x3n\x3n\x3n\x3n\x3n\x3n\x5n\x4B5"+
		"\nn\x3o\x3o\x3o\x3o\x3o\x3o\x5o\x4BD\no\x3p\x3p\x3p\x3p\x3p\x3p\x5p\x4C5"+
		"\np\x3q\x3q\x3q\x3q\x3q\x3q\x5q\x4CD\nq\x3r\x3r\x3r\x3r\x3r\x3r\x5r\x4D5"+
		"\nr\x3s\x3s\x3s\x3s\x3s\x3s\x5s\x4DD\ns\x3t\x3t\x3t\x3t\x5t\x4E3\nt\x3"+
		"u\x3u\x3u\x3u\x5u\x4E9\nu\x3v\x3v\x3v\x3v\x3v\x3v\x3v\x3v\x5v\x4F3\nv"+
		"\x3w\x3w\x3w\x3w\x5w\x4F9\nw\x3x\x3x\x3x\x3x\x5x\x4FF\nx\x3y\x3y\x3y\x3"+
		"y\x3y\x3y\x3y\x3y\x5y\x509\ny\x3z\x3z\x3z\x3z\x3z\x3z\x5z\x511\nz\x3{"+
		"\x3{\x3{\x3{\x3{\x3{\x3{\x3{\x5{\x51B\n{\x3|\x3|\x3|\x3|\x3|\x3|\x5|\x523"+
		"\n|\x3}\x3}\x3}\x3}\x5}\x529\n}\x3~\x3~\x3~\x3~\x3~\x3~\x5~\x531\n~\x3"+
		"\x7F\x3\x7F\x3\x7F\x3\x7F\x5\x7F\x537\n\x7F\x3\x80\x3\x80\x3\x80\x3\x80"+
		"\x3\x80\x3\x80\x5\x80\x53F\n\x80\x3\x81\x3\x81\x3\x81\x3\x81\x3\x81\x3"+
		"\x81\x5\x81\x547\n\x81\x3\x82\x3\x82\x3\x82\x3\x82\x5\x82\x54D\n\x82\x3"+
		"\x83\x3\x83\x3\x83\x3\x83\x5\x83\x553\n\x83\x3\x84\x3\x84\x3\x84\x3\x84"+
		"\x3\x84\x3\x84\x5\x84\x55B\n\x84\x3\x85\x3\x85\x3\x85\x3\x85\x3\x85\x3"+
		"\x85\x5\x85\x563\n\x85\x3\x86\x3\x86\x3\x86\x3\x86\x3\x86\x3\x86\x5\x86"+
		"\x56B\n\x86\x3\x87\x3\x87\x3\x87\x3\x87\x3\x87\x3\x87\x5\x87\x573\n\x87"+
		"\x3\x88\x3\x88\x3\x88\x3\x88\x3\x88\x3\x88\x5\x88\x57B\n\x88\x3\x89\x3"+
		"\x89\x3\x89\x3\x89\x3\x89\x3\x89\x5\x89\x583\n\x89\x3\x8A\x3\x8A\x3\x8A"+
		"\x3\x8A\x3\x8A\x3\x8A\x5\x8A\x58B\n\x8A\x3\x8B\x3\x8B\x3\x8B\x3\x8B\x3"+
		"\x8B\x3\x8B\x3\x8B\x3\x8B\x3\x8B\x3\x8B\x3\x8B\x3\x8B\x3\x8B\x3\x8B\x5"+
		"\x8B\x59B\n\x8B\x3\x8C\x3\x8C\x3\x8C\x3\x8C\x3\x8C\x3\x8C\x5\x8C\x5A3"+
		"\n\x8C\x3\x8D\x3\x8D\x3\x8D\x3\x8D\x3\x8D\x3\x8D\x3\x8D\x3\x8D\x5\x8D"+
		"\x5AD\n\x8D\x3\x8E\x3\x8E\x3\x8E\x3\x8E\x3\x8E\x3\x8E\x3\x8E\x3\x8E\x3"+
		"\x8E\x3\x8E\x3\x8E\x3\x8E\x5\x8E\x5BB\n\x8E\x3\x8F\x3\x8F\x3\x8F\x3\x8F"+
		"\x3\x8F\x3\x8F\x3\x8F\x3\x8F\x5\x8F\x5C5\n\x8F\x3\x90\x3\x90\x3\x90\x3"+
		"\x90\x3\x90\x3\x90\x3\x90\x3\x90\x3\x90\x3\x90\x3\x90\x3\x90\x3\x90\x3"+
		"\x90\x5\x90\x5D5\n\x90\x3\x91\x3\x91\x3\x91\x3\x91\x3\x91\x3\x91\x3\x91"+
		"\x3\x91\x3\x91\x3\x91\x3\x91\x3\x91\x5\x91\x5E3\n\x91\x3\x92\x3\x92\x3"+
		"\x92\x3\x92\x3\x92\x3\x92\x3\x92\x3\x92\x5\x92\x5ED\n\x92\x3\x93\x3\x93"+
		"\x3\x93\x3\x93\x3\x93\x3\x93\x3\x93\x3\x93\x3\x93\x3\x93\x5\x93\x5F9\n"+
		"\x93\x3\x94\x3\x94\x3\x94\x3\x94\x3\x94\x3\x94\x3\x94\x3\x94\x5\x94\x603"+
		"\n\x94\x3\x95\x3\x95\x3\x95\x3\x95\x3\x95\x3\x95\x3\x95\x3\x95\x3\x95"+
		"\x3\x95\x5\x95\x60F\n\x95\x3\x96\x3\x96\x3\x96\x3\x96\x3\x96\x3\x96\x3"+
		"\x96\x3\x96\x3\x96\x3\x96\x3\x96\x3\x96\x3\x96\x3\x96\x5\x96\x61F\n\x96"+
		"\x3\x97\x3\x97\x3\x97\x3\x97\x3\x97\x3\x97\x3\x97\x3\x97\x3\x97\x3\x97"+
		"\x3\x97\x3\x97\x3\x97\x3\x97\x5\x97\x62F\n\x97\x3\x98\x3\x98\x3\x98\x3"+
		"\x98\x3\x98\x3\x98\x3\x98\x3\x98\x3\x98\x3\x98\x5\x98\x63B\n\x98\x3\x99"+
		"\x3\x99\x3\x99\x3\x99\x3\x99\x3\x99\x3\x99\x3\x99\x3\x99\x3\x99\x3\x99"+
		"\x3\x99\x5\x99\x649\n\x99\x3\x9A\x3\x9A\x3\x9A\x3\x9A\x3\x9A\x3\x9A\x3"+
		"\x9A\x3\x9A\x3\x9A\x3\x9A\x3\x9A\x3\x9A\x3\x9A\x3\x9A\x3\x9A\x3\x9A\x3"+
		"\x9A\x3\x9A\x5\x9A\x65D\n\x9A\x3\x9B\x3\x9B\x3\x9B\x3\x9B\x3\x9B\x3\x9B"+
		"\x3\x9B\x3\x9C\x3\x9C\x3\x9C\x3\x9C\x3\x9C\x3\x9C\x3\x9C\x3\x9C\x3\x9D"+
		"\x3\x9D\x3\x9D\x3\x9D\x3\x9D\x3\x9D\x3\x9D\x3\x9E\x3\x9E\x3\x9E\x3\x9E"+
		"\x3\x9E\x3\x9E\x3\x9F\x3\x9F\x3\x9F\x3\x9F\x3\x9F\x3\x9F\x3\x9F\x3\x9F"+
		"\x3\xA0\x3\xA0\x3\xA0\x3\xA0\x3\xA0\x3\xA0\x3\xA0\x3\xA1\x3\xA1\x3\xA1"+
		"\x3\xA1\x3\xA1\x3\xA1\x3\xA1\x3\xA1\x3\xA1\x3\xA2\x3\xA2\x3\xA2\x3\xA2"+
		"\x3\xA3\x3\xA3\x3\xA3\x3\xA3\x3\xA3\x3\xA3\x3\xA3\x3\xA4\x3\xA4\x3\xA4"+
		"\x3\xA4\x3\xA4\x3\xA4\x3\xA4\x3\xA4\x3\xA5\x3\xA5\x3\xA5\x3\xA5\x3\xA5"+
		"\x3\xA5\x3\xA6\x3\xA6\x3\xA6\x3\xA6\x3\xA6\x3\xA6\x3\xA6\x3\xA6\x3\xA6"+
		"\x3\xA6\x3\xA6\x3\xA6\x3\xA6\x3\xA6\x5\xA6\x6BA\n\xA6\x3\xA7\x3\xA7\x3"+
		"\xA7\x3\xA7\x3\xA7\x3\xA7\x3\xA7\x3\xA7\x3\xA7\x3\xA7\x3\xA7\x3\xA7\x3"+
		"\xA7\x3\xA7\x3\xA7\x3\xA7\x3\xA7\x3\xA7\x5\xA7\x6CE\n\xA7\x3\xA8\x3\xA8"+
		"\x3\xA8\x3\xA8\x3\xA8\x3\xA8\x3\xA8\x3\xA8\x3\xA8\x3\xA8\x3\xA8\x3\xA8"+
		"\x3\xA8\x3\xA8\x3\xA8\x3\xA8\x3\xA8\x3\xA8\x5\xA8\x6E2\n\xA8\x3\xA9\x3"+
		"\xA9\x3\xA9\x3\xA9\x3\xA9\x3\xA9\x3\xA9\x3\xA9\x3\xA9\x3\xA9\x3\xA9\x3"+
		"\xA9\x3\xA9\x3\xA9\x5\xA9\x6F2\n\xA9\x3\xAA\x3\xAA\x3\xAA\x3\xAA\x3\xAA"+
		"\x3\xAA\x3\xAA\x3\xAA\x3\xAA\x3\xAA\x3\xAA\x3\xAA\x3\xAA\x3\xAA\x3\xAA"+
		"\x3\xAA\x3\xAA\x3\xAA\x5\xAA\x706\n\xAA\x3\xAB\x3\xAB\x3\xAB\x3\xAB\x3"+
		"\xAB\x3\xAB\x3\xAB\x3\xAB\x3\xAB\x3\xAB\x3\xAB\x3\xAB\x3\xAB\x3\xAB\x5"+
		"\xAB\x716\n\xAB\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAC"+
		"\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x3\xAC\x5\xAC\x728\n"+
		"\xAC\x3\xAD\x3\xAD\x3\xAD\x3\xAD\x3\xAD\x3\xAD\x3\xAD\x3\xAD\x3\xAD\x3"+
		"\xAD\x3\xAD\x3\xAD\x3\xAD\x3\xAD\x3\xAD\x3\xAD\x3\xAD\x3\xAD\x5\xAD\x73C"+
		"\n\xAD\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE"+
		"\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE"+
		"\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x3\xAE\x5\xAE"+
		"\x75A\n\xAE\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3"+
		"\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3"+
		"\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x3\xAF\x5"+
		"\xAF\x778\n\xAF\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0"+
		"\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0"+
		"\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0\x3\xB0"+
		"\x5\xB0\x796\n\xB0\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3"+
		"\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3"+
		"\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3\xB1\x3"+
		"\xB1\x5\xB1\x7B4\n\xB1\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2"+
		"\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2"+
		"\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2\x3\xB2"+
		"\x3\xB2\x5\xB2\x7D2\n\xB2\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3"+
		"\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3"+
		"\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3"+
		"\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x3\xB3\x5"+
		"\xB3\x7F8\n\xB3\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4"+
		"\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4"+
		"\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4\x3\xB4"+
		"\x5\xB4\x816\n\xB4\x3\xB4\x6\xB4\x819\n\xB4\r\xB4\xE\xB4\x81A\x3\xB4\x6"+
		"\xB4\x81E\n\xB4\r\xB4\xE\xB4\x81F\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3"+
		"\xB5\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3"+
		"\xB5\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3\xB5\x3"+
		"\xB5\x3\xB5\x3\xB5\x5\xB5\x83E\n\xB5\x3\xB6\x3\xB6\x3\xB6\x3\xB6\x3\xB6"+
		"\x3\xB6\x3\xB6\x3\xB6\x3\xB6\x3\xB6\x3\xB6\x3\xB6\x3\xB6\x3\xB6\x3\xB6"+
		"\x3\xB6\x3\xB6\x3\xB6\x5\xB6\x852\n\xB6\x3\xB7\x3\xB7\x3\xB7\x3\xB7\x3"+
		"\xB7\x3\xB7\x3\xB7\x3\xB7\x3\xB7\x3\xB7\x3\xB7\x3\xB7\x3\xB7\x3\xB7\x3"+
		"\xB7\x3\xB7\x3\xB7\x3\xB7\x3\xB7\x3\xB7\x3\xB7\x3\xB7\x3\xB7\x3\xB7\x3"+
		"\xB7\x3\xB7\x5\xB7\x86E\n\xB7\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8"+
		"\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8"+
		"\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8\x3\xB8"+
		"\x3\xB8\x3\xB8\x5\xB8\x88C\n\xB8\x3\xB9\x3\xB9\x3\xB9\x3\xB9\x3\xB9\x3"+
		"\xB9\x3\xB9\x3\xB9\x3\xB9\x3\xB9\x3\xB9\x3\xB9\x3\xB9\x3\xB9\x3\xB9\x3"+
		"\xB9\x3\xB9\x3\xB9\x3\xB9\x3\xB9\x3\xB9\x3\xB9\x5\xB9\x8A4\n\xB9\x3\xBA"+
		"\x3\xBA\x3\xBA\x3\xBA\x3\xBA\x3\xBA\x3\xBA\x3\xBA\x3\xBA\x3\xBA\x3\xBA"+
		"\x3\xBA\x3\xBA\x3\xBA\x3\xBA\x3\xBA\x3\xBA\x3\xBA\x3\xBA\x3\xBA\x3\xBA"+
		"\x3\xBA\x5\xBA\x8BC\n\xBA\x3\xBB\x3\xBB\x3\xBB\x3\xBB\x3\xBB\x3\xBB\x3"+
		"\xBB\x3\xBB\x3\xBB\x3\xBB\x3\xBB\x3\xBB\x3\xBB\x3\xBB\x3\xBB\x3\xBB\x3"+
		"\xBB\x3\xBB\x3\xBB\x3\xBB\x3\xBB\x3\xBB\x5\xBB\x8D4\n\xBB\x3\xBC\x3\xBC"+
		"\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC"+
		"\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC"+
		"\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC"+
		"\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x3\xBC\x5\xBC\x8FC\n\xBC\x3\xBD\x3"+
		"\xBD\x3\xBD\x3\xBD\x3\xBD\x3\xBD\x3\xBD\x3\xBD\x3\xBD\x3\xBD\x3\xBD\x3"+
		"\xBD\x3\xBD\x3\xBD\x3\xBD\x3\xBD\x3\xBD\x3\xBD\x3\xBD\x3\xBD\x3\xBD\x3"+
		"\xBD\x5\xBD\x914\n\xBD\x3\xBE\x3\xBE\x3\xBE\x3\xBE\x3\xBE\x3\xBE\x3\xBE"+
		"\x3\xBE\x3\xBE\x3\xBE\x3\xBE\x3\xBE\x3\xBE\x3\xBE\x3\xBE\x3\xBE\x3\xBE"+
		"\x3\xBE\x3\xBE\x3\xBE\x3\xBE\x3\xBE\x5\xBE\x92C\n\xBE\x3\xBF\x3\xBF\x3"+
		"\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3"+
		"\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3"+
		"\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3\xBF\x3"+
		"\xBF\x3\xBF\x5\xBF\x950\n\xBF\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0"+
		"\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0"+
		"\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x3\xC0"+
		"\x3\xC0\x3\xC0\x3\xC0\x3\xC0\x5\xC0\x970\n\xC0\x3\xC1\x3\xC1\x3\xC1\x3"+
		"\xC1\x3\xC1\x3\xC1\x3\xC1\x3\xC1\x3\xC1\x3\xC1\x3\xC1\x3\xC1\x3\xC1\x3"+
		"\xC1\x3\xC1\x3\xC1\x3\xC1\x3\xC1\x3\xC1\x3\xC1\x3\xC1\x3\xC1\x5\xC1\x988"+
		"\n\xC1\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2"+
		"\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2"+
		"\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2"+
		"\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2"+
		"\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2"+
		"\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2"+
		"\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2"+
		"\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2"+
		"\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2"+
		"\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2"+
		"\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2"+
		"\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x3\xC2\x5\xC2\x9FC\n\xC2\x3\xC3\x3\xC3\x3"+
		"\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3"+
		"\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3"+
		"\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3"+
		"\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x3\xC3\x5"+
		"\xC3\xA28\n\xC3\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4"+
		"\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4"+
		"\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4\x3\xC4"+
		"\x3\xC4\x3\xC4\x5\xC4\xA48\n\xC4\x3\xC5\x3\xC5\x3\xC5\x3\xC5\x3\xC5\x3"+
		"\xC5\x3\xC5\x3\xC5\x3\xC5\x3\xC5\x3\xC5\x3\xC5\x3\xC5\x3\xC5\x3\xC5\x3"+
		"\xC5\x3\xC5\x3\xC5\x3\xC5\x3\xC5\x3\xC5\x3\xC5\x5\xC5\xA60\n\xC5\x3\xC6"+
		"\x3\xC6\x3\xC6\x3\xC6\x3\xC6\x3\xC6\x3\xC6\x3\xC6\x3\xC6\x3\xC6\x3\xC6"+
		"\x3\xC6\x3\xC6\x3\xC6\x3\xC6\x3\xC6\x3\xC6\x3\xC6\x3\xC6\x3\xC6\x5\xC6"+
		"\xA76\n\xC6\x3\xC7\x3\xC7\x3\xC7\x3\xC7\x3\xC7\x3\xC7\x3\xC7\x3\xC7\x3"+
		"\xC7\x3\xC7\x5\xC7\xA82\n\xC7\x3\xC8\x3\xC8\x3\xC8\x3\xC8\x3\xC8\x3\xC8"+
		"\x3\xC8\x3\xC8\x3\xC8\x3\xC8\x3\xC8\x3\xC8\x3\xC8\x3\xC8\x3\xC8\x3\xC8"+
		"\x3\xC8\x3\xC8\x3\xC8\x3\xC8\x5\xC8\xA98\n\xC8\x3\xC9\x3\xC9\x3\xC9\x3"+
		"\xC9\x3\xC9\x3\xC9\x3\xC9\x3\xC9\x3\xC9\x3\xC9\x5\xC9\xAA4\n\xC9\x3\xCA"+
		"\x3\xCA\x3\xCA\x3\xCA\x3\xCA\x3\xCA\x3\xCA\x3\xCA\x3\xCA\x3\xCA\x3\xCA"+
		"\x3\xCA\x3\xCA\x3\xCA\x3\xCA\x3\xCA\x3\xCA\x3\xCA\x3\xCA\x3\xCA\x5\xCA"+
		"\xABA\n\xCA\x3\xCB\x3\xCB\x3\xCB\x3\xCB\x3\xCB\x3\xCB\x3\xCB\x3\xCB\x3"+
		"\xCB\x3\xCB\x3\xCB\x3\xCB\x3\xCB\x3\xCB\x5\xCB\xACA\n\xCB\x3\xCC\x3\xCC"+
		"\x3\xCC\x3\xCC\x3\xCC\x3\xCC\x3\xCC\x3\xCC\x3\xCC\x3\xCC\x3\xCC\x3\xCC"+
		"\x5\xCC\xAD8\n\xCC\x3\xCD\x3\xCD\x3\xCD\x3\xCD\x3\xCD\x3\xCD\x3\xCD\x3"+
		"\xCD\x3\xCD\x3\xCD\x3\xCD\x3\xCD\x5\xCD\xAE6\n\xCD\x3\xCE\x3\xCE\x3\xCE"+
		"\x3\xCE\x3\xCE\x3\xCE\x3\xCE\x3\xCE\x3\xCE\x3\xCE\x3\xCE\x3\xCE\x3\xCE"+
		"\x3\xCE\x3\xCE\x3\xCE\x3\xCE\x3\xCE\x3\xCE\x3\xCE\x5\xCE\xAFC\n\xCE\x3"+
		"\xCF\x3\xCF\x3\xCF\x3\xCF\x3\xCF\x3\xCF\x3\xCF\x3\xCF\x3\xCF\x3\xCF\x5"+
		"\xCF\xB08\n\xCF\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0"+
		"\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0"+
		"\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x3\xD0\x5\xD0\xB24\n"+
		"\xD0\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3"+
		"\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3"+
		"\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3\xD1\x3"+
		"\xD1\x5\xD1\xB44\n\xD1\x3\xD2\x3\xD2\x3\xD2\x3\xD2\x3\xD2\x3\xD2\x3\xD2"+
		"\x3\xD2\x3\xD2\x3\xD2\x5\xD2\xB50\n\xD2\x3\xD3\x3\xD3\x3\xD3\x3\xD3\x3"+
		"\xD3\x3\xD3\x3\xD3\x3\xD3\x3\xD3\x3\xD3\x5\xD3\xB5C\n\xD3\x3\xD4\x3\xD4"+
		"\x3\xD4\x3\xD4\x3\xD4\x3\xD4\x3\xD4\x3\xD4\x3\xD4\x3\xD4\x3\xD4\x3\xD4"+
		"\x5\xD4\xB6A\n\xD4\x3\xD5\x3\xD5\x3\xD5\x3\xD5\x3\xD5\x3\xD5\x3\xD5\x3"+
		"\xD5\x3\xD5\x3\xD5\x3\xD5\x3\xD5\x3\xD5\x3\xD5\x5\xD5\xB7A\n\xD5\x3\xD6"+
		"\x3\xD6\x3\xD6\x3\xD6\x3\xD6\x3\xD6\x3\xD6\x3\xD6\x3\xD6\x3\xD6\x5\xD6"+
		"\xB86\n\xD6\x3\xD7\x3\xD7\x3\xD7\x3\xD7\x3\xD7\x3\xD7\x3\xD7\x3\xD7\x3"+
		"\xD7\x3\xD7\x3\xD7\x3\xD7\x3\xD7\x3\xD7\x3\xD7\x3\xD7\x3\xD7\x3\xD7\x5"+
		"\xD7\xB9A\n\xD7\x3\xD8\x3\xD8\x3\xD8\x3\xD8\x3\xD8\x3\xD8\x3\xD8\x3\xD8"+
		"\x3\xD8\x3\xD8\x5\xD8\xBA6\n\xD8\x3\xD9\x3\xD9\x3\xD9\x3\xD9\x3\xD9\x3"+
		"\xD9\x3\xD9\x3\xD9\x5\xD9\xBB0\n\xD9\x3\xDA\x3\xDA\x3\xDA\x3\xDA\x3\xDA"+
		"\x3\xDA\x3\xDA\x3\xDA\x3\xDA\x3\xDA\x3\xDA\x3\xDA\x5\xDA\xBBE\n\xDA\x3"+
		"\xDB\x3\xDB\x3\xDB\x3\xDB\x3\xDB\x3\xDB\x3\xDB\x3\xDB\x3\xDB\x3\xDB\x3"+
		"\xDB\x3\xDB\x3\xDB\x3\xDB\x3\xDB\x3\xDB\x3\xDB\x3\xDB\x5\xDB\xBD2\n\xDB"+
		"\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC"+
		"\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC"+
		"\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC"+
		"\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC"+
		"\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x3\xDC\x5\xDC\xC04\n"+
		"\xDC\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x3"+
		"\xDD\x3\xDD\x3\xDD\x3\xDD\x3\xDD\x5\xDD\xC96\n\xDD\x3\xDE\x3\xDE\x3\xDE"+
		"\x3\xDE\x3\xDE\x3\xDE\x3\xDE\x3\xDE\x3\xDE\x3\xDE\x3\xDE\x3\xDE\x3\xDE"+
		"\x3\xDE\x3\xDE\x3\xDE\x3\xDE\x3\xDE\x3\xDE\x3\xDE\x3\xDE\x3\xDE\x3\xDE"+
		"\x3\xDE\x3\xDE\x3\xDE\x5\xDE\xCB2\n\xDE\x3\xDF\x3\xDF\x3\xDF\x3\xDF\x3"+
		"\xDF\x3\xDF\x3\xDF\x3\xDF\x3\xDF\x3\xDF\x5\xDF\xCBE\n\xDF\x3\xE0\x3\xE0"+
		"\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x3\xE0"+
		"\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x3\xE0"+
		"\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x3\xE0\x5\xE0\xCDB\n\xE0\x3\xE1\x3\xE1\x3"+
		"\xE1\x3\xE1\x3\xE1\x3\xE1\x3\xE1\x3\xE1\x3\xE1\x3\xE1\x3\xE1\x3\xE1\x3"+
		"\xE1\x3\xE1\x3\xE1\x3\xE1\x3\xE1\x3\xE1\x3\xE1\x3\xE1\x5\xE1\xCF1\n\xE1"+
		"\x3\xE2\x3\xE2\x3\xE2\x3\xE2\x3\xE2\x3\xE2\x3\xE2\x3\xE2\x3\xE2\x3\xE2"+
		"\x3\xE2\x3\xE2\x5\xE2\xCFF\n\xE2\x3\xE3\x3\xE3\x3\xE3\x3\xE3\x3\xE3\x3"+
		"\xE3\x3\xE3\x3\xE3\x3\xE3\x3\xE3\x3\xE3\x3\xE3\x3\xE3\x3\xE3\x5\xE3\xD0F"+
		"\n\xE3\x3\xE4\x3\xE4\x3\xE4\x3\xE4\x3\xE4\x3\xE4\x3\xE4\x3\xE4\x5\xE4"+
		"\xD19\n\xE4\x3\xE5\x3\xE5\x3\xE5\x3\xE5\x3\xE5\x3\xE5\x3\xE5\x3\xE5\x5"+
		"\xE5\xD23\n\xE5\x3\xE6\x3\xE6\x3\xE6\x3\xE6\x3\xE6\x3\xE6\x5\xE6\xD2B"+
		"\n\xE6\x3\xE7\x3\xE7\x3\xE7\x3\xE7\x3\xE7\x3\xE7\x3\xE7\x3\xE7\x3\xE7"+
		"\x3\xE7\x3\xE7\x3\xE7\x5\xE7\xD39\n\xE7\x3\xE8\x3\xE8\x3\xE8\x3\xE8\x3"+
		"\xE8\x3\xE8\x3\xE8\x3\xE8\x3\xE8\x3\xE8\x3\xE8\x3\xE8\x3\xE8\x3\xE8\x3"+
		"\xE8\x3\xE8\x3\xE8\x3\xE8\x5\xE8\xD4D\n\xE8\x3\xE9\x3\xE9\x3\xE9\x3\xE9"+
		"\x3\xE9\x3\xE9\x3\xE9\x3\xE9\x3\xE9\x3\xE9\x3\xE9\x3\xE9\x3\xE9\x3\xE9"+
		"\x3\xE9\x3\xE9\x3\xE9\x3\xE9\x3\xE9\x3\xE9\x5\xE9\xD63\n\xE9\x3\xEA\x3"+
		"\xEA\x3\xEA\x3\xEA\x3\xEA\x3\xEA\x3\xEA\x3\xEA\x3\xEA\x3\xEA\x3\xEA\x3"+
		"\xEA\x3\xEA\x3\xEA\x3\xEA\x3\xEA\x3\xEA\x3\xEA\x5\xEA\xD77\n\xEA\x3\xEB"+
		"\x3\xEB\x3\xEB\x3\xEB\x3\xEB\x3\xEB\x3\xEB\x3\xEB\x3\xEB\x3\xEB\x3\xEB"+
		"\x3\xEB\x3\xEB\x3\xEB\x5\xEB\xD87\n\xEB\x3\xEC\x3\xEC\x3\xEC\x3\xEC\x3"+
		"\xEC\x3\xEC\x3\xEC\x3\xEC\x3\xEC\x3\xEC\x3\xEC\x3\xEC\x3\xEC\x3\xEC\x3"+
		"\xEC\x3\xEC\x3\xEC\x3\xEC\x3\xEC\x3\xEC\x5\xEC\xD9D\n\xEC\x3\xED\x3\xED"+
		"\x3\xED\x3\xED\x3\xED\x3\xED\x3\xED\x3\xED\x3\xED\x3\xED\x3\xED\x3\xED"+
		"\x3\xED\x3\xED\x3\xED\x3\xED\x3\xED\x3\xED\x3\xED\x3\xED\x5\xED\xDB3\n"+
		"\xED\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3"+
		"\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3"+
		"\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x3\xEE\x5\xEE\xDCF\n\xEE\x3\xEF"+
		"\x3\xEF\x3\xEF\x3\xEF\x3\xEF\x3\xEF\x3\xEF\x3\xEF\x3\xEF\x3\xEF\x3\xEF"+
		"\x3\xEF\x3\xEF\x3\xEF\x5\xEF\xDDF\n\xEF\x3\xF0\x3\xF0\x3\xF0\x3\xF0\x3"+
		"\xF0\x3\xF0\x3\xF0\x3\xF0\x3\xF0\x3\xF0\x3\xF0\x3\xF0\x3\xF0\x3\xF0\x3"+
		"\xF0\x3\xF0\x3\xF0\x3\xF0\x3\xF0\x3\xF0\x3\xF0\x3\xF0\x3\xF0\x3\xF0\x3"+
		"\xF0\x3\xF0\x5\xF0\xDFB\n\xF0\x3\xF1\x3\xF1\x3\xF1\x3\xF1\x3\xF1\x3\xF1"+
		"\x3\xF1\x3\xF1\x3\xF1\x3\xF1\x3\xF1\x3\xF1\x3\xF1\x3\xF1\x3\xF1\x3\xF1"+
		"\x3\xF1\x3\xF1\x3\xF1\x3\xF1\x3\xF1\x3\xF1\x5\xF1\xE13\n\xF1\x3\xF2\x3"+
		"\xF2\x3\xF2\x3\xF2\x3\xF2\x3\xF2\x3\xF2\x3\xF2\x3\xF2\x3\xF2\x3\xF2\x3"+
		"\xF2\x5\xF2\xE21\n\xF2\x3\xF3\x3\xF3\x3\xF3\x3\xF3\x3\xF3\x3\xF3\x3\xF3"+
		"\x3\xF3\x3\xF3\x3\xF3\x3\xF3\x3\xF3\x5\xF3\xE2F\n\xF3\x3\xF4\x3\xF4\x3"+
		"\xF4\x3\xF4\x3\xF4\x3\xF4\x3\xF4\x3\xF4\x3\xF4\x3\xF4\x3\xF4\x3\xF4\x3"+
		"\xF4\x3\xF4\x5\xF4\xE3F\n\xF4\x3\xF5\x3\xF5\x3\xF5\x3\xF5\x3\xF5\x3\xF5"+
		"\x3\xF5\x3\xF5\x3\xF5\x3\xF5\x3\xF5\x3\xF5\x5\xF5\xE4D\n\xF5\x3\xF6\x3"+
		"\xF6\x3\xF6\x3\xF6\x3\xF6\x3\xF6\x3\xF6\x3\xF6\x3\xF6\x3\xF6\x3\xF6\x3"+
		"\xF6\x5\xF6\xE5B\n\xF6\x3\xF7\x3\xF7\x3\xF7\x3\xF7\x3\xF7\x3\xF7\x3\xF7"+
		"\x3\xF7\x3\xF7\x3\xF7\x3\xF7\x3\xF7\x3\xF7\x3\xF7\x5\xF7\xE6B\n\xF7\x3"+
		"\xF8\x3\xF8\x3\xF8\x3\xF8\x3\xF8\x3\xF8\x3\xF8\x3\xF8\x3\xF8\x3\xF8\x3"+
		"\xF8\x3\xF8\x5\xF8\xE79\n\xF8\x3\xF9\x3\xF9\x3\xF9\x3\xF9\x3\xF9\x3\xF9"+
		"\x3\xF9\x3\xF9\x3\xF9\x3\xF9\x3\xF9\x3\xF9\x5\xF9\xE87\n\xF9\x3\xFA\x3"+
		"\xFA\x3\xFA\x3\xFA\x3\xFA\x3\xFA\x3\xFA\x3\xFA\x3\xFA\x3\xFA\x3\xFA\x3"+
		"\xFA\x3\xFA\x3\xFA\x5\xFA\xE97\n\xFA\x3\xFB\x3\xFB\x3\xFB\x3\xFB\x3\xFB"+
		"\x3\xFB\x3\xFB\x3\xFB\x3\xFB\x3\xFB\x3\xFB\x3\xFB\x5\xFB\xEA5\n\xFB\x3"+
		"\xFC\x3\xFC\x3\xFC\x3\xFC\x3\xFC\x3\xFC\x3\xFC\x3\xFC\x3\xFC\x3\xFC\x3"+
		"\xFC\x3\xFC\x5\xFC\xEB3\n\xFC\x3\xFD\x3\xFD\x3\xFD\x3\xFD\x3\xFD\x3\xFD"+
		"\x3\xFD\x3\xFD\x3\xFD\x3\xFD\x3\xFD\x3\xFD\x3\xFD\x3\xFD\x5\xFD\xEC3\n"+
		"\xFD\x3\xFE\x3\xFE\x3\xFE\x3\xFE\x3\xFE\x3\xFE\x3\xFE\x3\xFE\x3\xFE\x3"+
		"\xFE\x3\xFE\x3\xFE\x5\xFE\xED1\n\xFE\x3\xFF\x3\xFF\x3\xFF\x3\xFF\x3\xFF"+
		"\x3\xFF\x3\xFF\x3\xFF\x3\xFF\x3\xFF\x3\xFF\x3\xFF\x5\xFF\xEDF\n\xFF\x3"+
		"\x100\x3\x100\x3\x100\x3\x100\x3\x100\x3\x100\x3\x100\x3\x100\x3\x100"+
		"\x3\x100\x3\x100\x3\x100\x3\x100\x3\x100\x5\x100\xEEF\n\x100\x3\x101\x3"+
		"\x101\x3\x101\x3\x101\x3\x101\x3\x101\x3\x101\x3\x101\x3\x101\x3\x101"+
		"\x3\x101\x3\x101\x3\x101\x3\x101\x5\x101\xEFF\n\x101\x3\x102\x3\x102\x3"+
		"\x102\x3\x102\x3\x102\x3\x102\x3\x102\x3\x102\x3\x102\x3\x102\x3\x102"+
		"\x3\x102\x3\x102\x3\x102\x5\x102\xF0F\n\x102\x3\x103\x3\x103\x3\x103\x3"+
		"\x103\x3\x103\x3\x103\x3\x103\x3\x103\x3\x103\x3\x103\x3\x103\x3\x103"+
		"\x3\x103\x3\x103\x5\x103\xF1F\n\x103\x3\x104\x3\x104\x3\x104\x3\x104\x3"+
		"\x104\x3\x104\x3\x104\x3\x104\x3\x104\x3\x104\x3\x104\x3\x104\x3\x104"+
		"\x3\x104\x5\x104\xF2F\n\x104\x3\x105\x3\x105\x3\x105\x3\x105\x3\x105\x3"+
		"\x105\x3\x105\x3\x105\x3\x105\x3\x105\x3\x105\x3\x105\x3\x105\x3\x105"+
		"\x5\x105\xF3F\n\x105\x3\x106\x3\x106\x3\x106\x3\x106\x3\x106\x3\x106\x3"+
		"\x106\x3\x106\x3\x106\x3\x106\x3\x106\x3\x106\x3\x106\x3\x106\x5\x106"+
		"\xF4F\n\x106\x3\x107\x3\x107\x3\x107\x3\x107\x5\x107\xF55\n\x107\x3\x107"+
		"\x3\x107\x5\x107\xF59\n\x107\x3\x107\x5\x107\xF5C\n\x107\x3\x107\x5\x107"+
		"\xF5F\n\x107\x3\x107\x3\x107\x5\x107\xF63\n\x107\x3\x107\x5\x107\xF66"+
		"\n\x107\x3\x107\x5\x107\xF69\n\x107\x3\x107\x5\x107\xF6C\n\x107\x3\x107"+
		"\x3\x107\x5\x107\xF70\n\x107\x3\x108\x3\x108\x3\x108\x5\x108\xF75\n\x108"+
		"\x3\x108\x5\x108\xF78\n\x108\x3\x108\x3\x108\x5\x108\xF7C\n\x108\x3\x108"+
		"\x5\x108\xF7F\n\x108\x3\x108\x5\x108\xF82\n\x108\x3\x108\x5\x108\xF85"+
		"\n\x108\x3\x108\x5\x108\xF88\n\x108\x3\x108\x5\x108\xF8B\n\x108\x3\x108"+
		"\x5\x108\xF8E\n\x108\x3\x108\x5\x108\xF91\n\x108\x3\x108\x5\x108\xF94"+
		"\n\x108\x3\x108\x5\x108\xF97\n\x108\x3\x108\x5\x108\xF9A\n\x108\x3\x108"+
		"\x5\x108\xF9D\n\x108\x3\x108\x5\x108\xFA0\n\x108\x3\x108\x5\x108\xFA3"+
		"\n\x108\x3\x108\x5\x108\xFA6\n\x108\x3\x108\x5\x108\xFA9\n\x108\x3\x108"+
		"\x3\x108\x5\x108\xFAD\n\x108\x3\x108\x5\x108\xFB0\n\x108\x3\x108\x5\x108"+
		"\xFB3\n\x108\x3\x108\x5\x108\xFB6\n\x108\x3\x108\x5\x108\xFB9\n\x108\x3"+
		"\x108\x5\x108\xFBC\n\x108\x3\x108\x5\x108\xFBF\n\x108\x3\x108\x5\x108"+
		"\xFC2\n\x108\x3\x108\x5\x108\xFC5\n\x108\x3\x108\x5\x108\xFC8\n\x108\x3"+
		"\x108\x5\x108\xFCB\n\x108\x3\x108\x5\x108\xFCE\n\x108\x3\x108\x5\x108"+
		"\xFD1\n\x108\x3\x108\x5\x108\xFD4\n\x108\x3\x108\x5\x108\xFD7\n\x108\x3"+
		"\x108\x3\x108\x5\x108\xFDB\n\x108\x3\x109\x3\x109\x5\x109\xFDF\n\x109"+
		"\x3\x109\x5\x109\xFE2\n\x109\x3\x109\x5\x109\xFE5\n\x109\x3\x109\x5\x109"+
		"\xFE8\n\x109\x3\x109\x5\x109\xFEB\n\x109\x3\x109\x3\x109\x3\x10A\x3\x10A"+
		"\x5\x10A\xFF1\n\x10A\x3\x10A\x5\x10A\xFF4\n\x10A\x3\x10A\x5\x10A\xFF7"+
		"\n\x10A\x3\x10A\x5\x10A\xFFA\n\x10A\x3\x10B\x3\x10B\x3\x10C\a\x10C\xFFF"+
		"\n\x10C\f\x10C\xE\x10C\x1002\v\x10C\x3\x10C\x3\x10C\x6\x10C\x1006\n\x10C"+
		"\r\x10C\xE\x10C\x1007\x3\x10C\x5\x10C\x100B\n\x10C\x3\x10C\x6\x10C\x100E"+
		"\n\x10C\r\x10C\xE\x10C\x100F\x3\x10C\x5\x10C\x1013\n\x10C\x3\x10D\x3\x10D"+
		"\x3\x10D\x5\x10D\x1018\n\x10D\x3\x10D\x3\x10D\x3\x10E\x3\x10E\x3\x10E"+
		"\a\x10E\x101F\n\x10E\f\x10E\xE\x10E\x1022\v\x10E\x3\x10E\x3\x10E\x3\x10F"+
		"\x3\x10F\x5\x10F\x1028\n\x10F\x3\x110\x3\x110\x3\x110\x3\x110\x3\x110"+
		"\x3\x110\x3\x110\x3\x110\x3\x110\x3\x110\x3\x110\x3\x110\x3\x110\x3\x110"+
		"\x3\x110\x3\x110\x3\x110\x3\x110\x5\x110\x103C\n\x110\x3\x111\x3\x111"+
		"\x3\x111\x3\x111\x3\x111\x3\x111\x3\x111\x3\x111\x3\x111\x3\x111\x3\x111"+
		"\x3\x111\x3\x111\x3\x111\x3\x111\x3\x111\x3\x111\x3\x111\x3\x111\x3\x111"+
		"\x3\x111\x3\x111\x5\x111\x1054\n\x111\x3\x112\x3\x112\x3\x112\x3\x112"+
		"\x3\x112\x3\x112\x3\x112\x3\x112\x3\x112\x3\x112\x3\x112\x3\x112\x3\x112"+
		"\x3\x112\x3\x112\x3\x112\x5\x112\x1066\n\x112\x3\x113\x3\x113\a\x113\x106A"+
		"\n\x113\f\x113\xE\x113\x106D\v\x113\x3\x114\x3\x114\x3\x115\x3\x115\x3"+
		"\x116\x3\x116\x3\x116\x3\x116\x3\x116\x3\x116\x3\x116\x3\x116\x3\x116"+
		"\x3\x117\x3\x117\x3\x118\x3\x118\x5\x118\x1080\n\x118\x3\x119\x3\x119"+
		"\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119"+
		"\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119"+
		"\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119\x3\x119"+
		"\x5\x119\x109F\n\x119\x3\x11A\x3\x11A\x3\x11A\x3\x11A\x3\x11A\x3\x11A"+
		"\x3\x11A\x3\x11A\x3\x11A\x3\x11A\x5\x11A\x10AB\n\x11A\x3\x11B\x5\x11B"+
		"\x10AE\n\x11B\x3\x11C\x3\x11C\x3\x11D\x3\x11D\x5\x11D\x10B4\n\x11D\x3"+
		"\x11E\x3\x11E\x5\x11E\x10B8\n\x11E\x3\x11F\x3\x11F\x3\x11F\x5\x11F\x10BD"+
		"\n\x11F\x3\x11F\x6\x11F\x10C0\n\x11F\r\x11F\xE\x11F\x10C1\x3\x24C\x2\x2"+
		"\x120\x3\x2\x3\x5\x2\x4\a\x2\x5\t\x2\x6\v\x2\a\r\x2\b\xF\x2\t\x11\x2\n"+
		"\x13\x2\v\x15\x2\f\x17\x2\r\x19\x2\xE\x1B\x2\xF\x1D\x2\x10\x1F\x2\x11"+
		"!\x2\x12#\x2\x13%\x2\x14\'\x2\x15)\x2\x16+\x2\x17-\x2\x18/\x2\x19\x31"+
		"\x2\x1A\x33\x2\x1B\x35\x2\x1C\x37\x2\x1D\x39\x2\x1E;\x2\x1F=\x2 ?\x2!"+
		"\x41\x2\"\x43\x2#\x45\x2$G\x2%I\x2&K\x2\'M\x2(O\x2)Q\x2*S\x2+U\x2,W\x2"+
		"-Y\x2.[\x2/]\x2\x30_\x2\x31\x61\x2\x32\x63\x2\x33\x65\x2\x34g\x2\x35i"+
		"\x2\x36k\x2\x37m\x2\x38o\x2\x39q\x2:s\x2;u\x2<w\x2=y\x2>{\x2?}\x2@\x7F"+
		"\x2\x41\x81\x2\x42\x83\x2\x43\x85\x2\x44\x87\x2\x45\x89\x2\x46\x8B\x2"+
		"G\x8D\x2H\x8F\x2I\x91\x2J\x93\x2K\x95\x2L\x97\x2M\x99\x2N\x9B\x2O\x9D"+
		"\x2P\x9F\x2Q\xA1\x2R\xA3\x2S\xA5\x2T\xA7\x2U\xA9\x2V\xAB\x2W\xAD\x2X\xAF"+
		"\x2Y\xB1\x2Z\xB3\x2[\xB5\x2\\\xB7\x2]\xB9\x2^\xBB\x2_\xBD\x2`\xBF\x2\x61"+
		"\xC1\x2\x62\xC3\x2\x63\xC5\x2\x64\xC7\x2\x65\xC9\x2\x66\xCB\x2g\xCD\x2"+
		"h\xCF\x2i\xD1\x2j\xD3\x2k\xD5\x2l\xD7\x2m\xD9\x2n\xDB\x2o\xDD\x2p\xDF"+
		"\x2q\xE1\x2r\xE3\x2s\xE5\x2t\xE7\x2u\xE9\x2v\xEB\x2w\xED\x2x\xEF\x2y\xF1"+
		"\x2z\xF3\x2{\xF5\x2|\xF7\x2}\xF9\x2~\xFB\x2\x7F\xFD\x2\x80\xFF\x2\x81"+
		"\x101\x2\x82\x103\x2\x83\x105\x2\x84\x107\x2\x85\x109\x2\x86\x10B\x2\x87"+
		"\x10D\x2\x88\x10F\x2\x89\x111\x2\x8A\x113\x2\x8B\x115\x2\x8C\x117\x2\x8D"+
		"\x119\x2\x8E\x11B\x2\x8F\x11D\x2\x90\x11F\x2\x91\x121\x2\x92\x123\x2\x93"+
		"\x125\x2\x94\x127\x2\x95\x129\x2\x96\x12B\x2\x97\x12D\x2\x98\x12F\x2\x99"+
		"\x131\x2\x9A\x133\x2\x9B\x135\x2\x9C\x137\x2\x9D\x139\x2\x9E\x13B\x2\x9F"+
		"\x13D\x2\xA0\x13F\x2\xA1\x141\x2\xA2\x143\x2\xA3\x145\x2\xA4\x147\x2\xA5"+
		"\x149\x2\xA6\x14B\x2\xA7\x14D\x2\xA8\x14F\x2\xA9\x151\x2\xAA\x153\x2\xAB"+
		"\x155\x2\xAC\x157\x2\xAD\x159\x2\xAE\x15B\x2\xAF\x15D\x2\xB0\x15F\x2\xB1"+
		"\x161\x2\xB2\x163\x2\xB3\x165\x2\xB4\x167\x2\xB5\x169\x2\xB6\x16B\x2\xB7"+
		"\x16D\x2\xB8\x16F\x2\xB9\x171\x2\xBA\x173\x2\xBB\x175\x2\xBC\x177\x2\xBD"+
		"\x179\x2\xBE\x17B\x2\xBF\x17D\x2\xC0\x17F\x2\xC1\x181\x2\xC2\x183\x2\xC3"+
		"\x185\x2\xC4\x187\x2\xC5\x189\x2\xC6\x18B\x2\xC7\x18D\x2\xC8\x18F\x2\xC9"+
		"\x191\x2\xCA\x193\x2\xCB\x195\x2\xCC\x197\x2\xCD\x199\x2\xCE\x19B\x2\xCF"+
		"\x19D\x2\xD0\x19F\x2\xD1\x1A1\x2\xD2\x1A3\x2\xD3\x1A5\x2\xD4\x1A7\x2\xD5"+
		"\x1A9\x2\xD6\x1AB\x2\xD7\x1AD\x2\xD8\x1AF\x2\xD9\x1B1\x2\xDA\x1B3\x2\xDB"+
		"\x1B5\x2\xDC\x1B7\x2\xDD\x1B9\x2\xDE\x1BB\x2\xDF\x1BD\x2\xE0\x1BF\x2\xE1"+
		"\x1C1\x2\xE2\x1C3\x2\xE3\x1C5\x2\xE4\x1C7\x2\xE5\x1C9\x2\xE6\x1CB\x2\xE7"+
		"\x1CD\x2\xE8\x1CF\x2\xE9\x1D1\x2\xEA\x1D3\x2\xEB\x1D5\x2\xEC\x1D7\x2\xED"+
		"\x1D9\x2\xEE\x1DB\x2\xEF\x1DD\x2\xF0\x1DF\x2\xF1\x1E1\x2\xF2\x1E3\x2\xF3"+
		"\x1E5\x2\xF4\x1E7\x2\xF5\x1E9\x2\xF6\x1EB\x2\xF7\x1ED\x2\xF8\x1EF\x2\xF9"+
		"\x1F1\x2\xFA\x1F3\x2\xFB\x1F5\x2\xFC\x1F7\x2\xFD\x1F9\x2\xFE\x1FB\x2\xFF"+
		"\x1FD\x2\x100\x1FF\x2\x101\x201\x2\x102\x203\x2\x103\x205\x2\x104\x207"+
		"\x2\x105\x209\x2\x106\x20B\x2\x107\x20D\x2\x108\x20F\x2\x109\x211\x2\x10A"+
		"\x213\x2\x10B\x215\x2\x10C\x217\x2\x10D\x219\x2\x10E\x21B\x2\x10F\x21D"+
		"\x2\x110\x21F\x2\x111\x221\x2\x112\x223\x2\x113\x225\x2\x114\x227\x2\x115"+
		"\x229\x2\x116\x22B\x2\x117\x22D\x2\x118\x22F\x2\x2\x231\x2\x2\x233\x2"+
		"\x2\x235\x2\x2\x237\x2\x2\x239\x2\x2\x23B\x2\x2\x23D\x2\x2\x3\x2\x17\x4"+
		"\x2\v\v\"\"\x4\x2\f\f\xF\xF\x4\x2\x43\x43\x63\x63\x4\x2\x44\x44\x64\x64"+
		"\x4\x2\x45\x45\x65\x65\x4\x2\x46\x46\x66\x66\x4\x2GGgg\x4\x2JJjj\x4\x2"+
		"NNnn\x4\x2KKkk\x4\x2TTtt\x4\x2\\\\||\x4\x2RRrr\x4\x2OOoo\x6\x2QQSSqqs"+
		"s\x3\x2\x32;\b\x2\f\f\xF\xF$$^^\x87\x87\x202A\x202B\x5\x2\x30\x30\x42"+
		"\\\x61|\t\x2##%%\x30\x30\x32;\x41\\\x61\x61\x63|\x5\x2\x32;\x43H\x63h"+
		"\x3\x2\x32\x39\x128B\x2\x3\x3\x2\x2\x2\x2\x5\x3\x2\x2\x2\x2\a\x3\x2\x2"+
		"\x2\x2\t\x3\x2\x2\x2\x2\v\x3\x2\x2\x2\x2\r\x3\x2\x2\x2\x2\xF\x3\x2\x2"+
		"\x2\x2\x11\x3\x2\x2\x2\x2\x13\x3\x2\x2\x2\x2\x15\x3\x2\x2\x2\x2\x17\x3"+
		"\x2\x2\x2\x2\x19\x3\x2\x2\x2\x2\x1B\x3\x2\x2\x2\x2\x1D\x3\x2\x2\x2\x2"+
		"\x1F\x3\x2\x2\x2\x2!\x3\x2\x2\x2\x2#\x3\x2\x2\x2\x2%\x3\x2\x2\x2\x2\'"+
		"\x3\x2\x2\x2\x2)\x3\x2\x2\x2\x2+\x3\x2\x2\x2\x2-\x3\x2\x2\x2\x2/\x3\x2"+
		"\x2\x2\x2\x31\x3\x2\x2\x2\x2\x33\x3\x2\x2\x2\x2\x35\x3\x2\x2\x2\x2\x37"+
		"\x3\x2\x2\x2\x2\x39\x3\x2\x2\x2\x2;\x3\x2\x2\x2\x2=\x3\x2\x2\x2\x2?\x3"+
		"\x2\x2\x2\x2\x41\x3\x2\x2\x2\x2\x43\x3\x2\x2\x2\x2\x45\x3\x2\x2\x2\x2"+
		"G\x3\x2\x2\x2\x2I\x3\x2\x2\x2\x2K\x3\x2\x2\x2\x2M\x3\x2\x2\x2\x2O\x3\x2"+
		"\x2\x2\x2Q\x3\x2\x2\x2\x2S\x3\x2\x2\x2\x2U\x3\x2\x2\x2\x2W\x3\x2\x2\x2"+
		"\x2Y\x3\x2\x2\x2\x2[\x3\x2\x2\x2\x2]\x3\x2\x2\x2\x2_\x3\x2\x2\x2\x2\x61"+
		"\x3\x2\x2\x2\x2\x63\x3\x2\x2\x2\x2\x65\x3\x2\x2\x2\x2g\x3\x2\x2\x2\x2"+
		"i\x3\x2\x2\x2\x2k\x3\x2\x2\x2\x2m\x3\x2\x2\x2\x2o\x3\x2\x2\x2\x2q\x3\x2"+
		"\x2\x2\x2s\x3\x2\x2\x2\x2u\x3\x2\x2\x2\x2w\x3\x2\x2\x2\x2y\x3\x2\x2\x2"+
		"\x2{\x3\x2\x2\x2\x2}\x3\x2\x2\x2\x2\x7F\x3\x2\x2\x2\x2\x81\x3\x2\x2\x2"+
		"\x2\x83\x3\x2\x2\x2\x2\x85\x3\x2\x2\x2\x2\x87\x3\x2\x2\x2\x2\x89\x3\x2"+
		"\x2\x2\x2\x8B\x3\x2\x2\x2\x2\x8D\x3\x2\x2\x2\x2\x8F\x3\x2\x2\x2\x2\x91"+
		"\x3\x2\x2\x2\x2\x93\x3\x2\x2\x2\x2\x95\x3\x2\x2\x2\x2\x97\x3\x2\x2\x2"+
		"\x2\x99\x3\x2\x2\x2\x2\x9B\x3\x2\x2\x2\x2\x9D\x3\x2\x2\x2\x2\x9F\x3\x2"+
		"\x2\x2\x2\xA1\x3\x2\x2\x2\x2\xA3\x3\x2\x2\x2\x2\xA5\x3\x2\x2\x2\x2\xA7"+
		"\x3\x2\x2\x2\x2\xA9\x3\x2\x2\x2\x2\xAB\x3\x2\x2\x2\x2\xAD\x3\x2\x2\x2"+
		"\x2\xAF\x3\x2\x2\x2\x2\xB1\x3\x2\x2\x2\x2\xB3\x3\x2\x2\x2\x2\xB5\x3\x2"+
		"\x2\x2\x2\xB7\x3\x2\x2\x2\x2\xB9\x3\x2\x2\x2\x2\xBB\x3\x2\x2\x2\x2\xBD"+
		"\x3\x2\x2\x2\x2\xBF\x3\x2\x2\x2\x2\xC1\x3\x2\x2\x2\x2\xC3\x3\x2\x2\x2"+
		"\x2\xC5\x3\x2\x2\x2\x2\xC7\x3\x2\x2\x2\x2\xC9\x3\x2\x2\x2\x2\xCB\x3\x2"+
		"\x2\x2\x2\xCD\x3\x2\x2\x2\x2\xCF\x3\x2\x2\x2\x2\xD1\x3\x2\x2\x2\x2\xD3"+
		"\x3\x2\x2\x2\x2\xD5\x3\x2\x2\x2\x2\xD7\x3\x2\x2\x2\x2\xD9\x3\x2\x2\x2"+
		"\x2\xDB\x3\x2\x2\x2\x2\xDD\x3\x2\x2\x2\x2\xDF\x3\x2\x2\x2\x2\xE1\x3\x2"+
		"\x2\x2\x2\xE3\x3\x2\x2\x2\x2\xE5\x3\x2\x2\x2\x2\xE7\x3\x2\x2\x2\x2\xE9"+
		"\x3\x2\x2\x2\x2\xEB\x3\x2\x2\x2\x2\xED\x3\x2\x2\x2\x2\xEF\x3\x2\x2\x2"+
		"\x2\xF1\x3\x2\x2\x2\x2\xF3\x3\x2\x2\x2\x2\xF5\x3\x2\x2\x2\x2\xF7\x3\x2"+
		"\x2\x2\x2\xF9\x3\x2\x2\x2\x2\xFB\x3\x2\x2\x2\x2\xFD\x3\x2\x2\x2\x2\xFF"+
		"\x3\x2\x2\x2\x2\x101\x3\x2\x2\x2\x2\x103\x3\x2\x2\x2\x2\x105\x3\x2\x2"+
		"\x2\x2\x107\x3\x2\x2\x2\x2\x109\x3\x2\x2\x2\x2\x10B\x3\x2\x2\x2\x2\x10D"+
		"\x3\x2\x2\x2\x2\x10F\x3\x2\x2\x2\x2\x111\x3\x2\x2\x2\x2\x113\x3\x2\x2"+
		"\x2\x2\x115\x3\x2\x2\x2\x2\x117\x3\x2\x2\x2\x2\x119\x3\x2\x2\x2\x2\x11B"+
		"\x3\x2\x2\x2\x2\x11D\x3\x2\x2\x2\x2\x11F\x3\x2\x2\x2\x2\x121\x3\x2\x2"+
		"\x2\x2\x123\x3\x2\x2\x2\x2\x125\x3\x2\x2\x2\x2\x127\x3\x2\x2\x2\x2\x129"+
		"\x3\x2\x2\x2\x2\x12B\x3\x2\x2\x2\x2\x12D\x3\x2\x2\x2\x2\x12F\x3\x2\x2"+
		"\x2\x2\x131\x3\x2\x2\x2\x2\x133\x3\x2\x2\x2\x2\x135\x3\x2\x2\x2\x2\x137"+
		"\x3\x2\x2\x2\x2\x139\x3\x2\x2\x2\x2\x13B\x3\x2\x2\x2\x2\x13D\x3\x2\x2"+
		"\x2\x2\x13F\x3\x2\x2\x2\x2\x141\x3\x2\x2\x2\x2\x143\x3\x2\x2\x2\x2\x145"+
		"\x3\x2\x2\x2\x2\x147\x3\x2\x2\x2\x2\x149\x3\x2\x2\x2\x2\x14B\x3\x2\x2"+
		"\x2\x2\x14D\x3\x2\x2\x2\x2\x14F\x3\x2\x2\x2\x2\x151\x3\x2\x2\x2\x2\x153"+
		"\x3\x2\x2\x2\x2\x155\x3\x2\x2\x2\x2\x157\x3\x2\x2\x2\x2\x159\x3\x2\x2"+
		"\x2\x2\x15B\x3\x2\x2\x2\x2\x15D\x3\x2\x2\x2\x2\x15F\x3\x2\x2\x2\x2\x161"+
		"\x3\x2\x2\x2\x2\x163\x3\x2\x2\x2\x2\x165\x3\x2\x2\x2\x2\x167\x3\x2\x2"+
		"\x2\x2\x169\x3\x2\x2\x2\x2\x16B\x3\x2\x2\x2\x2\x16D\x3\x2\x2\x2\x2\x16F"+
		"\x3\x2\x2\x2\x2\x171\x3\x2\x2\x2\x2\x173\x3\x2\x2\x2\x2\x175\x3\x2\x2"+
		"\x2\x2\x177\x3\x2\x2\x2\x2\x179\x3\x2\x2\x2\x2\x17B\x3\x2\x2\x2\x2\x17D"+
		"\x3\x2\x2\x2\x2\x17F\x3\x2\x2\x2\x2\x181\x3\x2\x2\x2\x2\x183\x3\x2\x2"+
		"\x2\x2\x185\x3\x2\x2\x2\x2\x187\x3\x2\x2\x2\x2\x189\x3\x2\x2\x2\x2\x18B"+
		"\x3\x2\x2\x2\x2\x18D\x3\x2\x2\x2\x2\x18F\x3\x2\x2\x2\x2\x191\x3\x2\x2"+
		"\x2\x2\x193\x3\x2\x2\x2\x2\x195\x3\x2\x2\x2\x2\x197\x3\x2\x2\x2\x2\x199"+
		"\x3\x2\x2\x2\x2\x19B\x3\x2\x2\x2\x2\x19D\x3\x2\x2\x2\x2\x19F\x3\x2\x2"+
		"\x2\x2\x1A1\x3\x2\x2\x2\x2\x1A3\x3\x2\x2\x2\x2\x1A5\x3\x2\x2\x2\x2\x1A7"+
		"\x3\x2\x2\x2\x2\x1A9\x3\x2\x2\x2\x2\x1AB\x3\x2\x2\x2\x2\x1AD\x3\x2\x2"+
		"\x2\x2\x1AF\x3\x2\x2\x2\x2\x1B1\x3\x2\x2\x2\x2\x1B3\x3\x2\x2\x2\x2\x1B5"+
		"\x3\x2\x2\x2\x2\x1B7\x3\x2\x2\x2\x2\x1B9\x3\x2\x2\x2\x2\x1BB\x3\x2\x2"+
		"\x2\x2\x1BD\x3\x2\x2\x2\x2\x1BF\x3\x2\x2\x2\x2\x1C1\x3\x2\x2\x2\x2\x1C3"+
		"\x3\x2\x2\x2\x2\x1C5\x3\x2\x2\x2\x2\x1C7\x3\x2\x2\x2\x2\x1C9\x3\x2\x2"+
		"\x2\x2\x1CB\x3\x2\x2\x2\x2\x1CD\x3\x2\x2\x2\x2\x1CF\x3\x2\x2\x2\x2\x1D1"+
		"\x3\x2\x2\x2\x2\x1D3\x3\x2\x2\x2\x2\x1D5\x3\x2\x2\x2\x2\x1D7\x3\x2\x2"+
		"\x2\x2\x1D9\x3\x2\x2\x2\x2\x1DB\x3\x2\x2\x2\x2\x1DD\x3\x2\x2\x2\x2\x1DF"+
		"\x3\x2\x2\x2\x2\x1E1\x3\x2\x2\x2\x2\x1E3\x3\x2\x2\x2\x2\x1E5\x3\x2\x2"+
		"\x2\x2\x1E7\x3\x2\x2\x2\x2\x1E9\x3\x2\x2\x2\x2\x1EB\x3\x2\x2\x2\x2\x1ED"+
		"\x3\x2\x2\x2\x2\x1EF\x3\x2\x2\x2\x2\x1F1\x3\x2\x2\x2\x2\x1F3\x3\x2\x2"+
		"\x2\x2\x1F5\x3\x2\x2\x2\x2\x1F7\x3\x2\x2\x2\x2\x1F9\x3\x2\x2\x2\x2\x1FB"+
		"\x3\x2\x2\x2\x2\x1FD\x3\x2\x2\x2\x2\x1FF\x3\x2\x2\x2\x2\x201\x3\x2\x2"+
		"\x2\x2\x203\x3\x2\x2\x2\x2\x205\x3\x2\x2\x2\x2\x207\x3\x2\x2\x2\x2\x209"+
		"\x3\x2\x2\x2\x2\x20B\x3\x2\x2\x2\x2\x20D\x3\x2\x2\x2\x2\x20F\x3\x2\x2"+
		"\x2\x2\x211\x3\x2\x2\x2\x2\x213\x3\x2\x2\x2\x2\x215\x3\x2\x2\x2\x2\x217"+
		"\x3\x2\x2\x2\x2\x219\x3\x2\x2\x2\x2\x21B\x3\x2\x2\x2\x2\x21D\x3\x2\x2"+
		"\x2\x2\x21F\x3\x2\x2\x2\x2\x221\x3\x2\x2\x2\x2\x223\x3\x2\x2\x2\x2\x225"+
		"\x3\x2\x2\x2\x2\x227\x3\x2\x2\x2\x2\x229\x3\x2\x2\x2\x2\x22B\x3\x2\x2"+
		"\x2\x2\x22D\x3\x2\x2\x2\x3\x240\x3\x2\x2\x2\x5\x246\x3\x2\x2\x2\a\x256"+
		"\x3\x2\x2\x2\t\x263\x3\x2\x2\x2\v\x267\x3\x2\x2\x2\r\x269\x3\x2\x2\x2"+
		"\xF\x26C\x3\x2\x2\x2\x11\x26E\x3\x2\x2\x2\x13\x271\x3\x2\x2\x2\x15\x273"+
		"\x3\x2\x2\x2\x17\x275\x3\x2\x2\x2\x19\x277\x3\x2\x2\x2\x1B\x279\x3\x2"+
		"\x2\x2\x1D\x27B\x3\x2\x2\x2\x1F\x27D\x3\x2\x2\x2!\x27F\x3\x2\x2\x2#\x281"+
		"\x3\x2\x2\x2%\x283\x3\x2\x2\x2\'\x285\x3\x2\x2\x2)\x287\x3\x2\x2\x2+\x289"+
		"\x3\x2\x2\x2-\x28C\x3\x2\x2\x2/\x290\x3\x2\x2\x2\x31\x293\x3\x2\x2\x2"+
		"\x33\x297\x3\x2\x2\x2\x35\x299\x3\x2\x2\x2\x37\x29C\x3\x2\x2\x2\x39\x29E"+
		"\x3\x2\x2\x2;\x2A1\x3\x2\x2\x2=\x2A4\x3\x2\x2\x2?\x2A7\x3\x2\x2\x2\x41"+
		"\x2A9\x3\x2\x2\x2\x43\x2AB\x3\x2\x2\x2\x45\x2AD\x3\x2\x2\x2G\x2B0\x3\x2"+
		"\x2\x2I\x2B3\x3\x2\x2\x2K\x2B5\x3\x2\x2\x2M\x2B8\x3\x2\x2\x2O\x2BB\x3"+
		"\x2\x2\x2Q\x2BD\x3\x2\x2\x2S\x2BF\x3\x2\x2\x2U\x2C2\x3\x2\x2\x2W\x2C4"+
		"\x3\x2\x2\x2Y\x2C6\x3\x2\x2\x2[\x2C8\x3\x2\x2\x2]\x2CA\x3\x2\x2\x2_\x2CC"+
		"\x3\x2\x2\x2\x61\x2CE\x3\x2\x2\x2\x63\x2D0\x3\x2\x2\x2\x65\x2D2\x3\x2"+
		"\x2\x2g\x2E1\x3\x2\x2\x2i\x2F0\x3\x2\x2\x2k\x2FF\x3\x2\x2\x2m\x30E\x3"+
		"\x2\x2\x2o\x314\x3\x2\x2\x2q\x31A\x3\x2\x2\x2s\x320\x3\x2\x2\x2u\x326"+
		"\x3\x2\x2\x2w\x32C\x3\x2\x2\x2y\x332\x3\x2\x2\x2{\x338\x3\x2\x2\x2}\x340"+
		"\x3\x2\x2\x2\x7F\x342\x3\x2\x2\x2\x81\x348\x3\x2\x2\x2\x83\x34E\x3\x2"+
		"\x2\x2\x85\x354\x3\x2\x2\x2\x87\x35A\x3\x2\x2\x2\x89\x35C\x3\x2\x2\x2"+
		"\x8B\x35E\x3\x2\x2\x2\x8D\x366\x3\x2\x2\x2\x8F\x370\x3\x2\x2\x2\x91\x37A"+
		"\x3\x2\x2\x2\x93\x382\x3\x2\x2\x2\x95\x38A\x3\x2\x2\x2\x97\x392\x3\x2"+
		"\x2\x2\x99\x39A\x3\x2\x2\x2\x9B\x3A2\x3\x2\x2\x2\x9D\x3AA\x3\x2\x2\x2"+
		"\x9F\x3B4\x3\x2\x2\x2\xA1\x3BC\x3\x2\x2\x2\xA3\x3C4\x3\x2\x2\x2\xA5\x3CA"+
		"\x3\x2\x2\x2\xA7\x3D0\x3\x2\x2\x2\xA9\x3D8\x3\x2\x2\x2\xAB\x3E2\x3\x2"+
		"\x2\x2\xAD\x3EC\x3\x2\x2\x2\xAF\x3F4\x3\x2\x2\x2\xB1\x3FC\x3\x2\x2\x2"+
		"\xB3\x404\x3\x2\x2\x2\xB5\x40C\x3\x2\x2\x2\xB7\x414\x3\x2\x2\x2\xB9\x41E"+
		"\x3\x2\x2\x2\xBB\x426\x3\x2\x2\x2\xBD\x42E\x3\x2\x2\x2\xBF\x436\x3\x2"+
		"\x2\x2\xC1\x440\x3\x2\x2\x2\xC3\x44A\x3\x2\x2\x2\xC5\x454\x3\x2\x2\x2"+
		"\xC7\x45E\x3\x2\x2\x2\xC9\x468\x3\x2\x2\x2\xCB\x472\x3\x2\x2\x2\xCD\x47C"+
		"\x3\x2\x2\x2\xCF\x486\x3\x2\x2\x2\xD1\x490\x3\x2\x2\x2\xD3\x496\x3\x2"+
		"\x2\x2\xD5\x49E\x3\x2\x2\x2\xD7\x4A6\x3\x2\x2\x2\xD9\x4AC\x3\x2\x2\x2"+
		"\xDB\x4B4\x3\x2\x2\x2\xDD\x4BC\x3\x2\x2\x2\xDF\x4C4\x3\x2\x2\x2\xE1\x4CC"+
		"\x3\x2\x2\x2\xE3\x4D4\x3\x2\x2\x2\xE5\x4DC\x3\x2\x2\x2\xE7\x4E2\x3\x2"+
		"\x2\x2\xE9\x4E8\x3\x2\x2\x2\xEB\x4F2\x3\x2\x2\x2\xED\x4F8\x3\x2\x2\x2"+
		"\xEF\x4FE\x3\x2\x2\x2\xF1\x508\x3\x2\x2\x2\xF3\x510\x3\x2\x2\x2\xF5\x51A"+
		"\x3\x2\x2\x2\xF7\x522\x3\x2\x2\x2\xF9\x528\x3\x2\x2\x2\xFB\x530\x3\x2"+
		"\x2\x2\xFD\x536\x3\x2\x2\x2\xFF\x53E\x3\x2\x2\x2\x101\x546\x3\x2\x2\x2"+
		"\x103\x54C\x3\x2\x2\x2\x105\x552\x3\x2\x2\x2\x107\x55A\x3\x2\x2\x2\x109"+
		"\x562\x3\x2\x2\x2\x10B\x56A\x3\x2\x2\x2\x10D\x572\x3\x2\x2\x2\x10F\x57A"+
		"\x3\x2\x2\x2\x111\x582\x3\x2\x2\x2\x113\x58A\x3\x2\x2\x2\x115\x59A\x3"+
		"\x2\x2\x2\x117\x5A2\x3\x2\x2\x2\x119\x5AC\x3\x2\x2\x2\x11B\x5BA\x3\x2"+
		"\x2\x2\x11D\x5C4\x3\x2\x2\x2\x11F\x5D4\x3\x2\x2\x2\x121\x5E2\x3\x2\x2"+
		"\x2\x123\x5EC\x3\x2\x2\x2\x125\x5F8\x3\x2\x2\x2\x127\x602\x3\x2\x2\x2"+
		"\x129\x60E\x3\x2\x2\x2\x12B\x61E\x3\x2\x2\x2\x12D\x62E\x3\x2\x2\x2\x12F"+
		"\x63A\x3\x2\x2\x2\x131\x648\x3\x2\x2\x2\x133\x65C\x3\x2\x2\x2\x135\x65E"+
		"\x3\x2\x2\x2\x137\x665\x3\x2\x2\x2\x139\x66D\x3\x2\x2\x2\x13B\x674\x3"+
		"\x2\x2\x2\x13D\x67A\x3\x2\x2\x2\x13F\x682\x3\x2\x2\x2\x141\x689\x3\x2"+
		"\x2\x2\x143\x692\x3\x2\x2\x2\x145\x696\x3\x2\x2\x2\x147\x69D\x3\x2\x2"+
		"\x2\x149\x6A5\x3\x2\x2\x2\x14B\x6B9\x3\x2\x2\x2\x14D\x6CD\x3\x2\x2\x2"+
		"\x14F\x6E1\x3\x2\x2\x2\x151\x6F1\x3\x2\x2\x2\x153\x705\x3\x2\x2\x2\x155"+
		"\x715\x3\x2\x2\x2\x157\x727\x3\x2\x2\x2\x159\x73B\x3\x2\x2\x2\x15B\x759"+
		"\x3\x2\x2\x2\x15D\x777\x3\x2\x2\x2\x15F\x795\x3\x2\x2\x2\x161\x7B3\x3"+
		"\x2\x2\x2\x163\x7D1\x3\x2\x2\x2\x165\x7F7\x3\x2\x2\x2\x167\x815\x3\x2"+
		"\x2\x2\x169\x83D\x3\x2\x2\x2\x16B\x851\x3\x2\x2\x2\x16D\x86D\x3\x2\x2"+
		"\x2\x16F\x88B\x3\x2\x2\x2\x171\x8A3\x3\x2\x2\x2\x173\x8BB\x3\x2\x2\x2"+
		"\x175\x8D3\x3\x2\x2\x2\x177\x8FB\x3\x2\x2\x2\x179\x913\x3\x2\x2\x2\x17B"+
		"\x92B\x3\x2\x2\x2\x17D\x94F\x3\x2\x2\x2\x17F\x96F\x3\x2\x2\x2\x181\x987"+
		"\x3\x2\x2\x2\x183\x9FB\x3\x2\x2\x2\x185\xA27\x3\x2\x2\x2\x187\xA47\x3"+
		"\x2\x2\x2\x189\xA5F\x3\x2\x2\x2\x18B\xA75\x3\x2\x2\x2\x18D\xA81\x3\x2"+
		"\x2\x2\x18F\xA97\x3\x2\x2\x2\x191\xAA3\x3\x2\x2\x2\x193\xAB9\x3\x2\x2"+
		"\x2\x195\xAC9\x3\x2\x2\x2\x197\xAD7\x3\x2\x2\x2\x199\xAE5\x3\x2\x2\x2"+
		"\x19B\xAFB\x3\x2\x2\x2\x19D\xB07\x3\x2\x2\x2\x19F\xB23\x3\x2\x2\x2\x1A1"+
		"\xB43\x3\x2\x2\x2\x1A3\xB4F\x3\x2\x2\x2\x1A5\xB5B\x3\x2\x2\x2\x1A7\xB69"+
		"\x3\x2\x2\x2\x1A9\xB79\x3\x2\x2\x2\x1AB\xB85\x3\x2\x2\x2\x1AD\xB99\x3"+
		"\x2\x2\x2\x1AF\xBA5\x3\x2\x2\x2\x1B1\xBAF\x3\x2\x2\x2\x1B3\xBBD\x3\x2"+
		"\x2\x2\x1B5\xBD1\x3\x2\x2\x2\x1B7\xC03\x3\x2\x2\x2\x1B9\xC95\x3\x2\x2"+
		"\x2\x1BB\xCB1\x3\x2\x2\x2\x1BD\xCBD\x3\x2\x2\x2\x1BF\xCDA\x3\x2\x2\x2"+
		"\x1C1\xCF0\x3\x2\x2\x2\x1C3\xCFE\x3\x2\x2\x2\x1C5\xD0E\x3\x2\x2\x2\x1C7"+
		"\xD18\x3\x2\x2\x2\x1C9\xD22\x3\x2\x2\x2\x1CB\xD2A\x3\x2\x2\x2\x1CD\xD38"+
		"\x3\x2\x2\x2\x1CF\xD4C\x3\x2\x2\x2\x1D1\xD62\x3\x2\x2\x2\x1D3\xD76\x3"+
		"\x2\x2\x2\x1D5\xD86\x3\x2\x2\x2\x1D7\xD9C\x3\x2\x2\x2\x1D9\xDB2\x3\x2"+
		"\x2\x2\x1DB\xDCE\x3\x2\x2\x2\x1DD\xDDE\x3\x2\x2\x2\x1DF\xDFA\x3\x2\x2"+
		"\x2\x1E1\xE12\x3\x2\x2\x2\x1E3\xE20\x3\x2\x2\x2\x1E5\xE2E\x3\x2\x2\x2"+
		"\x1E7\xE3E\x3\x2\x2\x2\x1E9\xE4C\x3\x2\x2\x2\x1EB\xE5A\x3\x2\x2\x2\x1ED"+
		"\xE6A\x3\x2\x2\x2\x1EF\xE78\x3\x2\x2\x2\x1F1\xE86\x3\x2\x2\x2\x1F3\xE96"+
		"\x3\x2\x2\x2\x1F5\xEA4\x3\x2\x2\x2\x1F7\xEB2\x3\x2\x2\x2\x1F9\xEC2\x3"+
		"\x2\x2\x2\x1FB\xED0\x3\x2\x2\x2\x1FD\xEDE\x3\x2\x2\x2\x1FF\xEEE\x3\x2"+
		"\x2\x2\x201\xEFE\x3\x2\x2\x2\x203\xF0E\x3\x2\x2\x2\x205\xF1E\x3\x2\x2"+
		"\x2\x207\xF2E\x3\x2\x2\x2\x209\xF3E\x3\x2\x2\x2\x20B\xF4E\x3\x2\x2\x2"+
		"\x20D\xF6F\x3\x2\x2\x2\x20F\xFDA\x3\x2\x2\x2\x211\xFDC\x3\x2\x2\x2\x213"+
		"\xFEE\x3\x2\x2\x2\x215\xFFB\x3\x2\x2\x2\x217\x1012\x3\x2\x2\x2\x219\x1014"+
		"\x3\x2\x2\x2\x21B\x101B\x3\x2\x2\x2\x21D\x1027\x3\x2\x2\x2\x21F\x103B"+
		"\x3\x2\x2\x2\x221\x1053\x3\x2\x2\x2\x223\x1065\x3\x2\x2\x2\x225\x1067"+
		"\x3\x2\x2\x2\x227\x106E\x3\x2\x2\x2\x229\x1070\x3\x2\x2\x2\x22B\x1072"+
		"\x3\x2\x2\x2\x22D\x107B\x3\x2\x2\x2\x22F\x107F\x3\x2\x2\x2\x231\x109E"+
		"\x3\x2\x2\x2\x233\x10AA\x3\x2\x2\x2\x235\x10AD\x3\x2\x2\x2\x237\x10AF"+
		"\x3\x2\x2\x2\x239\x10B3\x3\x2\x2\x2\x23B\x10B5\x3\x2\x2\x2\x23D\x10B9"+
		"\x3\x2\x2\x2\x23F\x241\t\x2\x2\x2\x240\x23F\x3\x2\x2\x2\x241\x242\x3\x2"+
		"\x2\x2\x242\x240\x3\x2\x2\x2\x242\x243\x3\x2\x2\x2\x243\x244\x3\x2\x2"+
		"\x2\x244\x245\b\x2\x2\x2\x245\x4\x3\x2\x2\x2\x246\x247\a\x31\x2\x2\x247"+
		"\x248\a,\x2\x2\x248\x24C\x3\x2\x2\x2\x249\x24B\n\x3\x2\x2\x24A\x249\x3"+
		"\x2\x2\x2\x24B\x24E\x3\x2\x2\x2\x24C\x24D\x3\x2\x2\x2\x24C\x24A\x3\x2"+
		"\x2\x2\x24D\x24F\x3\x2\x2\x2\x24E\x24C\x3\x2\x2\x2\x24F\x250\a,\x2\x2"+
		"\x250\x251\a\x31\x2\x2\x251\x252\x3\x2\x2\x2\x252\x253\b\x3\x2\x2\x253"+
		"\x6\x3\x2\x2\x2\x254\x257\x5\xF\b\x2\x255\x257\x5\x11\t\x2\x256\x254\x3"+
		"\x2\x2\x2\x256\x255\x3\x2\x2\x2\x257\x25B\x3\x2\x2\x2\x258\x25A\n\x3\x2"+
		"\x2\x259\x258\x3\x2\x2\x2\x25A\x25D\x3\x2\x2\x2\x25B\x259\x3\x2\x2\x2"+
		"\x25B\x25C\x3\x2\x2\x2\x25C\b\x3\x2\x2\x2\x25D\x25B\x3\x2\x2\x2\x25E\x260"+
		"\a\xF\x2\x2\x25F\x25E\x3\x2\x2\x2\x25F\x260\x3\x2\x2\x2\x260\x261\x3\x2"+
		"\x2\x2\x261\x264\a\f\x2\x2\x262\x264\a\xF\x2\x2\x263\x25F\x3\x2\x2\x2"+
		"\x263\x262\x3\x2\x2\x2\x264\x265\x3\x2\x2\x2\x265\x263\x3\x2\x2\x2\x265"+
		"\x266\x3\x2\x2\x2\x266\n\x3\x2\x2\x2\x267\x268\a<\x2\x2\x268\f\x3\x2\x2"+
		"\x2\x269\x26A\a<\x2\x2\x26A\x26B\a<\x2\x2\x26B\xE\x3\x2\x2\x2\x26C\x26D"+
		"\a=\x2\x2\x26D\x10\x3\x2\x2\x2\x26E\x26F\a\x31\x2\x2\x26F\x270\a\x31\x2"+
		"\x2\x270\x12\x3\x2\x2\x2\x271\x272\a.\x2\x2\x272\x14\x3\x2\x2\x2\x273"+
		"\x274\a?\x2\x2\x274\x16\x3\x2\x2\x2\x275\x276\a*\x2\x2\x276\x18\x3\x2"+
		"\x2\x2\x277\x278\a+\x2\x2\x278\x1A\x3\x2\x2\x2\x279\x27A\a]\x2\x2\x27A"+
		"\x1C\x3\x2\x2\x2\x27B\x27C\a_\x2\x2\x27C\x1E\x3\x2\x2\x2\x27D\x27E\a\x41"+
		"\x2\x2\x27E \x3\x2\x2\x2\x27F\x280\a-\x2\x2\x280\"\x3\x2\x2\x2\x281\x282"+
		"\a/\x2\x2\x282$\x3\x2\x2\x2\x283\x284\a~\x2\x2\x284&\x3\x2\x2\x2\x285"+
		"\x286\a`\x2\x2\x286(\x3\x2\x2\x2\x287\x288\a(\x2\x2\x288*\x3\x2\x2\x2"+
		"\x289\x28A\a?\x2\x2\x28A\x28B\a?\x2\x2\x28B,\x3\x2\x2\x2\x28C\x28D\a?"+
		"\x2\x2\x28D\x28E\a?\x2\x2\x28E\x28F\a?\x2\x2\x28F.\x3\x2\x2\x2\x290\x291"+
		"\a#\x2\x2\x291\x292\a?\x2\x2\x292\x30\x3\x2\x2\x2\x293\x294\a#\x2\x2\x294"+
		"\x295\a?\x2\x2\x295\x296\a?\x2\x2\x296\x32\x3\x2\x2\x2\x297\x298\a>\x2"+
		"\x2\x298\x34\x3\x2\x2\x2\x299\x29A\a>\x2\x2\x29A\x29B\a?\x2\x2\x29B\x36"+
		"\x3\x2\x2\x2\x29C\x29D\a@\x2\x2\x29D\x38\x3\x2\x2\x2\x29E\x29F\a@\x2\x2"+
		"\x29F\x2A0\a?\x2\x2\x2A0:\x3\x2\x2\x2\x2A1\x2A2\a>\x2\x2\x2A2\x2A3\a>"+
		"\x2\x2\x2A3<\x3\x2\x2\x2\x2A4\x2A5\a@\x2\x2\x2A5\x2A6\a@\x2\x2\x2A6>\x3"+
		"\x2\x2\x2\x2A7\x2A8\a,\x2\x2\x2A8@\x3\x2\x2\x2\x2A9\x2AA\a\x31\x2\x2\x2AA"+
		"\x42\x3\x2\x2\x2\x2AB\x2AC\a\'\x2\x2\x2AC\x44\x3\x2\x2\x2\x2AD\x2AE\a"+
		">\x2\x2\x2AE\x2AF\a\x41\x2\x2\x2AF\x46\x3\x2\x2\x2\x2B0\x2B1\a@\x2\x2"+
		"\x2B1\x2B2\a\x41\x2\x2\x2B2H\x3\x2\x2\x2\x2B3\x2B4\a\x80\x2\x2\x2B4J\x3"+
		"\x2\x2\x2\x2B5\x2B6\a}\x2\x2\x2B6\x2B7\a}\x2\x2\x2B7L\x3\x2\x2\x2\x2B8"+
		"\x2B9\a\x7F\x2\x2\x2B9\x2BA\a\x7F\x2\x2\x2BAN\x3\x2\x2\x2\x2BB\x2BC\a"+
		"#\x2\x2\x2BCP\x3\x2\x2\x2\x2BD\x2BE\a\x30\x2\x2\x2BER\x3\x2\x2\x2\x2BF"+
		"\x2C0\a/\x2\x2\x2C0\x2C1\a@\x2\x2\x2C1T\x3\x2\x2\x2\x2C2\x2C3\t\x4\x2"+
		"\x2\x2C3V\x3\x2\x2\x2\x2C4\x2C5\t\x5\x2\x2\x2C5X\x3\x2\x2\x2\x2C6\x2C7"+
		"\t\x6\x2\x2\x2C7Z\x3\x2\x2\x2\x2C8\x2C9\t\a\x2\x2\x2C9\\\x3\x2\x2\x2\x2CA"+
		"\x2CB\t\b\x2\x2\x2CB^\x3\x2\x2\x2\x2CC\x2CD\t\t\x2\x2\x2CD`\x3\x2\x2\x2"+
		"\x2CE\x2CF\t\n\x2\x2\x2CF\x62\x3\x2\x2\x2\x2D0\x2D1\t\v\x2\x2\x2D1\x64"+
		"\x3\x2\x2\x2\x2D2\x2D3\t\f\x2\x2\x2D3\x66\x3\x2\x2\x2\x2D4\x2D5\az\x2"+
		"\x2\x2D5\x2E2\an\x2\x2\x2D6\x2D7\aZ\x2\x2\x2D7\x2E2\aN\x2\x2\x2D8\x2D9"+
		"\ak\x2\x2\x2D9\x2DA\az\x2\x2\x2DA\x2E2\an\x2\x2\x2DB\x2DC\aK\x2\x2\x2DC"+
		"\x2DD\aZ\x2\x2\x2DD\x2E2\aN\x2\x2\x2DE\x2DF\aK\x2\x2\x2DF\x2E0\aZ\x2\x2"+
		"\x2E0\x2E2\an\x2\x2\x2E1\x2D4\x3\x2\x2\x2\x2E1\x2D6\x3\x2\x2\x2\x2E1\x2D8"+
		"\x3\x2\x2\x2\x2E1\x2DB\x3\x2\x2\x2\x2E1\x2DE\x3\x2\x2\x2\x2E2h\x3\x2\x2"+
		"\x2\x2E3\x2E4\az\x2\x2\x2E4\x2F1\aj\x2\x2\x2E5\x2E6\aZ\x2\x2\x2E6\x2F1"+
		"\aJ\x2\x2\x2E7\x2E8\ak\x2\x2\x2E8\x2E9\az\x2\x2\x2E9\x2F1\aj\x2\x2\x2EA"+
		"\x2EB\aK\x2\x2\x2EB\x2EC\aZ\x2\x2\x2EC\x2F1\aJ\x2\x2\x2ED\x2EE\aK\x2\x2"+
		"\x2EE\x2EF\aZ\x2\x2\x2EF\x2F1\aj\x2\x2\x2F0\x2E3\x3\x2\x2\x2\x2F0\x2E5"+
		"\x3\x2\x2\x2\x2F0\x2E7\x3\x2\x2\x2\x2F0\x2EA\x3\x2\x2\x2\x2F0\x2ED\x3"+
		"\x2\x2\x2\x2F1j\x3\x2\x2\x2\x2F2\x2F3\a{\x2\x2\x2F3\x300\an\x2\x2\x2F4"+
		"\x2F5\a[\x2\x2\x2F5\x300\aN\x2\x2\x2F6\x2F7\ak\x2\x2\x2F7\x2F8\a{\x2\x2"+
		"\x2F8\x300\an\x2\x2\x2F9\x2FA\aK\x2\x2\x2FA\x2FB\a[\x2\x2\x2FB\x300\a"+
		"N\x2\x2\x2FC\x2FD\aK\x2\x2\x2FD\x2FE\a[\x2\x2\x2FE\x300\an\x2\x2\x2FF"+
		"\x2F2\x3\x2\x2\x2\x2FF\x2F4\x3\x2\x2\x2\x2FF\x2F6\x3\x2\x2\x2\x2FF\x2F9"+
		"\x3\x2\x2\x2\x2FF\x2FC\x3\x2\x2\x2\x300l\x3\x2\x2\x2\x301\x302\a{\x2\x2"+
		"\x302\x30F\aj\x2\x2\x303\x304\a[\x2\x2\x304\x30F\aJ\x2\x2\x305\x306\a"+
		"k\x2\x2\x306\x307\a{\x2\x2\x307\x30F\aj\x2\x2\x308\x309\aK\x2\x2\x309"+
		"\x30A\a[\x2\x2\x30A\x30F\aJ\x2\x2\x30B\x30C\aK\x2\x2\x30C\x30D\a[\x2\x2"+
		"\x30D\x30F\aj\x2\x2\x30E\x301\x3\x2\x2\x2\x30E\x303\x3\x2\x2\x2\x30E\x305"+
		"\x3\x2\x2\x2\x30E\x308\x3\x2\x2\x2\x30E\x30B\x3\x2\x2\x2\x30Fn\x3\x2\x2"+
		"\x2\x310\x311\a\x64\x2\x2\x311\x315\a\x65\x2\x2\x312\x313\a\x44\x2\x2"+
		"\x313\x315\a\x45\x2\x2\x314\x310\x3\x2\x2\x2\x314\x312\x3\x2\x2\x2\x315"+
		"p\x3\x2\x2\x2\x316\x317\a\x66\x2\x2\x317\x31B\ag\x2\x2\x318\x319\a\x46"+
		"\x2\x2\x319\x31B\aG\x2\x2\x31A\x316\x3\x2\x2\x2\x31A\x318\x3\x2\x2\x2"+
		"\x31Br\x3\x2\x2\x2\x31C\x31D\aj\x2\x2\x31D\x321\an\x2\x2\x31E\x31F\aJ"+
		"\x2\x2\x31F\x321\aN\x2\x2\x320\x31C\x3\x2\x2\x2\x320\x31E\x3\x2\x2\x2"+
		"\x321t\x3\x2\x2\x2\x322\x323\au\x2\x2\x323\x327\ar\x2\x2\x324\x325\aU"+
		"\x2\x2\x325\x327\aR\x2\x2\x326\x322\x3\x2\x2\x2\x326\x324\x3\x2\x2\x2"+
		"\x327v\x3\x2\x2\x2\x328\x329\ak\x2\x2\x329\x32D\az\x2\x2\x32A\x32B\aK"+
		"\x2\x2\x32B\x32D\aZ\x2\x2\x32C\x328\x3\x2\x2\x2\x32C\x32A\x3\x2\x2\x2"+
		"\x32Dx\x3\x2\x2\x2\x32E\x32F\ak\x2\x2\x32F\x333\a{\x2\x2\x330\x331\aK"+
		"\x2\x2\x331\x333\a[\x2\x2\x332\x32E\x3\x2\x2\x2\x332\x330\x3\x2\x2\x2"+
		"\x333z\x3\x2\x2\x2\x334\x335\a\x63\x2\x2\x335\x339\ah\x2\x2\x336\x337"+
		"\a\x43\x2\x2\x337\x339\aH\x2\x2\x338\x334\x3\x2\x2\x2\x338\x336\x3\x2"+
		"\x2\x2\x339|\x3\x2\x2\x2\x33A\x33B\a\x63\x2\x2\x33B\x33C\ah\x2\x2\x33C"+
		"\x341\a)\x2\x2\x33D\x33E\a\x43\x2\x2\x33E\x33F\aH\x2\x2\x33F\x341\a)\x2"+
		"\x2\x340\x33A\x3\x2\x2\x2\x340\x33D\x3\x2\x2\x2\x341~\x3\x2\x2\x2\x342"+
		"\x343\t\r\x2\x2\x343\x80\x3\x2\x2\x2\x344\x345\ap\x2\x2\x345\x349\a|\x2"+
		"\x2\x346\x347\aP\x2\x2\x347\x349\a\\\x2\x2\x348\x344\x3\x2\x2\x2\x348"+
		"\x346\x3\x2\x2\x2\x349\x82\x3\x2\x2\x2\x34A\x34B\ap\x2\x2\x34B\x34F\a"+
		"\x65\x2\x2\x34C\x34D\aP\x2\x2\x34D\x34F\a\x45\x2\x2\x34E\x34A\x3\x2\x2"+
		"\x2\x34E\x34C\x3\x2\x2\x2\x34F\x84\x3\x2\x2\x2\x350\x351\ar\x2\x2\x351"+
		"\x355\aq\x2\x2\x352\x353\aR\x2\x2\x353\x355\aQ\x2\x2\x354\x350\x3\x2\x2"+
		"\x2\x354\x352\x3\x2\x2\x2\x355\x86\x3\x2\x2\x2\x356\x357\ar\x2\x2\x357"+
		"\x35B\ag\x2\x2\x358\x359\aR\x2\x2\x359\x35B\aG\x2\x2\x35A\x356\x3\x2\x2"+
		"\x2\x35A\x358\x3\x2\x2\x2\x35B\x88\x3\x2\x2\x2\x35C\x35D\t\xE\x2\x2\x35D"+
		"\x8A\x3\x2\x2\x2\x35E\x35F\t\xF\x2\x2\x35F\x8C\x3\x2\x2\x2\x360\x361\a"+
		"p\x2\x2\x361\x362\aq\x2\x2\x362\x367\ar\x2\x2\x363\x364\aP\x2\x2\x364"+
		"\x365\aQ\x2\x2\x365\x367\aR\x2\x2\x366\x360\x3\x2\x2\x2\x366\x363\x3\x2"+
		"\x2\x2\x367\x8E\x3\x2\x2\x2\x368\x369\at\x2\x2\x369\x36A\an\x2\x2\x36A"+
		"\x36B\a\x65\x2\x2\x36B\x371\a\x63\x2\x2\x36C\x36D\aT\x2\x2\x36D\x36E\a"+
		"N\x2\x2\x36E\x36F\a\x45\x2\x2\x36F\x371\a\x43\x2\x2\x370\x368\x3\x2\x2"+
		"\x2\x370\x36C\x3\x2\x2\x2\x371\x90\x3\x2\x2\x2\x372\x373\at\x2\x2\x373"+
		"\x374\at\x2\x2\x374\x375\a\x65\x2\x2\x375\x37B\a\x63\x2\x2\x376\x377\a"+
		"T\x2\x2\x377\x378\aT\x2\x2\x378\x379\a\x45\x2\x2\x379\x37B\a\x43\x2\x2"+
		"\x37A\x372\x3\x2\x2\x2\x37A\x376\x3\x2\x2\x2\x37B\x92\x3\x2\x2\x2\x37C"+
		"\x37D\at\x2\x2\x37D\x37E\an\x2\x2\x37E\x383\a\x63\x2\x2\x37F\x380\aT\x2"+
		"\x2\x380\x381\aN\x2\x2\x381\x383\a\x43\x2\x2\x382\x37C\x3\x2\x2\x2\x382"+
		"\x37F\x3\x2\x2\x2\x383\x94\x3\x2\x2\x2\x384\x385\at\x2\x2\x385\x386\a"+
		"t\x2\x2\x386\x38B\a\x63\x2\x2\x387\x388\aT\x2\x2\x388\x389\aT\x2\x2\x389"+
		"\x38B\a\x43\x2\x2\x38A\x384\x3\x2\x2\x2\x38A\x387\x3\x2\x2\x2\x38B\x96"+
		"\x3\x2\x2\x2\x38C\x38D\a\x66\x2\x2\x38D\x38E\a\x63\x2\x2\x38E\x393\a\x63"+
		"\x2\x2\x38F\x390\a\x46\x2\x2\x390\x391\a\x43\x2\x2\x391\x393\a\x43\x2"+
		"\x2\x392\x38C\x3\x2\x2\x2\x392\x38F\x3\x2\x2\x2\x393\x98\x3\x2\x2\x2\x394"+
		"\x395\a\x65\x2\x2\x395\x396\ar\x2\x2\x396\x39B\an\x2\x2\x397\x398\a\x45"+
		"\x2\x2\x398\x399\aR\x2\x2\x399\x39B\aN\x2\x2\x39A\x394\x3\x2\x2\x2\x39A"+
		"\x397\x3\x2\x2\x2\x39B\x9A\x3\x2\x2\x2\x39C\x39D\au\x2\x2\x39D\x39E\a"+
		"\x65\x2\x2\x39E\x3A3\ah\x2\x2\x39F\x3A0\aU\x2\x2\x3A0\x3A1\a\x45\x2\x2"+
		"\x3A1\x3A3\aH\x2\x2\x3A2\x39C\x3\x2\x2\x2\x3A2\x39F\x3\x2\x2\x2\x3A3\x9C"+
		"\x3\x2\x2\x2\x3A4\x3A5\a\x65\x2\x2\x3A5\x3A6\a\x65\x2\x2\x3A6\x3AB\ah"+
		"\x2\x2\x3A7\x3A8\a\x45\x2\x2\x3A8\x3A9\a\x45\x2\x2\x3A9\x3AB\aH\x2\x2"+
		"\x3AA\x3A4\x3\x2\x2\x2\x3AA\x3A7\x3\x2\x2\x2\x3AB\x9E\x3\x2\x2\x2\x3AC"+
		"\x3AD\aj\x2\x2\x3AD\x3AE\a\x63\x2\x2\x3AE\x3AF\an\x2\x2\x3AF\x3B5\av\x2"+
		"\x2\x3B0\x3B1\aJ\x2\x2\x3B1\x3B2\a\x43\x2\x2\x3B2\x3B3\aN\x2\x2\x3B3\x3B5"+
		"\aV\x2\x2\x3B4\x3AC\x3\x2\x2\x2\x3B4\x3B0\x3\x2\x2\x2\x3B5\xA0\x3\x2\x2"+
		"\x2\x3B6\x3B7\at\x2\x2\x3B7\x3B8\ag\x2\x2\x3B8\x3BD\av\x2\x2\x3B9\x3BA"+
		"\aT\x2\x2\x3BA\x3BB\aG\x2\x2\x3BB\x3BD\aV\x2\x2\x3BC\x3B6\x3\x2\x2\x2"+
		"\x3BC\x3B9\x3\x2\x2\x2\x3BD\xA2\x3\x2\x2\x2\x3BE\x3BF\ag\x2\x2\x3BF\x3C0"+
		"\az\x2\x2\x3C0\x3C5\az\x2\x2\x3C1\x3C2\aG\x2\x2\x3C2\x3C3\aZ\x2\x2\x3C3"+
		"\x3C5\aZ\x2\x2\x3C4\x3BE\x3\x2\x2\x2\x3C4\x3C1\x3\x2\x2\x2\x3C5\xA4\x3"+
		"\x2\x2\x2\x3C6\x3C7\a\x66\x2\x2\x3C7\x3CB\ak\x2\x2\x3C8\x3C9\a\x46\x2"+
		"\x2\x3C9\x3CB\aK\x2\x2\x3CA\x3C6\x3\x2\x2\x2\x3CA\x3C8\x3\x2\x2\x2\x3CB"+
		"\xA6\x3\x2\x2\x2\x3CC\x3CD\ag\x2\x2\x3CD\x3D1\ak\x2\x2\x3CE\x3CF\aG\x2"+
		"\x2\x3CF\x3D1\aK\x2\x2\x3D0\x3CC\x3\x2\x2\x2\x3D0\x3CE\x3\x2\x2\x2\x3D1"+
		"\xA8\x3\x2\x2\x2\x3D2\x3D3\ap\x2\x2\x3D3\x3D4\ag\x2\x2\x3D4\x3D9\ai\x2"+
		"\x2\x3D5\x3D6\aP\x2\x2\x3D6\x3D7\aG\x2\x2\x3D7\x3D9\aI\x2\x2\x3D8\x3D2"+
		"\x3\x2\x2\x2\x3D8\x3D5\x3\x2\x2\x2\x3D9\xAA\x3\x2\x2\x2\x3DA\x3DB\at\x2"+
		"\x2\x3DB\x3DC\ag\x2\x2\x3DC\x3DD\av\x2\x2\x3DD\x3E3\ap\x2\x2\x3DE\x3DF"+
		"\aT\x2\x2\x3DF\x3E0\aG\x2\x2\x3E0\x3E1\aV\x2\x2\x3E1\x3E3\aP\x2\x2\x3E2"+
		"\x3DA\x3\x2\x2\x2\x3E2\x3DE\x3\x2\x2\x2\x3E3\xAC\x3\x2\x2\x2\x3E4\x3E5"+
		"\at\x2\x2\x3E5\x3E6\ag\x2\x2\x3E6\x3E7\av\x2\x2\x3E7\x3ED\ak\x2\x2\x3E8"+
		"\x3E9\aT\x2\x2\x3E9\x3EA\aG\x2\x2\x3EA\x3EB\aV\x2\x2\x3EB\x3ED\aK\x2\x2"+
		"\x3EC\x3E4\x3\x2\x2\x2\x3EC\x3E8\x3\x2\x2\x2\x3ED\xAE\x3\x2\x2\x2\x3EE"+
		"\x3EF\at\x2\x2\x3EF\x3F0\an\x2\x2\x3F0\x3F5\a\x66\x2\x2\x3F1\x3F2\aT\x2"+
		"\x2\x3F2\x3F3\aN\x2\x2\x3F3\x3F5\a\x46\x2\x2\x3F4\x3EE\x3\x2\x2\x2\x3F4"+
		"\x3F1\x3\x2\x2\x2\x3F5\xB0\x3\x2\x2\x2\x3F6\x3F7\at\x2\x2\x3F7\x3F8\a"+
		"t\x2\x2\x3F8\x3FD\a\x66\x2\x2\x3F9\x3FA\aT\x2\x2\x3FA\x3FB\aT\x2\x2\x3FB"+
		"\x3FD\a\x46\x2\x2\x3FC\x3F6\x3\x2\x2\x2\x3FC\x3F9\x3\x2\x2\x2\x3FD\xB2"+
		"\x3\x2\x2\x2\x3FE\x3FF\an\x2\x2\x3FF\x400\a\x66\x2\x2\x400\x405\ak\x2"+
		"\x2\x401\x402\aN\x2\x2\x402\x403\a\x46\x2\x2\x403\x405\aK\x2\x2\x404\x3FE"+
		"\x3\x2\x2\x2\x404\x401\x3\x2\x2\x2\x405\xB4\x3\x2\x2\x2\x406\x407\a\x65"+
		"\x2\x2\x407\x408\ar\x2\x2\x408\x40D\ak\x2\x2\x409\x40A\a\x45\x2\x2\x40A"+
		"\x40B\aR\x2\x2\x40B\x40D\aK\x2\x2\x40C\x406\x3\x2\x2\x2\x40C\x409\x3\x2"+
		"\x2\x2\x40D\xB6\x3\x2\x2\x2\x40E\x40F\ak\x2\x2\x40F\x410\ap\x2\x2\x410"+
		"\x415\ak\x2\x2\x411\x412\aK\x2\x2\x412\x413\aP\x2\x2\x413\x415\aK\x2\x2"+
		"\x414\x40E\x3\x2\x2\x2\x414\x411\x3\x2\x2\x2\x415\xB8\x3\x2\x2\x2\x416"+
		"\x417\aq\x2\x2\x417\x418\aw\x2\x2\x418\x419\av\x2\x2\x419\x41F\ak\x2\x2"+
		"\x41A\x41B\aQ\x2\x2\x41B\x41C\aW\x2\x2\x41C\x41D\aV\x2\x2\x41D\x41F\a"+
		"K\x2\x2\x41E\x416\x3\x2\x2\x2\x41E\x41A\x3\x2\x2\x2\x41F\xBA\x3\x2\x2"+
		"\x2\x420\x421\an\x2\x2\x421\x422\a\x66\x2\x2\x422\x427\a\x66\x2\x2\x423"+
		"\x424\aN\x2\x2\x424\x425\a\x46\x2\x2\x425\x427\a\x46\x2\x2\x426\x420\x3"+
		"\x2\x2\x2\x426\x423\x3\x2\x2\x2\x427\xBC\x3\x2\x2\x2\x428\x429\a\x65\x2"+
		"\x2\x429\x42A\ar\x2\x2\x42A\x42F\a\x66\x2\x2\x42B\x42C\a\x45\x2\x2\x42C"+
		"\x42D\aR\x2\x2\x42D\x42F\a\x46\x2\x2\x42E\x428\x3\x2\x2\x2\x42E\x42B\x3"+
		"\x2\x2\x2\x42F\xBE\x3\x2\x2\x2\x430\x431\ak\x2\x2\x431\x432\ap\x2\x2\x432"+
		"\x437\a\x66\x2\x2\x433\x434\aK\x2\x2\x434\x435\aP\x2\x2\x435\x437\a\x46"+
		"\x2\x2\x436\x430\x3\x2\x2\x2\x436\x433\x3\x2\x2\x2\x437\xC0\x3\x2\x2\x2"+
		"\x438\x439\aq\x2\x2\x439\x43A\aw\x2\x2\x43A\x43B\av\x2\x2\x43B\x441\a"+
		"\x66\x2\x2\x43C\x43D\aQ\x2\x2\x43D\x43E\aW\x2\x2\x43E\x43F\aV\x2\x2\x43F"+
		"\x441\a\x46\x2\x2\x440\x438\x3\x2\x2\x2\x440\x43C\x3\x2\x2\x2\x441\xC2"+
		"\x3\x2\x2\x2\x442\x443\an\x2\x2\x443\x444\a\x66\x2\x2\x444\x445\ak\x2"+
		"\x2\x445\x44B\at\x2\x2\x446\x447\aN\x2\x2\x447\x448\a\x46\x2\x2\x448\x449"+
		"\aK\x2\x2\x449\x44B\aT\x2\x2\x44A\x442\x3\x2\x2\x2\x44A\x446\x3\x2\x2"+
		"\x2\x44B\xC4\x3\x2\x2\x2\x44C\x44D\a\x65\x2\x2\x44D\x44E\ar\x2\x2\x44E"+
		"\x44F\ak\x2\x2\x44F\x455\at\x2\x2\x450\x451\a\x45\x2\x2\x451\x452\aR\x2"+
		"\x2\x452\x453\aK\x2\x2\x453\x455\aT\x2\x2\x454\x44C\x3\x2\x2\x2\x454\x450"+
		"\x3\x2\x2\x2\x455\xC6\x3\x2\x2\x2\x456\x457\ak\x2\x2\x457\x458\ap\x2\x2"+
		"\x458\x459\ak\x2\x2\x459\x45F\at\x2\x2\x45A\x45B\aK\x2\x2\x45B\x45C\a"+
		"P\x2\x2\x45C\x45D\aK\x2\x2\x45D\x45F\aT\x2\x2\x45E\x456\x3\x2\x2\x2\x45E"+
		"\x45A\x3\x2\x2\x2\x45F\xC8\x3\x2\x2\x2\x460\x461\aq\x2\x2\x461\x462\a"+
		"v\x2\x2\x462\x463\ak\x2\x2\x463\x469\at\x2\x2\x464\x465\aQ\x2\x2\x465"+
		"\x466\aV\x2\x2\x466\x467\aK\x2\x2\x467\x469\aT\x2\x2\x468\x460\x3\x2\x2"+
		"\x2\x468\x464\x3\x2\x2\x2\x469\xCA\x3\x2\x2\x2\x46A\x46B\an\x2\x2\x46B"+
		"\x46C\a\x66\x2\x2\x46C\x46D\a\x66\x2\x2\x46D\x473\at\x2\x2\x46E\x46F\a"+
		"N\x2\x2\x46F\x470\a\x46\x2\x2\x470\x471\a\x46\x2\x2\x471\x473\aT\x2\x2"+
		"\x472\x46A\x3\x2\x2\x2\x472\x46E\x3\x2\x2\x2\x473\xCC\x3\x2\x2\x2\x474"+
		"\x475\a\x65\x2\x2\x475\x476\ar\x2\x2\x476\x477\a\x66\x2\x2\x477\x47D\a"+
		"t\x2\x2\x478\x479\a\x45\x2\x2\x479\x47A\aR\x2\x2\x47A\x47B\a\x46\x2\x2"+
		"\x47B\x47D\aT\x2\x2\x47C\x474\x3\x2\x2\x2\x47C\x478\x3\x2\x2\x2\x47D\xCE"+
		"\x3\x2\x2\x2\x47E\x47F\ak\x2\x2\x47F\x480\ap\x2\x2\x480\x481\a\x66\x2"+
		"\x2\x481\x487\at\x2\x2\x482\x483\aK\x2\x2\x483\x484\aP\x2\x2\x484\x485"+
		"\a\x46\x2\x2\x485\x487\aT\x2\x2\x486\x47E\x3\x2\x2\x2\x486\x482\x3\x2"+
		"\x2\x2\x487\xD0\x3\x2\x2\x2\x488\x489\aq\x2\x2\x489\x48A\av\x2\x2\x48A"+
		"\x48B\a\x66\x2\x2\x48B\x491\at\x2\x2\x48C\x48D\aQ\x2\x2\x48D\x48E\aV\x2"+
		"\x2\x48E\x48F\a\x46\x2\x2\x48F\x491\aT\x2\x2\x490\x488\x3\x2\x2\x2\x490"+
		"\x48C\x3\x2\x2\x2\x491\xD2\x3\x2\x2\x2\x492\x493\an\x2\x2\x493\x497\a"+
		"\x66\x2\x2\x494\x495\aN\x2\x2\x495\x497\a\x46\x2\x2\x496\x492\x3\x2\x2"+
		"\x2\x496\x494\x3\x2\x2\x2\x497\xD4\x3\x2\x2\x2\x498\x499\ak\x2\x2\x499"+
		"\x49A\ap\x2\x2\x49A\x49F\a\x65\x2\x2\x49B\x49C\aK\x2\x2\x49C\x49D\aP\x2"+
		"\x2\x49D\x49F\a\x45\x2\x2\x49E\x498\x3\x2\x2\x2\x49E\x49B\x3\x2\x2\x2"+
		"\x49F\xD6\x3\x2\x2\x2\x4A0\x4A1\a\x66\x2\x2\x4A1\x4A2\ag\x2\x2\x4A2\x4A7"+
		"\a\x65\x2\x2\x4A3\x4A4\a\x46\x2\x2\x4A4\x4A5\aG\x2\x2\x4A5\x4A7\a\x45"+
		"\x2\x2\x4A6\x4A0\x3\x2\x2\x2\x4A6\x4A3\x3\x2\x2\x2\x4A7\xD8\x3\x2\x2\x2"+
		"\x4A8\x4A9\ag\x2\x2\x4A9\x4AD\az\x2\x2\x4AA\x4AB\aG\x2\x2\x4AB\x4AD\a"+
		"Z\x2\x2\x4AC\x4A8\x3\x2\x2\x2\x4AC\x4AA\x3\x2\x2\x2\x4AD\xDA\x3\x2\x2"+
		"\x2\x4AE\x4AF\a\x63\x2\x2\x4AF\x4B0\a\x66\x2\x2\x4B0\x4B5\a\x66\x2\x2"+
		"\x4B1\x4B2\a\x43\x2\x2\x4B2\x4B3\a\x46\x2\x2\x4B3\x4B5\a\x46\x2\x2\x4B4"+
		"\x4AE\x3\x2\x2\x2\x4B4\x4B1\x3\x2\x2\x2\x4B5\xDC\x3\x2\x2\x2\x4B6\x4B7"+
		"\a\x63\x2\x2\x4B7\x4B8\a\x66\x2\x2\x4B8\x4BD\a\x65\x2\x2\x4B9\x4BA\a\x43"+
		"\x2\x2\x4BA\x4BB\a\x46\x2\x2\x4BB\x4BD\a\x45\x2\x2\x4BC\x4B6\x3\x2\x2"+
		"\x2\x4BC\x4B9\x3\x2\x2\x2\x4BD\xDE\x3\x2\x2\x2\x4BE\x4BF\au\x2\x2\x4BF"+
		"\x4C0\aw\x2\x2\x4C0\x4C5\a\x64\x2\x2\x4C1\x4C2\aU\x2\x2\x4C2\x4C3\aW\x2"+
		"\x2\x4C3\x4C5\a\x44\x2\x2\x4C4\x4BE\x3\x2\x2\x2\x4C4\x4C1\x3\x2\x2\x2"+
		"\x4C5\xE0\x3\x2\x2\x2\x4C6\x4C7\au\x2\x2\x4C7\x4C8\a\x64\x2\x2\x4C8\x4CD"+
		"\a\x65\x2\x2\x4C9\x4CA\aU\x2\x2\x4CA\x4CB\a\x44\x2\x2\x4CB\x4CD\a\x45"+
		"\x2\x2\x4CC\x4C6\x3\x2\x2\x2\x4CC\x4C9\x3\x2\x2\x2\x4CD\xE2\x3\x2\x2\x2"+
		"\x4CE\x4CF\a\x63\x2\x2\x4CF\x4D0\ap\x2\x2\x4D0\x4D5\a\x66\x2\x2\x4D1\x4D2"+
		"\a\x43\x2\x2\x4D2\x4D3\aP\x2\x2\x4D3\x4D5\a\x46\x2\x2\x4D4\x4CE\x3\x2"+
		"\x2\x2\x4D4\x4D1\x3\x2\x2\x2\x4D5\xE4\x3\x2\x2\x2\x4D6\x4D7\az\x2\x2\x4D7"+
		"\x4D8\aq\x2\x2\x4D8\x4DD\at\x2\x2\x4D9\x4DA\aZ\x2\x2\x4DA\x4DB\aQ\x2\x2"+
		"\x4DB\x4DD\aT\x2\x2\x4DC\x4D6\x3\x2\x2\x2\x4DC\x4D9\x3\x2\x2\x2\x4DD\xE6"+
		"\x3\x2\x2\x2\x4DE\x4DF\aq\x2\x2\x4DF\x4E3\at\x2\x2\x4E0\x4E1\aQ\x2\x2"+
		"\x4E1\x4E3\aT\x2\x2\x4E2\x4DE\x3\x2\x2\x2\x4E2\x4E0\x3\x2\x2\x2\x4E3\xE8"+
		"\x3\x2\x2\x2\x4E4\x4E5\a\x65\x2\x2\x4E5\x4E9\ar\x2\x2\x4E6\x4E7\a\x45"+
		"\x2\x2\x4E7\x4E9\aR\x2\x2\x4E8\x4E4\x3\x2\x2\x2\x4E8\x4E6\x3\x2\x2\x2"+
		"\x4E9\xEA\x3\x2\x2\x2\x4EA\x4EB\a\x66\x2\x2\x4EB\x4EC\al\x2\x2\x4EC\x4ED"+
		"\ap\x2\x2\x4ED\x4F3\a|\x2\x2\x4EE\x4EF\a\x46\x2\x2\x4EF\x4F0\aL\x2\x2"+
		"\x4F0\x4F1\aP\x2\x2\x4F1\x4F3\a\\\x2\x2\x4F2\x4EA\x3\x2\x2\x2\x4F2\x4EE"+
		"\x3\x2\x2\x2\x4F3\xEC\x3\x2\x2\x2\x4F4\x4F5\al\x2\x2\x4F5\x4F9\at\x2\x2"+
		"\x4F6\x4F7\aL\x2\x2\x4F7\x4F9\aT\x2\x2\x4F8\x4F4\x3\x2\x2\x2\x4F8\x4F6"+
		"\x3\x2\x2\x2\x4F9\xEE\x3\x2\x2\x2\x4FA\x4FB\al\x2\x2\x4FB\x4FF\ar\x2\x2"+
		"\x4FC\x4FD\aL\x2\x2\x4FD\x4FF\aR\x2\x2\x4FE\x4FA\x3\x2\x2\x2\x4FE\x4FC"+
		"\x3\x2\x2\x2\x4FF\xF0\x3\x2\x2\x2\x500\x501\a\x65\x2\x2\x501\x502\a\x63"+
		"\x2\x2\x502\x503\an\x2\x2\x503\x509\an\x2\x2\x504\x505\a\x45\x2\x2\x505"+
		"\x506\a\x43\x2\x2\x506\x507\aN\x2\x2\x507\x509\aN\x2\x2\x508\x500\x3\x2"+
		"\x2\x2\x508\x504\x3\x2\x2\x2\x509\xF2\x3\x2\x2\x2\x50A\x50B\at\x2\x2\x50B"+
		"\x50C\au\x2\x2\x50C\x511\av\x2\x2\x50D\x50E\aT\x2\x2\x50E\x50F\aU\x2\x2"+
		"\x50F\x511\aV\x2\x2\x510\x50A\x3\x2\x2\x2\x510\x50D\x3\x2\x2\x2\x511\xF4"+
		"\x3\x2\x2\x2\x512\x513\ar\x2\x2\x513\x514\aw\x2\x2\x514\x515\au\x2\x2"+
		"\x515\x51B\aj\x2\x2\x516\x517\aR\x2\x2\x517\x518\aW\x2\x2\x518\x519\a"+
		"U\x2\x2\x519\x51B\aJ\x2\x2\x51A\x512\x3\x2\x2\x2\x51A\x516\x3\x2\x2\x2"+
		"\x51B\xF6\x3\x2\x2\x2\x51C\x51D\ar\x2\x2\x51D\x51E\aq\x2\x2\x51E\x523"+
		"\ar\x2\x2\x51F\x520\aR\x2\x2\x520\x521\aQ\x2\x2\x521\x523\aR\x2\x2\x522"+
		"\x51C\x3\x2\x2\x2\x522\x51F\x3\x2\x2\x2\x523\xF8\x3\x2\x2\x2\x524\x525"+
		"\ak\x2\x2\x525\x529\ap\x2\x2\x526\x527\aK\x2\x2\x527\x529\aP\x2\x2\x528"+
		"\x524\x3\x2\x2\x2\x528\x526\x3\x2\x2\x2\x529\xFA\x3\x2\x2\x2\x52A\x52B"+
		"\aq\x2\x2\x52B\x52C\aw\x2\x2\x52C\x531\av\x2\x2\x52D\x52E\aQ\x2\x2\x52E"+
		"\x52F\aW\x2\x2\x52F\x531\aV\x2\x2\x530\x52A\x3\x2\x2\x2\x530\x52D\x3\x2"+
		"\x2\x2\x531\xFC\x3\x2\x2\x2\x532\x533\ak\x2\x2\x533\x537\ao\x2\x2\x534"+
		"\x535\aK\x2\x2\x535\x537\aO\x2\x2\x536\x532\x3\x2\x2\x2\x536\x534\x3\x2"+
		"\x2\x2\x537\xFE\x3\x2\x2\x2\x538\x539\at\x2\x2\x539\x53A\an\x2\x2\x53A"+
		"\x53F\a\x65\x2\x2\x53B\x53C\aT\x2\x2\x53C\x53D\aN\x2\x2\x53D\x53F\a\x45"+
		"\x2\x2\x53E\x538\x3\x2\x2\x2\x53E\x53B\x3\x2\x2\x2\x53F\x100\x3\x2\x2"+
		"\x2\x540\x541\at\x2\x2\x541\x542\at\x2\x2\x542\x547\a\x65\x2\x2\x543\x544"+
		"\aT\x2\x2\x544\x545\aT\x2\x2\x545\x547\a\x45\x2\x2\x546\x540\x3\x2\x2"+
		"\x2\x546\x543\x3\x2\x2\x2\x547\x102\x3\x2\x2\x2\x548\x549\at\x2\x2\x549"+
		"\x54D\an\x2\x2\x54A\x54B\aT\x2\x2\x54B\x54D\aN\x2\x2\x54C\x548\x3\x2\x2"+
		"\x2\x54C\x54A\x3\x2\x2\x2\x54D\x104\x3\x2\x2\x2\x54E\x54F\at\x2\x2\x54F"+
		"\x553\at\x2\x2\x550\x551\aT\x2\x2\x551\x553\aT\x2\x2\x552\x54E\x3\x2\x2"+
		"\x2\x552\x550\x3\x2\x2\x2\x553\x106\x3\x2\x2\x2\x554\x555\au\x2\x2\x555"+
		"\x556\an\x2\x2\x556\x55B\a\x63\x2\x2\x557\x558\aU\x2\x2\x558\x559\aN\x2"+
		"\x2\x559\x55B\a\x43\x2\x2\x55A\x554\x3\x2\x2\x2\x55A\x557\x3\x2\x2\x2"+
		"\x55B\x108\x3\x2\x2\x2\x55C\x55D\au\x2\x2\x55D\x55E\at\x2\x2\x55E\x563"+
		"\a\x63\x2\x2\x55F\x560\aU\x2\x2\x560\x561\aT\x2\x2\x561\x563\a\x43\x2"+
		"\x2\x562\x55C\x3\x2\x2\x2\x562\x55F\x3\x2\x2\x2\x563\x10A\x3\x2\x2\x2"+
		"\x564\x565\au\x2\x2\x565\x566\an\x2\x2\x566\x56B\an\x2\x2\x567\x568\a"+
		"U\x2\x2\x568\x569\aN\x2\x2\x569\x56B\aN\x2\x2\x56A\x564\x3\x2\x2\x2\x56A"+
		"\x567\x3\x2\x2\x2\x56B\x10C\x3\x2\x2\x2\x56C\x56D\au\x2\x2\x56D\x56E\a"+
		"t\x2\x2\x56E\x573\an\x2\x2\x56F\x570\aU\x2\x2\x570\x571\aT\x2\x2\x571"+
		"\x573\aN\x2\x2\x572\x56C\x3\x2\x2\x2\x572\x56F\x3\x2\x2\x2\x573\x10E\x3"+
		"\x2\x2\x2\x574\x575\a\x64\x2\x2\x575\x576\ak\x2\x2\x576\x57B\av\x2\x2"+
		"\x577\x578\a\x44\x2\x2\x578\x579\aK\x2\x2\x579\x57B\aV\x2\x2\x57A\x574"+
		"\x3\x2\x2\x2\x57A\x577\x3\x2\x2\x2\x57B\x110\x3\x2\x2\x2\x57C\x57D\at"+
		"\x2\x2\x57D\x57E\ag\x2\x2\x57E\x583\au\x2\x2\x57F\x580\aT\x2\x2\x580\x581"+
		"\aG\x2\x2\x581\x583\aU\x2\x2\x582\x57C\x3\x2\x2\x2\x582\x57F\x3\x2\x2"+
		"\x2\x583\x112\x3\x2\x2\x2\x584\x585\au\x2\x2\x585\x586\ag\x2\x2\x586\x58B"+
		"\av\x2\x2\x587\x588\aU\x2\x2\x588\x589\aG\x2\x2\x589\x58B\aV\x2\x2\x58A"+
		"\x584\x3\x2\x2\x2\x58A\x587\x3\x2\x2\x2\x58B\x114\x3\x2\x2\x2\x58C\x58D"+
		"\au\x2\x2\x58D\x58E\ay\x2\x2\x58E\x58F\a\x63\x2\x2\x58F\x590\ar\x2\x2"+
		"\x590\x591\ap\x2\x2\x591\x592\ak\x2\x2\x592\x59B\a\x64\x2\x2\x593\x594"+
		"\aU\x2\x2\x594\x595\aY\x2\x2\x595\x596\a\x43\x2\x2\x596\x597\aR\x2\x2"+
		"\x597\x598\aP\x2\x2\x598\x599\aK\x2\x2\x599\x59B\a\x44\x2\x2\x59A\x58C"+
		"\x3\x2\x2\x2\x59A\x593\x3\x2\x2\x2\x59B\x116\x3\x2\x2\x2\x59C\x59D\ao"+
		"\x2\x2\x59D\x59E\aw\x2\x2\x59E\x5A3\an\x2\x2\x59F\x5A0\aO\x2\x2\x5A0\x5A1"+
		"\aW\x2\x2\x5A1\x5A3\aN\x2\x2\x5A2\x59C\x3\x2\x2\x2\x5A2\x59F\x3\x2\x2"+
		"\x2\x5A3\x118\x3\x2\x2\x2\x5A4\x5A5\ar\x2\x2\x5A5\x5A6\aq\x2\x2\x5A6\x5A7"+
		"\ar\x2\x2\x5A7\x5AD\az\x2\x2\x5A8\x5A9\aR\x2\x2\x5A9\x5AA\aQ\x2\x2\x5AA"+
		"\x5AB\aR\x2\x2\x5AB\x5AD\aZ\x2\x2\x5AC\x5A4\x3\x2\x2\x2\x5AC\x5A8\x3\x2"+
		"\x2\x2\x5AD\x11A\x3\x2\x2\x2\x5AE\x5AF\ao\x2\x2\x5AF\x5B0\ak\x2\x2\x5B0"+
		"\x5B1\at\x2\x2\x5B1\x5B2\at\x2\x2\x5B2\x5B3\aq\x2\x2\x5B3\x5BB\at\x2\x2"+
		"\x5B4\x5B5\aO\x2\x2\x5B5\x5B6\aK\x2\x2\x5B6\x5B7\aT\x2\x2\x5B7\x5B8\a"+
		"T\x2\x2\x5B8\x5B9\aQ\x2\x2\x5B9\x5BB\aT\x2\x2\x5BA\x5AE\x3\x2\x2\x2\x5BA"+
		"\x5B4\x3\x2\x2\x2\x5BB\x11C\x3\x2\x2\x2\x5BC\x5BD\av\x2\x2\x5BD\x5BE\a"+
		"g\x2\x2\x5BE\x5BF\au\x2\x2\x5BF\x5C5\av\x2\x2\x5C0\x5C1\aV\x2\x2\x5C1"+
		"\x5C2\aG\x2\x2\x5C2\x5C3\aU\x2\x2\x5C3\x5C5\aV\x2\x2\x5C4\x5BC\x3\x2\x2"+
		"\x2\x5C4\x5C0\x3\x2\x2\x2\x5C5\x11E\x3\x2\x2\x2\x5C6\x5C7\ap\x2\x2\x5C7"+
		"\x5C8\ag\x2\x2\x5C8\x5C9\az\x2\x2\x5C9\x5CA\av\x2\x2\x5CA\x5CB\at\x2\x2"+
		"\x5CB\x5CC\ag\x2\x2\x5CC\x5D5\ai\x2\x2\x5CD\x5CE\aP\x2\x2\x5CE\x5CF\a"+
		"G\x2\x2\x5CF\x5D0\aZ\x2\x2\x5D0\x5D1\aV\x2\x2\x5D1\x5D2\aT\x2\x2\x5D2"+
		"\x5D3\aG\x2\x2\x5D3\x5D5\aI\x2\x2\x5D4\x5C6\x3\x2\x2\x2\x5D4\x5CD\x3\x2"+
		"\x2\x2\x5D5\x120\x3\x2\x2\x2\x5D6\x5D7\aq\x2\x2\x5D7\x5D8\aw\x2\x2\x5D8"+
		"\x5D9\av\x2\x2\x5D9\x5DA\ak\x2\x2\x5DA\x5DB\ap\x2\x2\x5DB\x5E3\a\x64\x2"+
		"\x2\x5DC\x5DD\aQ\x2\x2\x5DD\x5DE\aW\x2\x2\x5DE\x5DF\aV\x2\x2\x5DF\x5E0"+
		"\aK\x2\x2\x5E0\x5E1\aP\x2\x2\x5E1\x5E3\a\x44\x2\x2\x5E2\x5D6\x3\x2\x2"+
		"\x2\x5E2\x5DC\x3\x2\x2\x2\x5E3\x122\x3\x2\x2\x2\x5E4\x5E5\an\x2\x2\x5E5"+
		"\x5E6\a\x66\x2\x2\x5E6\x5E7\ak\x2\x2\x5E7\x5ED\az\x2\x2\x5E8\x5E9\aN\x2"+
		"\x2\x5E9\x5EA\a\x46\x2\x2\x5EA\x5EB\aK\x2\x2\x5EB\x5ED\aZ\x2\x2\x5EC\x5E4"+
		"\x3\x2\x2\x2\x5EC\x5E8\x3\x2\x2\x2\x5ED\x124\x3\x2\x2\x2\x5EE\x5EF\an"+
		"\x2\x2\x5EF\x5F0\a\x66\x2\x2\x5F0\x5F1\ak\x2\x2\x5F1\x5F2\at\x2\x2\x5F2"+
		"\x5F9\az\x2\x2\x5F3\x5F4\aN\x2\x2\x5F4\x5F5\a\x46\x2\x2\x5F5\x5F6\aK\x2"+
		"\x2\x5F6\x5F7\aT\x2\x2\x5F7\x5F9\aZ\x2\x2\x5F8\x5EE\x3\x2\x2\x2\x5F8\x5F3"+
		"\x3\x2\x2\x2\x5F9\x126\x3\x2\x2\x2\x5FA\x5FB\an\x2\x2\x5FB\x5FC\a\x66"+
		"\x2\x2\x5FC\x5FD\a\x66\x2\x2\x5FD\x603\az\x2\x2\x5FE\x5FF\aN\x2\x2\x5FF"+
		"\x600\a\x46\x2\x2\x600\x601\a\x46\x2\x2\x601\x603\aZ\x2\x2\x602\x5FA\x3"+
		"\x2\x2\x2\x602\x5FE\x3\x2\x2\x2\x603\x128\x3\x2\x2\x2\x604\x605\an\x2"+
		"\x2\x605\x606\a\x66\x2\x2\x606\x607\a\x66\x2\x2\x607\x608\at\x2\x2\x608"+
		"\x60F\az\x2\x2\x609\x60A\aN\x2\x2\x60A\x60B\a\x46\x2\x2\x60B\x60C\a\x46"+
		"\x2\x2\x60C\x60D\aT\x2\x2\x60D\x60F\aZ\x2\x2\x60E\x604\x3\x2\x2\x2\x60E"+
		"\x609\x3\x2\x2\x2\x60F\x12A\x3\x2\x2\x2\x610\x611\ar\x2\x2\x611\x612\a"+
		"k\x2\x2\x612\x613\az\x2\x2\x613\x614\ag\x2\x2\x614\x615\an\x2\x2\x615"+
		"\x616\a\x66\x2\x2\x616\x61F\ap\x2\x2\x617\x618\aR\x2\x2\x618\x619\aK\x2"+
		"\x2\x619\x61A\aZ\x2\x2\x61A\x61B\aG\x2\x2\x61B\x61C\aN\x2\x2\x61C\x61D"+
		"\a\x46\x2\x2\x61D\x61F\aP\x2\x2\x61E\x610\x3\x2\x2\x2\x61E\x617\x3\x2"+
		"\x2\x2\x61F\x12C\x3\x2\x2\x2\x620\x621\ar\x2\x2\x621\x622\ak\x2\x2\x622"+
		"\x623\az\x2\x2\x623\x624\ag\x2\x2\x624\x625\an\x2\x2\x625\x626\a\x63\x2"+
		"\x2\x626\x62F\a\x66\x2\x2\x627\x628\aR\x2\x2\x628\x629\aK\x2\x2\x629\x62A"+
		"\aZ\x2\x2\x62A\x62B\aG\x2\x2\x62B\x62C\aN\x2\x2\x62C\x62D\a\x43\x2\x2"+
		"\x62D\x62F\a\x46\x2\x2\x62E\x620\x3\x2\x2\x2\x62E\x627\x3\x2\x2\x2\x62F"+
		"\x12E\x3\x2\x2\x2\x630\x631\au\x2\x2\x631\x632\ag\x2\x2\x632\x633\av\x2"+
		"\x2\x633\x634\a\x63\x2\x2\x634\x63B\ag\x2\x2\x635\x636\aU\x2\x2\x636\x637"+
		"\aG\x2\x2\x637\x638\aV\x2\x2\x638\x639\a\x43\x2\x2\x639\x63B\aG\x2\x2"+
		"\x63A\x630\x3\x2\x2\x2\x63A\x635\x3\x2\x2\x2\x63B\x130\x3\x2\x2\x2\x63C"+
		"\x63D\an\x2\x2\x63D\x63E\a\x66\x2\x2\x63E\x63F\ar\x2\x2\x63F\x640\ak\x2"+
		"\x2\x640\x641\at\x2\x2\x641\x649\az\x2\x2\x642\x643\aN\x2\x2\x643\x644"+
		"\a\x46\x2\x2\x644\x645\aR\x2\x2\x645\x646\aK\x2\x2\x646\x647\aT\x2\x2"+
		"\x647\x649\aZ\x2\x2\x648\x63C\x3\x2\x2\x2\x648\x642\x3\x2\x2\x2\x649\x132"+
		"\x3\x2\x2\x2\x64A\x64B\an\x2\x2\x64B\x64C\a\x66\x2\x2\x64C\x64D\ak\x2"+
		"\x2\x64D\x64E\at\x2\x2\x64E\x64F\au\x2\x2\x64F\x650\a\x65\x2\x2\x650\x651"+
		"\a\x63\x2\x2\x651\x652\an\x2\x2\x652\x65D\ag\x2\x2\x653\x654\aN\x2\x2"+
		"\x654\x655\a\x46\x2\x2\x655\x656\aK\x2\x2\x656\x657\aT\x2\x2\x657\x658"+
		"\aU\x2\x2\x658\x659\a\x45\x2\x2\x659\x65A\a\x43\x2\x2\x65A\x65B\aN\x2"+
		"\x2\x65B\x65D\aG\x2\x2\x65C\x64A\x3\x2\x2\x2\x65C\x653\x3\x2\x2\x2\x65D"+
		"\x134\x3\x2\x2\x2\x65E\x65F\a%\x2\x2\x65F\x660\ak\x2\x2\x660\x661\ah\x2"+
		"\x2\x661\x662\a\x66\x2\x2\x662\x663\ag\x2\x2\x663\x664\ah\x2\x2\x664\x136"+
		"\x3\x2\x2\x2\x665\x666\a%\x2\x2\x666\x667\ak\x2\x2\x667\x668\ah\x2\x2"+
		"\x668\x669\ap\x2\x2\x669\x66A\a\x66\x2\x2\x66A\x66B\ag\x2\x2\x66B\x66C"+
		"\ah\x2\x2\x66C\x138\x3\x2\x2\x2\x66D\x66E\a%\x2\x2\x66E\x66F\ag\x2\x2"+
		"\x66F\x670\ap\x2\x2\x670\x671\a\x66\x2\x2\x671\x672\ak\x2\x2\x672\x673"+
		"\ah\x2\x2\x673\x13A\x3\x2\x2\x2\x674\x675\a%\x2\x2\x675\x676\ag\x2\x2"+
		"\x676\x677\an\x2\x2\x677\x678\au\x2\x2\x678\x679\ag\x2\x2\x679\x13C\x3"+
		"\x2\x2\x2\x67A\x67B\a%\x2\x2\x67B\x67C\a\x66\x2\x2\x67C\x67D\ag\x2\x2"+
		"\x67D\x67E\ah\x2\x2\x67E\x67F\ak\x2\x2\x67F\x680\ap\x2\x2\x680\x681\a"+
		"g\x2\x2\x681\x13E\x3\x2\x2\x2\x682\x683\a%\x2\x2\x683\x684\aw\x2\x2\x684"+
		"\x685\ap\x2\x2\x685\x686\a\x66\x2\x2\x686\x687\ag\x2\x2\x687\x688\ah\x2"+
		"\x2\x688\x140\x3\x2\x2\x2\x689\x68A\a%\x2\x2\x68A\x68B\ak\x2\x2\x68B\x68C"+
		"\ap\x2\x2\x68C\x68D\a\x65\x2\x2\x68D\x68E\an\x2\x2\x68E\x68F\aw\x2\x2"+
		"\x68F\x690\a\x66\x2\x2\x690\x691\ag\x2\x2\x691\x142\x3\x2\x2\x2\x692\x693"+
		"\a%\x2\x2\x693\x694\ak\x2\x2\x694\x695\ah\x2\x2\x695\x144\x3\x2\x2\x2"+
		"\x696\x697\a%\x2\x2\x697\x698\ak\x2\x2\x698\x699\ah\x2\x2\x699\x69A\a"+
		"o\x2\x2\x69A\x69B\aq\x2\x2\x69B\x69C\a\x66\x2\x2\x69C\x146\x3\x2\x2\x2"+
		"\x69D\x69E\a%\x2\x2\x69E\x69F\ak\x2\x2\x69F\x6A0\ah\x2\x2\x6A0\x6A1\a"+
		"p\x2\x2\x6A1\x6A2\ao\x2\x2\x6A2\x6A3\aq\x2\x2\x6A3\x6A4\a\x66\x2\x2\x6A4"+
		"\x148\x3\x2\x2\x2\x6A5\x6A6\a%\x2\x2\x6A6\x6A7\an\x2\x2\x6A7\x6A8\ak\x2"+
		"\x2\x6A8\x6A9\ap\x2\x2\x6A9\x6AA\ag\x2\x2\x6AA\x14A\x3\x2\x2\x2\x6AB\x6AC"+
		"\a\x30\x2\x2\x6AC\x6AD\aq\x2\x2\x6AD\x6AE\at\x2\x2\x6AE\x6BA\ai\x2\x2"+
		"\x6AF\x6B0\a\x30\x2\x2\x6B0\x6B1\aQ\x2\x2\x6B1\x6B2\aT\x2\x2\x6B2\x6BA"+
		"\aI\x2\x2\x6B3\x6B4\aq\x2\x2\x6B4\x6B5\at\x2\x2\x6B5\x6BA\ai\x2\x2\x6B6"+
		"\x6B7\aQ\x2\x2\x6B7\x6B8\aT\x2\x2\x6B8\x6BA\aI\x2\x2\x6B9\x6AB\x3\x2\x2"+
		"\x2\x6B9\x6AF\x3\x2\x2\x2\x6B9\x6B3\x3\x2\x2\x2\x6B9\x6B6\x3\x2\x2\x2"+
		"\x6BA\x14C\x3\x2\x2\x2\x6BB\x6BC\a\x30\x2\x2\x6BC\x6BD\a\x64\x2\x2\x6BD"+
		"\x6BE\a\x63\x2\x2\x6BE\x6BF\ap\x2\x2\x6BF\x6CE\am\x2\x2\x6C0\x6C1\a\x30"+
		"\x2\x2\x6C1\x6C2\a\x44\x2\x2\x6C2\x6C3\a\x43\x2\x2\x6C3\x6C4\aP\x2\x2"+
		"\x6C4\x6CE\aM\x2\x2\x6C5\x6C6\a\x64\x2\x2\x6C6\x6C7\a\x63\x2\x2\x6C7\x6C8"+
		"\ap\x2\x2\x6C8\x6CE\am\x2\x2\x6C9\x6CA\a\x44\x2\x2\x6CA\x6CB\a\x43\x2"+
		"\x2\x6CB\x6CC\aP\x2\x2\x6CC\x6CE\aM\x2\x2\x6CD\x6BB\x3\x2\x2\x2\x6CD\x6C0"+
		"\x3\x2\x2\x2\x6CD\x6C5\x3\x2\x2\x2\x6CD\x6C9\x3\x2\x2\x2\x6CE\x14E\x3"+
		"\x2\x2\x2\x6CF\x6D0\a\x30\x2\x2\x6D0\x6D1\az\x2\x2\x6D1\x6D2\aq\x2\x2"+
		"\x6D2\x6D3\at\x2\x2\x6D3\x6E2\ai\x2\x2\x6D4\x6D5\a\x30\x2\x2\x6D5\x6D6"+
		"\aZ\x2\x2\x6D6\x6D7\aQ\x2\x2\x6D7\x6D8\aT\x2\x2\x6D8\x6E2\aI\x2\x2\x6D9"+
		"\x6DA\az\x2\x2\x6DA\x6DB\aq\x2\x2\x6DB\x6DC\at\x2\x2\x6DC\x6E2\ai\x2\x2"+
		"\x6DD\x6DE\aZ\x2\x2\x6DE\x6DF\aQ\x2\x2\x6DF\x6E0\aT\x2\x2\x6E0\x6E2\a"+
		"I\x2\x2\x6E1\x6CF\x3\x2\x2\x2\x6E1\x6D4\x3\x2\x2\x2\x6E1\x6D9\x3\x2\x2"+
		"\x2\x6E1\x6DD\x3\x2\x2\x2\x6E2\x150\x3\x2\x2\x2\x6E3\x6E4\a\x30\x2\x2"+
		"\x6E4\x6E5\ag\x2\x2\x6E5\x6E6\ap\x2\x2\x6E6\x6F2\av\x2\x2\x6E7\x6E8\a"+
		"\x30\x2\x2\x6E8\x6E9\aG\x2\x2\x6E9\x6EA\aP\x2\x2\x6EA\x6F2\aV\x2\x2\x6EB"+
		"\x6EC\ag\x2\x2\x6EC\x6ED\ap\x2\x2\x6ED\x6F2\av\x2\x2\x6EE\x6EF\aG\x2\x2"+
		"\x6EF\x6F0\aP\x2\x2\x6F0\x6F2\aV\x2\x2\x6F1\x6E3\x3\x2\x2\x2\x6F1\x6E7"+
		"\x3\x2\x2\x2\x6F1\x6EB\x3\x2\x2\x2\x6F1\x6EE\x3\x2\x2\x2\x6F2\x152\x3"+
		"\x2\x2\x2\x6F3\x6F4\a\x30\x2\x2\x6F4\x6F5\az\x2\x2\x6F5\x6F6\ag\x2\x2"+
		"\x6F6\x6F7\ap\x2\x2\x6F7\x706\av\x2\x2\x6F8\x6F9\a\x30\x2\x2\x6F9\x6FA"+
		"\aZ\x2\x2\x6FA\x6FB\aG\x2\x2\x6FB\x6FC\aP\x2\x2\x6FC\x706\aV\x2\x2\x6FD"+
		"\x6FE\az\x2\x2\x6FE\x6FF\ag\x2\x2\x6FF\x700\ap\x2\x2\x700\x706\av\x2\x2"+
		"\x701\x702\aZ\x2\x2\x702\x703\aG\x2\x2\x703\x704\aP\x2\x2\x704\x706\a"+
		"V\x2\x2\x705\x6F3\x3\x2\x2\x2\x705\x6F8\x3\x2\x2\x2\x705\x6FD\x3\x2\x2"+
		"\x2\x705\x701\x3\x2\x2\x2\x706\x154\x3\x2\x2\x2\x707\x708\a\x30\x2\x2"+
		"\x708\x709\ag\x2\x2\x709\x70A\as\x2\x2\x70A\x716\aw\x2\x2\x70B\x70C\a"+
		"\x30\x2\x2\x70C\x70D\aG\x2\x2\x70D\x70E\aS\x2\x2\x70E\x716\aW\x2\x2\x70F"+
		"\x710\ag\x2\x2\x710\x711\as\x2\x2\x711\x716\aw\x2\x2\x712\x713\aG\x2\x2"+
		"\x713\x714\aS\x2\x2\x714\x716\aW\x2\x2\x715\x707\x3\x2\x2\x2\x715\x70B"+
		"\x3\x2\x2\x2\x715\x70F\x3\x2\x2\x2\x715\x712\x3\x2\x2\x2\x716\x156\x3"+
		"\x2\x2\x2\x717\x718\a\x30\x2\x2\x718\x719\ax\x2\x2\x719\x71A\a\x63\x2"+
		"\x2\x71A\x728\at\x2\x2\x71B\x71C\a\x30\x2\x2\x71C\x71D\aX\x2\x2\x71D\x71E"+
		"\a\x43\x2\x2\x71E\x728\aT\x2\x2\x71F\x720\ax\x2\x2\x720\x721\a\x63\x2"+
		"\x2\x721\x728\at\x2\x2\x722\x723\aX\x2\x2\x723\x724\a\x43\x2\x2\x724\x728"+
		"\aT\x2\x2\x725\x726\a<\x2\x2\x726\x728\a?\x2\x2\x727\x717\x3\x2\x2\x2"+
		"\x727\x71B\x3\x2\x2\x2\x727\x71F\x3\x2\x2\x2\x727\x722\x3\x2\x2\x2\x727"+
		"\x725\x3\x2\x2\x2\x728\x158\x3\x2\x2\x2\x729\x72A\a\x30\x2\x2\x72A\x72B"+
		"\a\x66\x2\x2\x72B\x72C\ak\x2\x2\x72C\x72D\au\x2\x2\x72D\x73C\ar\x2\x2"+
		"\x72E\x72F\a\x30\x2\x2\x72F\x730\a\x46\x2\x2\x730\x731\aK\x2\x2\x731\x732"+
		"\aU\x2\x2\x732\x73C\aR\x2\x2\x733\x734\a\x66\x2\x2\x734\x735\ak\x2\x2"+
		"\x735\x736\au\x2\x2\x736\x73C\ar\x2\x2\x737\x738\a\x46\x2\x2\x738\x739"+
		"\aK\x2\x2\x739\x73A\aU\x2\x2\x73A\x73C\aR\x2\x2\x73B\x729\x3\x2\x2\x2"+
		"\x73B\x72E\x3\x2\x2\x2\x73B\x733\x3\x2\x2\x2\x73B\x737\x3\x2\x2\x2\x73C"+
		"\x15A\x3\x2\x2\x2\x73D\x73E\a\x30\x2\x2\x73E\x73F\a\x66\x2\x2\x73F\x740"+
		"\ag\x2\x2\x740\x741\ah\x2\x2\x741\x75A\a\x64\x2\x2\x742\x743\a\x30\x2"+
		"\x2\x743\x744\a\x46\x2\x2\x744\x745\aG\x2\x2\x745\x746\aH\x2\x2\x746\x75A"+
		"\a\x44\x2\x2\x747\x748\a\x66\x2\x2\x748\x749\ag\x2\x2\x749\x74A\ah\x2"+
		"\x2\x74A\x75A\a\x64\x2\x2\x74B\x74C\a\x46\x2\x2\x74C\x74D\aG\x2\x2\x74D"+
		"\x74E\aH\x2\x2\x74E\x75A\a\x44\x2\x2\x74F\x750\a\x66\x2\x2\x750\x75A\a"+
		"\x64\x2\x2\x751\x752\a\x30\x2\x2\x752\x753\a\x66\x2\x2\x753\x75A\a\x64"+
		"\x2\x2\x754\x755\a\x46\x2\x2\x755\x75A\a\x44\x2\x2\x756\x757\a\x30\x2"+
		"\x2\x757\x758\a\x46\x2\x2\x758\x75A\a\x44\x2\x2\x759\x73D\x3\x2\x2\x2"+
		"\x759\x742\x3\x2\x2\x2\x759\x747\x3\x2\x2\x2\x759\x74B\x3\x2\x2\x2\x759"+
		"\x74F\x3\x2\x2\x2\x759\x751\x3\x2\x2\x2\x759\x754\x3\x2\x2\x2\x759\x756"+
		"\x3\x2\x2\x2\x75A\x15C\x3\x2\x2\x2\x75B\x75C\a\x30\x2\x2\x75C\x75D\a\x66"+
		"\x2\x2\x75D\x75E\ag\x2\x2\x75E\x75F\ah\x2\x2\x75F\x778\ay\x2\x2\x760\x761"+
		"\a\x30\x2\x2\x761\x762\a\x46\x2\x2\x762\x763\aG\x2\x2\x763\x764\aH\x2"+
		"\x2\x764\x778\aY\x2\x2\x765\x766\a\x66\x2\x2\x766\x767\ag\x2\x2\x767\x768"+
		"\ah\x2\x2\x768\x778\ay\x2\x2\x769\x76A\a\x46\x2\x2\x76A\x76B\aG\x2\x2"+
		"\x76B\x76C\aH\x2\x2\x76C\x778\aY\x2\x2\x76D\x76E\a\x66\x2\x2\x76E\x778"+
		"\ay\x2\x2\x76F\x770\a\x30\x2\x2\x770\x771\a\x66\x2\x2\x771\x778\ay\x2"+
		"\x2\x772\x773\a\x46\x2\x2\x773\x778\aY\x2\x2\x774\x775\a\x30\x2\x2\x775"+
		"\x776\a\x46\x2\x2\x776\x778\aY\x2\x2\x777\x75B\x3\x2\x2\x2\x777\x760\x3"+
		"\x2\x2\x2\x777\x765\x3\x2\x2\x2\x777\x769\x3\x2\x2\x2\x777\x76D\x3\x2"+
		"\x2\x2\x777\x76F\x3\x2\x2\x2\x777\x772\x3\x2\x2\x2\x777\x774\x3\x2\x2"+
		"\x2\x778\x15E\x3\x2\x2\x2\x779\x77A\a\x30\x2\x2\x77A\x77B\a\x66\x2\x2"+
		"\x77B\x77C\ag\x2\x2\x77C\x77D\ah\x2\x2\x77D\x796\ao\x2\x2\x77E\x77F\a"+
		"\x30\x2\x2\x77F\x780\a\x46\x2\x2\x780\x781\aG\x2\x2\x781\x782\aH\x2\x2"+
		"\x782\x796\aO\x2\x2\x783\x784\a\x66\x2\x2\x784\x785\ag\x2\x2\x785\x786"+
		"\ah\x2\x2\x786\x796\ao\x2\x2\x787\x788\a\x46\x2\x2\x788\x789\aG\x2\x2"+
		"\x789\x78A\aH\x2\x2\x78A\x796\aO\x2\x2\x78B\x78C\a\x66\x2\x2\x78C\x796"+
		"\ao\x2\x2\x78D\x78E\a\x30\x2\x2\x78E\x78F\a\x66\x2\x2\x78F\x796\ao\x2"+
		"\x2\x790\x791\a\x46\x2\x2\x791\x796\aO\x2\x2\x792\x793\a\x30\x2\x2\x793"+
		"\x794\a\x46\x2\x2\x794\x796\aO\x2\x2\x795\x779\x3\x2\x2\x2\x795\x77E\x3"+
		"\x2\x2\x2\x795\x783\x3\x2\x2\x2\x795\x787\x3\x2\x2\x2\x795\x78B\x3\x2"+
		"\x2\x2\x795\x78D\x3\x2\x2\x2\x795\x790\x3\x2\x2\x2\x795\x792\x3\x2\x2"+
		"\x2\x796\x160\x3\x2\x2\x2\x797\x798\a\x30\x2\x2\x798\x799\a\x66\x2\x2"+
		"\x799\x79A\ag\x2\x2\x79A\x79B\ah\x2\x2\x79B\x7B4\ap\x2\x2\x79C\x79D\a"+
		"\x30\x2\x2\x79D\x79E\a\x46\x2\x2\x79E\x79F\aG\x2\x2\x79F\x7A0\aH\x2\x2"+
		"\x7A0\x7B4\aP\x2\x2\x7A1\x7A2\a\x66\x2\x2\x7A2\x7A3\ag\x2\x2\x7A3\x7A4"+
		"\ah\x2\x2\x7A4\x7B4\ap\x2\x2\x7A5\x7A6\a\x46\x2\x2\x7A6\x7A7\aG\x2\x2"+
		"\x7A7\x7A8\aH\x2\x2\x7A8\x7B4\aP\x2\x2\x7A9\x7AA\a\x66\x2\x2\x7AA\x7B4"+
		"\ap\x2\x2\x7AB\x7AC\a\x30\x2\x2\x7AC\x7AD\a\x66\x2\x2\x7AD\x7B4\ap\x2"+
		"\x2\x7AE\x7AF\a\x46\x2\x2\x7AF\x7B4\aP\x2\x2\x7B0\x7B1\a\x30\x2\x2\x7B1"+
		"\x7B2\a\x46\x2\x2\x7B2\x7B4\aP\x2\x2\x7B3\x797\x3\x2\x2\x2\x7B3\x79C\x3"+
		"\x2\x2\x2\x7B3\x7A1\x3\x2\x2\x2\x7B3\x7A5\x3\x2\x2\x2\x7B3\x7A9\x3\x2"+
		"\x2\x2\x7B3\x7AB\x3\x2\x2\x2\x7B3\x7AE\x3\x2\x2\x2\x7B3\x7B0\x3\x2\x2"+
		"\x2\x7B4\x162\x3\x2\x2\x2\x7B5\x7B6\a\x30\x2\x2\x7B6\x7B7\a\x66\x2\x2"+
		"\x7B7\x7B8\ag\x2\x2\x7B8\x7B9\ah\x2\x2\x7B9\x7D2\aj\x2\x2\x7BA\x7BB\a"+
		"\x30\x2\x2\x7BB\x7BC\a\x46\x2\x2\x7BC\x7BD\aG\x2\x2\x7BD\x7BE\aH\x2\x2"+
		"\x7BE\x7D2\aJ\x2\x2\x7BF\x7C0\a\x66\x2\x2\x7C0\x7C1\ag\x2\x2\x7C1\x7C2"+
		"\ah\x2\x2\x7C2\x7D2\aj\x2\x2\x7C3\x7C4\a\x46\x2\x2\x7C4\x7C5\aG\x2\x2"+
		"\x7C5\x7C6\aH\x2\x2\x7C6\x7D2\aJ\x2\x2\x7C7\x7C8\a\x66\x2\x2\x7C8\x7D2"+
		"\aj\x2\x2\x7C9\x7CA\a\x30\x2\x2\x7CA\x7CB\a\x66\x2\x2\x7CB\x7D2\aj\x2"+
		"\x2\x7CC\x7CD\a\x46\x2\x2\x7CD\x7D2\aJ\x2\x2\x7CE\x7CF\a\x30\x2\x2\x7CF"+
		"\x7D0\a\x46\x2\x2\x7D0\x7D2\aJ\x2\x2\x7D1\x7B5\x3\x2\x2\x2\x7D1\x7BA\x3"+
		"\x2\x2\x2\x7D1\x7BF\x3\x2\x2\x2\x7D1\x7C3\x3\x2\x2\x2\x7D1\x7C7\x3\x2"+
		"\x2\x2\x7D1\x7C9\x3\x2\x2\x2\x7D1\x7CC\x3\x2\x2\x2\x7D1\x7CE\x3\x2\x2"+
		"\x2\x7D2\x164\x3\x2\x2\x2\x7D3\x7D4\a\x30\x2\x2\x7D4\x7D5\a\x66\x2\x2"+
		"\x7D5\x7D6\ag\x2\x2\x7D6\x7D7\ah\x2\x2\x7D7\x7D8\ai\x2\x2\x7D8\x7F8\a"+
		"z\x2\x2\x7D9\x7DA\a\x30\x2\x2\x7DA\x7DB\a\x46\x2\x2\x7DB\x7DC\aG\x2\x2"+
		"\x7DC\x7DD\aH\x2\x2\x7DD\x7DE\aI\x2\x2\x7DE\x7F8\aZ\x2\x2\x7DF\x7E0\a"+
		"\x66\x2\x2\x7E0\x7E1\ag\x2\x2\x7E1\x7E2\ah\x2\x2\x7E2\x7E3\ai\x2\x2\x7E3"+
		"\x7F8\az\x2\x2\x7E4\x7E5\a\x46\x2\x2\x7E5\x7E6\aG\x2\x2\x7E6\x7E7\aH\x2"+
		"\x2\x7E7\x7E8\aI\x2\x2\x7E8\x7F8\aZ\x2\x2\x7E9\x7EA\a\x66\x2\x2\x7EA\x7EB"+
		"\ai\x2\x2\x7EB\x7F8\az\x2\x2\x7EC\x7ED\a\x30\x2\x2\x7ED\x7EE\a\x66\x2"+
		"\x2\x7EE\x7EF\ai\x2\x2\x7EF\x7F8\az\x2\x2\x7F0\x7F1\a\x46\x2\x2\x7F1\x7F2"+
		"\aI\x2\x2\x7F2\x7F8\aZ\x2\x2\x7F3\x7F4\a\x30\x2\x2\x7F4\x7F5\a\x46\x2"+
		"\x2\x7F5\x7F6\aI\x2\x2\x7F6\x7F8\aZ\x2\x2\x7F7\x7D3\x3\x2\x2\x2\x7F7\x7D9"+
		"\x3\x2\x2\x2\x7F7\x7DF\x3\x2\x2\x2\x7F7\x7E4\x3\x2\x2\x2\x7F7\x7E9\x3"+
		"\x2\x2\x2\x7F7\x7EC\x3\x2\x2\x2\x7F7\x7F0\x3\x2\x2\x2\x7F7\x7F3\x3\x2"+
		"\x2\x2\x7F8\x166\x3\x2\x2\x2\x7F9\x7FA\a\x30\x2\x2\x7FA\x7FB\a\x66\x2"+
		"\x2\x7FB\x7FC\ag\x2\x2\x7FC\x7FD\ah\x2\x2\x7FD\x816\ai\x2\x2\x7FE\x7FF"+
		"\a\x30\x2\x2\x7FF\x800\a\x46\x2\x2\x800\x801\aG\x2\x2\x801\x802\aH\x2"+
		"\x2\x802\x816\aI\x2\x2\x803\x804\a\x66\x2\x2\x804\x805\ag\x2\x2\x805\x806"+
		"\ah\x2\x2\x806\x816\ai\x2\x2\x807\x808\a\x46\x2\x2\x808\x809\aG\x2\x2"+
		"\x809\x80A\aH\x2\x2\x80A\x816\aI\x2\x2\x80B\x80C\a\x66\x2\x2\x80C\x816"+
		"\ai\x2\x2\x80D\x80E\a\x30\x2\x2\x80E\x80F\a\x66\x2\x2\x80F\x816\ai\x2"+
		"\x2\x810\x811\a\x46\x2\x2\x811\x816\aI\x2\x2\x812\x813\a\x30\x2\x2\x813"+
		"\x814\a\x46\x2\x2\x814\x816\aI\x2\x2\x815\x7F9\x3\x2\x2\x2\x815\x7FE\x3"+
		"\x2\x2\x2\x815\x803\x3\x2\x2\x2\x815\x807\x3\x2\x2\x2\x815\x80B\x3\x2"+
		"\x2\x2\x815\x80D\x3\x2\x2\x2\x815\x810\x3\x2\x2\x2\x815\x812\x3\x2\x2"+
		"\x2\x816\x818\x3\x2\x2\x2\x817\x819\x5\x3\x2\x2\x818\x817\x3\x2\x2\x2"+
		"\x819\x81A\x3\x2\x2\x2\x81A\x818\x3\x2\x2\x2\x81A\x81B\x3\x2\x2\x2\x81B"+
		"\x81D\x3\x2\x2\x2\x81C\x81E\n\x3\x2\x2\x81D\x81C\x3\x2\x2\x2\x81E\x81F"+
		"\x3\x2\x2\x2\x81F\x81D\x3\x2\x2\x2\x81F\x820\x3\x2\x2\x2\x820\x168\x3"+
		"\x2\x2\x2\x821\x822\a\x30\x2\x2\x822\x823\a\x66\x2\x2\x823\x824\ag\x2"+
		"\x2\x824\x825\ah\x2\x2\x825\x83E\a\x65\x2\x2\x826\x827\a\x30\x2\x2\x827"+
		"\x828\a\x46\x2\x2\x828\x829\aG\x2\x2\x829\x82A\aH\x2\x2\x82A\x83E\a\x45"+
		"\x2\x2\x82B\x82C\a\x66\x2\x2\x82C\x82D\ag\x2\x2\x82D\x82E\ah\x2\x2\x82E"+
		"\x83E\a\x65\x2\x2\x82F\x830\a\x46\x2\x2\x830\x831\aG\x2\x2\x831\x832\a"+
		"H\x2\x2\x832\x83E\a\x45\x2\x2\x833\x834\a\x66\x2\x2\x834\x83E\a\x65\x2"+
		"\x2\x835\x836\a\x30\x2\x2\x836\x837\a\x66\x2\x2\x837\x83E\a\x65\x2\x2"+
		"\x838\x839\a\x46\x2\x2\x839\x83E\a\x45\x2\x2\x83A\x83B\a\x30\x2\x2\x83B"+
		"\x83C\a\x46\x2\x2\x83C\x83E\a\x45\x2\x2\x83D\x821\x3\x2\x2\x2\x83D\x826"+
		"\x3\x2\x2\x2\x83D\x82B\x3\x2\x2\x2\x83D\x82F\x3\x2\x2\x2\x83D\x833\x3"+
		"\x2\x2\x2\x83D\x835\x3\x2\x2\x2\x83D\x838\x3\x2\x2\x2\x83D\x83A\x3\x2"+
		"\x2\x2\x83E\x16A\x3\x2\x2\x2\x83F\x840\a\x30\x2\x2\x840\x841\au\x2\x2"+
		"\x841\x842\am\x2\x2\x842\x843\ak\x2\x2\x843\x852\ar\x2\x2\x844\x845\a"+
		"\x30\x2\x2\x845\x846\aU\x2\x2\x846\x847\aM\x2\x2\x847\x848\aK\x2\x2\x848"+
		"\x852\aR\x2\x2\x849\x84A\au\x2\x2\x84A\x84B\am\x2\x2\x84B\x84C\ak\x2\x2"+
		"\x84C\x852\ar\x2\x2\x84D\x84E\aU\x2\x2\x84E\x84F\aM\x2\x2\x84F\x850\a"+
		"K\x2\x2\x850\x852\aR\x2\x2\x851\x83F\x3\x2\x2\x2\x851\x844\x3\x2\x2\x2"+
		"\x851\x849\x3\x2\x2\x2\x851\x84D\x3\x2\x2\x2\x852\x16C\x3\x2\x2\x2\x853"+
		"\x854\a\x30\x2\x2\x854\x855\ag\x2\x2\x855\x856\az\x2\x2\x856\x857\av\x2"+
		"\x2\x857\x858\ag\x2\x2\x858\x859\at\x2\x2\x859\x86E\ap\x2\x2\x85A\x85B"+
		"\a\x30\x2\x2\x85B\x85C\aG\x2\x2\x85C\x85D\aZ\x2\x2\x85D\x85E\aV\x2\x2"+
		"\x85E\x85F\aG\x2\x2\x85F\x860\aT\x2\x2\x860\x86E\aP\x2\x2\x861\x862\a"+
		"g\x2\x2\x862\x863\az\x2\x2\x863\x864\av\x2\x2\x864\x865\ag\x2\x2\x865"+
		"\x866\at\x2\x2\x866\x86E\ap\x2\x2\x867\x868\aG\x2\x2\x868\x869\aZ\x2\x2"+
		"\x869\x86A\aV\x2\x2\x86A\x86B\aG\x2\x2\x86B\x86C\aT\x2\x2\x86C\x86E\a"+
		"P\x2\x2\x86D\x853\x3\x2\x2\x2\x86D\x85A\x3\x2\x2\x2\x86D\x861\x3\x2\x2"+
		"\x2\x86D\x867\x3\x2\x2\x2\x86E\x16E\x3\x2\x2\x2\x86F\x870\a\x30\x2\x2"+
		"\x870\x871\a\x66\x2\x2\x871\x872\ag\x2\x2\x872\x873\ah\x2\x2\x873\x88C"+
		"\au\x2\x2\x874\x875\a\x30\x2\x2\x875\x876\a\x46\x2\x2\x876\x877\aG\x2"+
		"\x2\x877\x878\aH\x2\x2\x878\x88C\aU\x2\x2\x879\x87A\a\x66\x2\x2\x87A\x87B"+
		"\ag\x2\x2\x87B\x87C\ah\x2\x2\x87C\x88C\au\x2\x2\x87D\x87E\a\x46\x2\x2"+
		"\x87E\x87F\aG\x2\x2\x87F\x880\aH\x2\x2\x880\x88C\aU\x2\x2\x881\x882\a"+
		"\x30\x2\x2\x882\x883\a\x66\x2\x2\x883\x88C\au\x2\x2\x884\x885\a\x30\x2"+
		"\x2\x885\x886\a\x46\x2\x2\x886\x88C\aU\x2\x2\x887\x888\a\x66\x2\x2\x888"+
		"\x88C\au\x2\x2\x889\x88A\a\x46\x2\x2\x88A\x88C\aU\x2\x2\x88B\x86F\x3\x2"+
		"\x2\x2\x88B\x874\x3\x2\x2\x2\x88B\x879\x3\x2\x2\x2\x88B\x87D\x3\x2\x2"+
		"\x2\x88B\x881\x3\x2\x2\x2\x88B\x884\x3\x2\x2\x2\x88B\x887\x3\x2\x2\x2"+
		"\x88B\x889\x3\x2\x2\x2\x88C\x170\x3\x2\x2\x2\x88D\x88E\a\x30\x2\x2\x88E"+
		"\x88F\ah\x2\x2\x88F\x890\ak\x2\x2\x890\x891\an\x2\x2\x891\x892\an\x2\x2"+
		"\x892\x8A4\a\x64\x2\x2\x893\x894\a\x30\x2\x2\x894\x895\aH\x2\x2\x895\x896"+
		"\aK\x2\x2\x896\x897\aN\x2\x2\x897\x898\aN\x2\x2\x898\x8A4\a\x44\x2\x2"+
		"\x899\x89A\ah\x2\x2\x89A\x89B\ak\x2\x2\x89B\x89C\an\x2\x2\x89C\x89D\a"+
		"n\x2\x2\x89D\x8A4\a\x64\x2\x2\x89E\x89F\aH\x2\x2\x89F\x8A0\aK\x2\x2\x8A0"+
		"\x8A1\aN\x2\x2\x8A1\x8A2\aN\x2\x2\x8A2\x8A4\a\x44\x2\x2\x8A3\x88D\x3\x2"+
		"\x2\x2\x8A3\x893\x3\x2\x2\x2\x8A3\x899\x3\x2\x2\x2\x8A3\x89E\x3\x2\x2"+
		"\x2\x8A4\x172\x3\x2\x2\x2\x8A5\x8A6\a\x30\x2\x2\x8A6\x8A7\ah\x2\x2\x8A7"+
		"\x8A8\ak\x2\x2\x8A8\x8A9\an\x2\x2\x8A9\x8AA\an\x2\x2\x8AA\x8BC\ay\x2\x2"+
		"\x8AB\x8AC\a\x30\x2\x2\x8AC\x8AD\aH\x2\x2\x8AD\x8AE\aK\x2\x2\x8AE\x8AF"+
		"\aN\x2\x2\x8AF\x8B0\aN\x2\x2\x8B0\x8BC\aY\x2\x2\x8B1\x8B2\ah\x2\x2\x8B2"+
		"\x8B3\ak\x2\x2\x8B3\x8B4\an\x2\x2\x8B4\x8B5\an\x2\x2\x8B5\x8BC\ay\x2\x2"+
		"\x8B6\x8B7\aH\x2\x2\x8B7\x8B8\aK\x2\x2\x8B8\x8B9\aN\x2\x2\x8B9\x8BA\a"+
		"N\x2\x2\x8BA\x8BC\aY\x2\x2\x8BB\x8A5\x3\x2\x2\x2\x8BB\x8AB\x3\x2\x2\x2"+
		"\x8BB\x8B1\x3\x2\x2\x2\x8BB\x8B6\x3\x2\x2\x2\x8BC\x174\x3\x2\x2\x2\x8BD"+
		"\x8BE\a\x30\x2\x2\x8BE\x8BF\ao\x2\x2\x8BF\x8C0\aq\x2\x2\x8C0\x8C1\a\x66"+
		"\x2\x2\x8C1\x8C2\ag\x2\x2\x8C2\x8D4\an\x2\x2\x8C3\x8C4\a\x30\x2\x2\x8C4"+
		"\x8C5\aO\x2\x2\x8C5\x8C6\aQ\x2\x2\x8C6\x8C7\a\x46\x2\x2\x8C7\x8C8\aG\x2"+
		"\x2\x8C8\x8D4\aN\x2\x2\x8C9\x8CA\ao\x2\x2\x8CA\x8CB\aq\x2\x2\x8CB\x8CC"+
		"\a\x66\x2\x2\x8CC\x8CD\ag\x2\x2\x8CD\x8D4\an\x2\x2\x8CE\x8CF\aO\x2\x2"+
		"\x8CF\x8D0\aQ\x2\x2\x8D0\x8D1\a\x46\x2\x2\x8D1\x8D2\aG\x2\x2\x8D2\x8D4"+
		"\aN\x2\x2\x8D3\x8BD\x3\x2\x2\x2\x8D3\x8C3\x3\x2\x2\x2\x8D3\x8C9\x3\x2"+
		"\x2\x2\x8D3\x8CE\x3\x2\x2\x2\x8D4\x176\x3\x2\x2\x2\x8D5\x8D6\a\x30\x2"+
		"\x2\x8D6\x8D7\ak\x2\x2\x8D7\x8D8\ap\x2\x2\x8D8\x8D9\al\x2\x2\x8D9\x8DA"+
		"\ag\x2\x2\x8DA\x8DB\a\x65\x2\x2\x8DB\x8DC\av\x2\x2\x8DC\x8DD\aq\x2\x2"+
		"\x8DD\x8DE\ar\x2\x2\x8DE\x8FC\av\x2\x2\x8DF\x8E0\a\x30\x2\x2\x8E0\x8E1"+
		"\aK\x2\x2\x8E1\x8E2\aP\x2\x2\x8E2\x8E3\aL\x2\x2\x8E3\x8E4\aG\x2\x2\x8E4"+
		"\x8E5\a\x45\x2\x2\x8E5\x8E6\aV\x2\x2\x8E6\x8E7\aQ\x2\x2\x8E7\x8E8\aR\x2"+
		"\x2\x8E8\x8FC\aV\x2\x2\x8E9\x8EA\ak\x2\x2\x8EA\x8EB\ap\x2\x2\x8EB\x8EC"+
		"\al\x2\x2\x8EC\x8ED\ag\x2\x2\x8ED\x8EE\a\x65\x2\x2\x8EE\x8EF\av\x2\x2"+
		"\x8EF\x8F0\aq\x2\x2\x8F0\x8F1\ar\x2\x2\x8F1\x8FC\av\x2\x2\x8F2\x8F3\a"+
		"K\x2\x2\x8F3\x8F4\aP\x2\x2\x8F4\x8F5\aL\x2\x2\x8F5\x8F6\aG\x2\x2\x8F6"+
		"\x8F7\a\x45\x2\x2\x8F7\x8F8\aV\x2\x2\x8F8\x8F9\aQ\x2\x2\x8F9\x8FA\aR\x2"+
		"\x2\x8FA\x8FC\aV\x2\x2\x8FB\x8D5\x3\x2\x2\x2\x8FB\x8DF\x3\x2\x2\x2\x8FB"+
		"\x8E9\x3\x2\x2\x2\x8FB\x8F2\x3\x2\x2\x2\x8FC\x178\x3\x2\x2\x2\x8FD\x8FE"+
		"\a\x30\x2\x2\x8FE\x8FF\a\x63\x2\x2\x8FF\x900\an\x2\x2\x900\x901\ak\x2"+
		"\x2\x901\x902\ai\x2\x2\x902\x914\ap\x2\x2\x903\x904\a\x30\x2\x2\x904\x905"+
		"\a\x43\x2\x2\x905\x906\aN\x2\x2\x906\x907\aK\x2\x2\x907\x908\aI\x2\x2"+
		"\x908\x914\aP\x2\x2\x909\x90A\a\x63\x2\x2\x90A\x90B\an\x2\x2\x90B\x90C"+
		"\ak\x2\x2\x90C\x90D\ai\x2\x2\x90D\x914\ap\x2\x2\x90E\x90F\a\x43\x2\x2"+
		"\x90F\x910\aN\x2\x2\x910\x911\aK\x2\x2\x911\x912\aI\x2\x2\x912\x914\a"+
		"P\x2\x2\x913\x8FD\x3\x2\x2\x2\x913\x903\x3\x2\x2\x2\x913\x909\x3\x2\x2"+
		"\x2\x913\x90E\x3\x2\x2\x2\x914\x17A\x3\x2\x2\x2\x915\x916\a\x30\x2\x2"+
		"\x916\x917\av\x2\x2\x917\x918\at\x2\x2\x918\x919\a\x63\x2\x2\x919\x91A"+
		"\a\x65\x2\x2\x91A\x92C\ag\x2\x2\x91B\x91C\a\x30\x2\x2\x91C\x91D\aV\x2"+
		"\x2\x91D\x91E\aT\x2\x2\x91E\x91F\a\x43\x2\x2\x91F\x920\a\x45\x2\x2\x920"+
		"\x92C\aG\x2\x2\x921\x922\av\x2\x2\x922\x923\at\x2\x2\x923\x924\a\x63\x2"+
		"\x2\x924\x925\a\x65\x2\x2\x925\x92C\ag\x2\x2\x926\x927\aV\x2\x2\x927\x928"+
		"\aT\x2\x2\x928\x929\a\x43\x2\x2\x929\x92A\a\x45\x2\x2\x92A\x92C\aG\x2"+
		"\x2\x92B\x915\x3\x2\x2\x2\x92B\x91B\x3\x2\x2\x2\x92B\x921\x3\x2\x2\x2"+
		"\x92B\x926\x3\x2\x2\x2\x92C\x17C\x3\x2\x2\x2\x92D\x92E\a\x30\x2\x2\x92E"+
		"\x92F\av\x2\x2\x92F\x930\at\x2\x2\x930\x931\a\x63\x2\x2\x931\x932\a\x65"+
		"\x2\x2\x932\x933\ag\x2\x2\x933\x934\aj\x2\x2\x934\x935\ag\x2\x2\x935\x950"+
		"\az\x2\x2\x936\x937\a\x30\x2\x2\x937\x938\aV\x2\x2\x938\x939\aT\x2\x2"+
		"\x939\x93A\a\x43\x2\x2\x93A\x93B\a\x45\x2\x2\x93B\x93C\aG\x2\x2\x93C\x93D"+
		"\aJ\x2\x2\x93D\x93E\aG\x2\x2\x93E\x950\aZ\x2\x2\x93F\x940\av\x2\x2\x940"+
		"\x941\at\x2\x2\x941\x942\a\x63\x2\x2\x942\x943\a\x65\x2\x2\x943\x944\a"+
		"g\x2\x2\x944\x945\aj\x2\x2\x945\x946\ag\x2\x2\x946\x950\az\x2\x2\x947"+
		"\x948\aV\x2\x2\x948\x949\aT\x2\x2\x949\x94A\a\x43\x2\x2\x94A\x94B\a\x45"+
		"\x2\x2\x94B\x94C\aG\x2\x2\x94C\x94D\aJ\x2\x2\x94D\x94E\aG\x2\x2\x94E\x950"+
		"\aZ\x2\x2\x94F\x92D\x3\x2\x2\x2\x94F\x936\x3\x2\x2\x2\x94F\x93F\x3\x2"+
		"\x2\x2\x94F\x947\x3\x2\x2\x2\x950\x17E\x3\x2\x2\x2\x951\x952\a\x30\x2"+
		"\x2\x952\x953\at\x2\x2\x953\x954\ap\x2\x2\x954\x955\a\x66\x2\x2\x955\x956"+
		"\au\x2\x2\x956\x957\ag\x2\x2\x957\x958\ag\x2\x2\x958\x970\a\x66\x2\x2"+
		"\x959\x95A\at\x2\x2\x95A\x95B\ap\x2\x2\x95B\x95C\a\x66\x2\x2\x95C\x95D"+
		"\au\x2\x2\x95D\x95E\ag\x2\x2\x95E\x95F\ag\x2\x2\x95F\x970\a\x66\x2\x2"+
		"\x960\x961\a\x30\x2\x2\x961\x962\aT\x2\x2\x962\x963\aP\x2\x2\x963\x964"+
		"\a\x46\x2\x2\x964\x965\aU\x2\x2\x965\x966\aG\x2\x2\x966\x967\aG\x2\x2"+
		"\x967\x970\a\x46\x2\x2\x968\x969\aT\x2\x2\x969\x96A\aP\x2\x2\x96A\x96B"+
		"\a\x46\x2\x2\x96B\x96C\aU\x2\x2\x96C\x96D\aG\x2\x2\x96D\x96E\aG\x2\x2"+
		"\x96E\x970\a\x46\x2\x2\x96F\x951\x3\x2\x2\x2\x96F\x959\x3\x2\x2\x2\x96F"+
		"\x960\x3\x2\x2\x2\x96F\x968\x3\x2\x2\x2\x970\x180\x3\x2\x2\x2\x971\x972"+
		"\a\x30\x2\x2\x972\x973\ag\x2\x2\x973\x974\at\x2\x2\x974\x975\at\x2\x2"+
		"\x975\x976\aq\x2\x2\x976\x988\at\x2\x2\x977\x978\a\x30\x2\x2\x978\x979"+
		"\aG\x2\x2\x979\x97A\aT\x2\x2\x97A\x97B\aT\x2\x2\x97B\x97C\aQ\x2\x2\x97C"+
		"\x988\aT\x2\x2\x97D\x97E\ag\x2\x2\x97E\x97F\at\x2\x2\x97F\x980\at\x2\x2"+
		"\x980\x981\aq\x2\x2\x981\x988\at\x2\x2\x982\x983\aG\x2\x2\x983\x984\a"+
		"T\x2\x2\x984\x985\aT\x2\x2\x985\x986\aQ\x2\x2\x986\x988\aT\x2\x2\x987"+
		"\x971\x3\x2\x2\x2\x987\x977\x3\x2\x2\x2\x987\x97D\x3\x2\x2\x2\x987\x982"+
		"\x3\x2\x2\x2\x988\x182\x3\x2\x2\x2\x989\x98A\a\x30\x2\x2\x98A\x98B\ak"+
		"\x2\x2\x98B\x98C\ap\x2\x2\x98C\x98D\a\x65\x2\x2\x98D\x98E\an\x2\x2\x98E"+
		"\x98F\aw\x2\x2\x98F\x990\a\x66\x2\x2\x990\x991\ag\x2\x2\x991\x992\a\x64"+
		"\x2\x2\x992\x993\ak\x2\x2\x993\x9FC\ap\x2\x2\x994\x995\ak\x2\x2\x995\x996"+
		"\ap\x2\x2\x996\x997\a\x65\x2\x2\x997\x998\an\x2\x2\x998\x999\aw\x2\x2"+
		"\x999\x99A\a\x66\x2\x2\x99A\x99B\ag\x2\x2\x99B\x99C\a\x64\x2\x2\x99C\x99D"+
		"\ak\x2\x2\x99D\x9FC\ap\x2\x2\x99E\x99F\a\x30\x2\x2\x99F\x9A0\aK\x2\x2"+
		"\x9A0\x9A1\aP\x2\x2\x9A1\x9A2\a\x45\x2\x2\x9A2\x9A3\aN\x2\x2\x9A3\x9A4"+
		"\aW\x2\x2\x9A4\x9A5\a\x46\x2\x2\x9A5\x9A6\aG\x2\x2\x9A6\x9A7\a\x44\x2"+
		"\x2\x9A7\x9A8\aK\x2\x2\x9A8\x9FC\aP\x2\x2\x9A9\x9AA\aK\x2\x2\x9AA\x9AB"+
		"\aP\x2\x2\x9AB\x9AC\a\x45\x2\x2\x9AC\x9AD\aN\x2\x2\x9AD\x9AE\aW\x2\x2"+
		"\x9AE\x9AF\a\x46\x2\x2\x9AF\x9B0\aG\x2\x2\x9B0\x9B1\a\x44\x2\x2\x9B1\x9B2"+
		"\aK\x2\x2\x9B2\x9FC\aP\x2\x2\x9B3\x9B4\a\x30\x2\x2\x9B4\x9B5\ak\x2\x2"+
		"\x9B5\x9B6\ap\x2\x2\x9B6\x9B7\a\x65\x2\x2\x9B7\x9B8\an\x2\x2\x9B8\x9B9"+
		"\aw\x2\x2\x9B9\x9BA\a\x66\x2\x2\x9BA\x9BB\ag\x2\x2\x9BB\x9BC\a\x61\x2"+
		"\x2\x9BC\x9BD\a\x64\x2\x2\x9BD\x9BE\ak\x2\x2\x9BE\x9FC\ap\x2\x2\x9BF\x9C0"+
		"\ak\x2\x2\x9C0\x9C1\ap\x2\x2\x9C1\x9C2\a\x65\x2\x2\x9C2\x9C3\an\x2\x2"+
		"\x9C3\x9C4\aw\x2\x2\x9C4\x9C5\a\x66\x2\x2\x9C5\x9C6\ag\x2\x2\x9C6\x9C7"+
		"\a\x61\x2\x2\x9C7\x9C8\a\x64\x2\x2\x9C8\x9C9\ak\x2\x2\x9C9\x9FC\ap\x2"+
		"\x2\x9CA\x9CB\a\x30\x2\x2\x9CB\x9CC\aK\x2\x2\x9CC\x9CD\aP\x2\x2\x9CD\x9CE"+
		"\a\x45\x2\x2\x9CE\x9CF\aN\x2\x2\x9CF\x9D0\aW\x2\x2\x9D0\x9D1\a\x46\x2"+
		"\x2\x9D1\x9D2\aG\x2\x2\x9D2\x9D3\a\x61\x2\x2\x9D3\x9D4\a\x44\x2\x2\x9D4"+
		"\x9D5\aK\x2\x2\x9D5\x9FC\aP\x2\x2\x9D6\x9D7\aK\x2\x2\x9D7\x9D8\aP\x2\x2"+
		"\x9D8\x9D9\a\x45\x2\x2\x9D9\x9DA\aN\x2\x2\x9DA\x9DB\aW\x2\x2\x9DB\x9DC"+
		"\a\x46\x2\x2\x9DC\x9DD\aG\x2\x2\x9DD\x9DE\a\x61\x2\x2\x9DE\x9DF\a\x44"+
		"\x2\x2\x9DF\x9E0\aK\x2\x2\x9E0\x9FC\aP\x2\x2\x9E1\x9E2\a\x30\x2\x2\x9E2"+
		"\x9E3\ak\x2\x2\x9E3\x9E4\ap\x2\x2\x9E4\x9E5\a\x65\x2\x2\x9E5\x9E6\a\x64"+
		"\x2\x2\x9E6\x9E7\ak\x2\x2\x9E7\x9FC\ap\x2\x2\x9E8\x9E9\ak\x2\x2\x9E9\x9EA"+
		"\ap\x2\x2\x9EA\x9EB\a\x65\x2\x2\x9EB\x9EC\a\x64\x2\x2\x9EC\x9ED\ak\x2"+
		"\x2\x9ED\x9FC\ap\x2\x2\x9EE\x9EF\a\x30\x2\x2\x9EF\x9F0\aK\x2\x2\x9F0\x9F1"+
		"\aP\x2\x2\x9F1\x9F2\a\x45\x2\x2\x9F2\x9F3\a\x44\x2\x2\x9F3\x9F4\aK\x2"+
		"\x2\x9F4\x9FC\aP\x2\x2\x9F5\x9F6\aK\x2\x2\x9F6\x9F7\aP\x2\x2\x9F7\x9F8"+
		"\a\x45\x2\x2\x9F8\x9F9\a\x44\x2\x2\x9F9\x9FA\aK\x2\x2\x9FA\x9FC\aP\x2"+
		"\x2\x9FB\x989\x3\x2\x2\x2\x9FB\x994\x3\x2\x2\x2\x9FB\x99E\x3\x2\x2\x2"+
		"\x9FB\x9A9\x3\x2\x2\x2\x9FB\x9B3\x3\x2\x2\x2\x9FB\x9BF\x3\x2\x2\x2\x9FB"+
		"\x9CA\x3\x2\x2\x2\x9FB\x9D6\x3\x2\x2\x2\x9FB\x9E1\x3\x2\x2\x2\x9FB\x9E8"+
		"\x3\x2\x2\x2\x9FB\x9EE\x3\x2\x2\x2\x9FB\x9F5\x3\x2\x2\x2\x9FC\x184\x3"+
		"\x2\x2\x2\x9FD\x9FE\a\x30\x2\x2\x9FE\x9FF\a\x65\x2\x2\x9FF\xA00\aq\x2"+
		"\x2\xA00\xA01\ao\x2\x2\xA01\xA02\ar\x2\x2\xA02\xA03\a\x63\x2\x2\xA03\xA04"+
		"\at\x2\x2\xA04\xA05\ag\x2\x2\xA05\xA06\a\x64\x2\x2\xA06\xA07\ak\x2\x2"+
		"\xA07\xA28\ap\x2\x2\xA08\xA09\a\x65\x2\x2\xA09\xA0A\aq\x2\x2\xA0A\xA0B"+
		"\ao\x2\x2\xA0B\xA0C\ar\x2\x2\xA0C\xA0D\a\x63\x2\x2\xA0D\xA0E\at\x2\x2"+
		"\xA0E\xA0F\ag\x2\x2\xA0F\xA10\a\x64\x2\x2\xA10\xA11\ak\x2\x2\xA11\xA28"+
		"\ap\x2\x2\xA12\xA13\a\x30\x2\x2\xA13\xA14\a\x45\x2\x2\xA14\xA15\aQ\x2"+
		"\x2\xA15\xA16\aO\x2\x2\xA16\xA17\aR\x2\x2\xA17\xA18\a\x43\x2\x2\xA18\xA19"+
		"\aT\x2\x2\xA19\xA1A\aG\x2\x2\xA1A\xA1B\a\x44\x2\x2\xA1B\xA1C\aK\x2\x2"+
		"\xA1C\xA28\aP\x2\x2\xA1D\xA1E\a\x45\x2\x2\xA1E\xA1F\aQ\x2\x2\xA1F\xA20"+
		"\aO\x2\x2\xA20\xA21\aR\x2\x2\xA21\xA22\a\x43\x2\x2\xA22\xA23\aT\x2\x2"+
		"\xA23\xA24\aG\x2\x2\xA24\xA25\a\x44\x2\x2\xA25\xA26\aK\x2\x2\xA26\xA28"+
		"\aP\x2\x2\xA27\x9FD\x3\x2\x2\x2\xA27\xA08\x3\x2\x2\x2\xA27\xA12\x3\x2"+
		"\x2\x2\xA27\xA1D\x3\x2\x2\x2\xA28\x186\x3\x2\x2\x2\xA29\xA2A\a|\x2\x2"+
		"\xA2A\xA2B\az\x2\x2\xA2B\xA2C\a\x64\x2\x2\xA2C\xA2D\a\x63\x2\x2\xA2D\xA2E"+
		"\au\x2\x2\xA2E\xA2F\ak\x2\x2\xA2F\xA48\a\x65\x2\x2\xA30\xA31\a\\\x2\x2"+
		"\xA31\xA32\aZ\x2\x2\xA32\xA33\a\x44\x2\x2\xA33\xA34\a\x43\x2\x2\xA34\xA35"+
		"\aU\x2\x2\xA35\xA36\aK\x2\x2\xA36\xA48\a\x45\x2\x2\xA37\xA38\a\x30\x2"+
		"\x2\xA38\xA39\a|\x2\x2\xA39\xA3A\az\x2\x2\xA3A\xA3B\a\x64\x2\x2\xA3B\xA3C"+
		"\a\x63\x2\x2\xA3C\xA3D\au\x2\x2\xA3D\xA3E\ak\x2\x2\xA3E\xA48\a\x65\x2"+
		"\x2\xA3F\xA40\a\x30\x2\x2\xA40\xA41\a\\\x2\x2\xA41\xA42\aZ\x2\x2\xA42"+
		"\xA43\a\x44\x2\x2\xA43\xA44\a\x43\x2\x2\xA44\xA45\aU\x2\x2\xA45\xA46\a"+
		"K\x2\x2\xA46\xA48\a\x45\x2\x2\xA47\xA29\x3\x2\x2\x2\xA47\xA30\x3\x2\x2"+
		"\x2\xA47\xA37\x3\x2\x2\x2\xA47\xA3F\x3\x2\x2\x2\xA48\x188\x3\x2\x2\x2"+
		"\xA49\xA4A\a\x30\x2\x2\xA4A\xA4B\ao\x2\x2\xA4B\xA4C\a\x63\x2\x2\xA4C\xA4D"+
		"\a\x65\x2\x2\xA4D\xA4E\at\x2\x2\xA4E\xA60\aq\x2\x2\xA4F\xA50\a\x30\x2"+
		"\x2\xA50\xA51\aO\x2\x2\xA51\xA52\a\x43\x2\x2\xA52\xA53\a\x45\x2\x2\xA53"+
		"\xA54\aT\x2\x2\xA54\xA60\aQ\x2\x2\xA55\xA56\ao\x2\x2\xA56\xA57\a\x63\x2"+
		"\x2\xA57\xA58\a\x65\x2\x2\xA58\xA59\at\x2\x2\xA59\xA60\aq\x2\x2\xA5A\xA5B"+
		"\aO\x2\x2\xA5B\xA5C\a\x43\x2\x2\xA5C\xA5D\a\x45\x2\x2\xA5D\xA5E\aT\x2"+
		"\x2\xA5E\xA60\aQ\x2\x2\xA5F\xA49\x3\x2\x2\x2\xA5F\xA4F\x3\x2\x2\x2\xA5F"+
		"\xA55\x3\x2\x2\x2\xA5F\xA5A\x3\x2\x2\x2\xA60\x18A\x3\x2\x2\x2\xA61\xA62"+
		"\a\x30\x2\x2\xA62\xA63\ag\x2\x2\xA63\xA64\ap\x2\x2\xA64\xA65\a\x66\x2"+
		"\x2\xA65\xA76\ao\x2\x2\xA66\xA67\a\x30\x2\x2\xA67\xA68\aG\x2\x2\xA68\xA69"+
		"\aP\x2\x2\xA69\xA6A\a\x46\x2\x2\xA6A\xA76\aO\x2\x2\xA6B\xA6C\a\x30\x2"+
		"\x2\xA6C\xA6D\ao\x2\x2\xA6D\xA6E\ag\x2\x2\xA6E\xA6F\ap\x2\x2\xA6F\xA76"+
		"\a\x66\x2\x2\xA70\xA71\a\x30\x2\x2\xA71\xA72\aO\x2\x2\xA72\xA73\aG\x2"+
		"\x2\xA73\xA74\aP\x2\x2\xA74\xA76\a\x46\x2\x2\xA75\xA61\x3\x2\x2\x2\xA75"+
		"\xA66\x3\x2\x2\x2\xA75\xA6B\x3\x2\x2\x2\xA75\xA70\x3\x2\x2\x2\xA76\x18C"+
		"\x3\x2\x2\x2\xA77\xA78\a\x30\x2\x2\xA78\xA79\ar\x2\x2\xA79\xA7A\at\x2"+
		"\x2\xA7A\xA7B\aq\x2\x2\xA7B\xA82\a\x65\x2\x2\xA7C\xA7D\a\x30\x2\x2\xA7D"+
		"\xA7E\aR\x2\x2\xA7E\xA7F\aT\x2\x2\xA7F\xA80\aQ\x2\x2\xA80\xA82\a\x45\x2"+
		"\x2\xA81\xA77\x3\x2\x2\x2\xA81\xA7C\x3\x2\x2\x2\xA82\x18E\x3\x2\x2\x2"+
		"\xA83\xA84\a\x30\x2\x2\xA84\xA85\ag\x2\x2\xA85\xA86\ap\x2\x2\xA86\xA87"+
		"\a\x66\x2\x2\xA87\xA98\ar\x2\x2\xA88\xA89\a\x30\x2\x2\xA89\xA8A\aG\x2"+
		"\x2\xA8A\xA8B\aP\x2\x2\xA8B\xA8C\a\x46\x2\x2\xA8C\xA98\aR\x2\x2\xA8D\xA8E"+
		"\a\x30\x2\x2\xA8E\xA8F\ar\x2\x2\xA8F\xA90\ag\x2\x2\xA90\xA91\ap\x2\x2"+
		"\xA91\xA98\a\x66\x2\x2\xA92\xA93\a\x30\x2\x2\xA93\xA94\aR\x2\x2\xA94\xA95"+
		"\aG\x2\x2\xA95\xA96\aP\x2\x2\xA96\xA98\a\x46\x2\x2\xA97\xA83\x3\x2\x2"+
		"\x2\xA97\xA88\x3\x2\x2\x2\xA97\xA8D\x3\x2\x2\x2\xA97\xA92\x3\x2\x2\x2"+
		"\xA98\x190\x3\x2\x2\x2\xA99\xA9A\a\x30\x2\x2\xA9A\xA9B\an\x2\x2\xA9B\xA9C"+
		"\aq\x2\x2\xA9C\xA9D\aq\x2\x2\xA9D\xAA4\ar\x2\x2\xA9E\xA9F\a\x30\x2\x2"+
		"\xA9F\xAA0\aN\x2\x2\xAA0\xAA1\aQ\x2\x2\xAA1\xAA2\aQ\x2\x2\xAA2\xAA4\a"+
		"R\x2\x2\xAA3\xA99\x3\x2\x2\x2\xAA3\xA9E\x3\x2\x2\x2\xAA4\x192\x3\x2\x2"+
		"\x2\xAA5\xAA6\a\x30\x2\x2\xAA6\xAA7\ag\x2\x2\xAA7\xAA8\ap\x2\x2\xAA8\xAA9"+
		"\a\x66\x2\x2\xAA9\xABA\an\x2\x2\xAAA\xAAB\a\x30\x2\x2\xAAB\xAAC\aG\x2"+
		"\x2\xAAC\xAAD\aP\x2\x2\xAAD\xAAE\a\x46\x2\x2\xAAE\xABA\aN\x2\x2\xAAF\xAB0"+
		"\a\x30\x2\x2\xAB0\xAB1\an\x2\x2\xAB1\xAB2\ag\x2\x2\xAB2\xAB3\ap\x2\x2"+
		"\xAB3\xABA\a\x66\x2\x2\xAB4\xAB5\a\x30\x2\x2\xAB5\xAB6\aN\x2\x2\xAB6\xAB7"+
		"\aG\x2\x2\xAB7\xAB8\aP\x2\x2\xAB8\xABA\a\x46\x2\x2\xAB9\xAA5\x3\x2\x2"+
		"\x2\xAB9\xAAA\x3\x2\x2\x2\xAB9\xAAF\x3\x2\x2\x2\xAB9\xAB4\x3\x2\x2\x2"+
		"\xABA\x194\x3\x2\x2\x2\xABB\xABC\a\x30\x2\x2\xABC\xABD\at\x2\x2\xABD\xABE"+
		"\ag\x2\x2\xABE\xABF\ar\x2\x2\xABF\xAC0\ag\x2\x2\xAC0\xAC1\a\x63\x2\x2"+
		"\xAC1\xACA\av\x2\x2\xAC2\xAC3\a\x30\x2\x2\xAC3\xAC4\aT\x2\x2\xAC4\xAC5"+
		"\aG\x2\x2\xAC5\xAC6\aR\x2\x2\xAC6\xAC7\aG\x2\x2\xAC7\xAC8\a\x43\x2\x2"+
		"\xAC8\xACA\aV\x2\x2\xAC9\xABB\x3\x2\x2\x2\xAC9\xAC2\x3\x2\x2\x2\xACA\x196"+
		"\x3\x2\x2\x2\xACB\xACC\a\x30\x2\x2\xACC\xACD\aw\x2\x2\xACD\xACE\ap\x2"+
		"\x2\xACE\xACF\av\x2\x2\xACF\xAD0\ak\x2\x2\xAD0\xAD8\an\x2\x2\xAD1\xAD2"+
		"\a\x30\x2\x2\xAD2\xAD3\aW\x2\x2\xAD3\xAD4\aP\x2\x2\xAD4\xAD5\aV\x2\x2"+
		"\xAD5\xAD6\aK\x2\x2\xAD6\xAD8\aN\x2\x2\xAD7\xACB\x3\x2\x2\x2\xAD7\xAD1"+
		"\x3\x2\x2\x2\xAD8\x198\x3\x2\x2\x2\xAD9\xADA\a\x30\x2\x2\xADA\xADB\ay"+
		"\x2\x2\xADB\xADC\aj\x2\x2\xADC\xADD\ak\x2\x2\xADD\xADE\an\x2\x2\xADE\xAE6"+
		"\ag\x2\x2\xADF\xAE0\a\x30\x2\x2\xAE0\xAE1\aY\x2\x2\xAE1\xAE2\aJ\x2\x2"+
		"\xAE2\xAE3\aK\x2\x2\xAE3\xAE4\aN\x2\x2\xAE4\xAE6\aG\x2\x2\xAE5\xAD9\x3"+
		"\x2\x2\x2\xAE5\xADF\x3\x2\x2\x2\xAE6\x19A\x3\x2\x2\x2\xAE7\xAE8\a\x30"+
		"\x2\x2\xAE8\xAE9\ag\x2\x2\xAE9\xAEA\ap\x2\x2\xAEA\xAEB\a\x66\x2\x2\xAEB"+
		"\xAFC\ay\x2\x2\xAEC\xAED\a\x30\x2\x2\xAED\xAEE\aG\x2\x2\xAEE\xAEF\aP\x2"+
		"\x2\xAEF\xAF0\a\x46\x2\x2\xAF0\xAFC\aY\x2\x2\xAF1\xAF2\a\x30\x2\x2\xAF2"+
		"\xAF3\ay\x2\x2\xAF3\xAF4\ag\x2\x2\xAF4\xAF5\ap\x2\x2\xAF5\xAFC\a\x66\x2"+
		"\x2\xAF6\xAF7\a\x30\x2\x2\xAF7\xAF8\aY\x2\x2\xAF8\xAF9\aG\x2\x2\xAF9\xAFA"+
		"\aP\x2\x2\xAFA\xAFC\a\x46\x2\x2\xAFB\xAE7\x3\x2\x2\x2\xAFB\xAEC\x3\x2"+
		"\x2\x2\xAFB\xAF1\x3\x2\x2\x2\xAFB\xAF6\x3\x2\x2\x2\xAFC\x19C\x3\x2\x2"+
		"\x2\xAFD\xAFE\a\x30\x2\x2\xAFE\xAFF\ak\x2\x2\xAFF\xB08\ah\x2\x2\xB00\xB01"+
		"\a\x30\x2\x2\xB01\xB02\aK\x2\x2\xB02\xB08\aH\x2\x2\xB03\xB04\ak\x2\x2"+
		"\xB04\xB08\ah\x2\x2\xB05\xB06\aK\x2\x2\xB06\xB08\aH\x2\x2\xB07\xAFD\x3"+
		"\x2\x2\x2\xB07\xB00\x3\x2\x2\x2\xB07\xB03\x3\x2\x2\x2\xB07\xB05\x3\x2"+
		"\x2\x2\xB08\x19E\x3\x2\x2\x2\xB09\xB0A\a\x30\x2\x2\xB0A\xB0B\ak\x2\x2"+
		"\xB0B\xB0C\ah\x2\x2\xB0C\xB0D\aw\x2\x2\xB0D\xB0E\au\x2\x2\xB0E\xB0F\a"+
		"g\x2\x2\xB0F\xB24\a\x66\x2\x2\xB10\xB11\a\x30\x2\x2\xB11\xB12\aK\x2\x2"+
		"\xB12\xB13\aH\x2\x2\xB13\xB14\aW\x2\x2\xB14\xB15\aU\x2\x2\xB15\xB16\a"+
		"G\x2\x2\xB16\xB24\a\x46\x2\x2\xB17\xB18\ak\x2\x2\xB18\xB19\ah\x2\x2\xB19"+
		"\xB1A\aw\x2\x2\xB1A\xB1B\au\x2\x2\xB1B\xB1C\ag\x2\x2\xB1C\xB24\a\x66\x2"+
		"\x2\xB1D\xB1E\aK\x2\x2\xB1E\xB1F\aH\x2\x2\xB1F\xB20\aW\x2\x2\xB20\xB21"+
		"\aU\x2\x2\xB21\xB22\aG\x2\x2\xB22\xB24\a\x46\x2\x2\xB23\xB09\x3\x2\x2"+
		"\x2\xB23\xB10\x3\x2\x2\x2\xB23\xB17\x3\x2\x2\x2\xB23\xB1D\x3\x2\x2\x2"+
		"\xB24\x1A0\x3\x2\x2\x2\xB25\xB26\a\x30\x2\x2\xB26\xB27\ak\x2\x2\xB27\xB28"+
		"\ah\x2\x2\xB28\xB29\ap\x2\x2\xB29\xB2A\aw\x2\x2\xB2A\xB2B\au\x2\x2\xB2B"+
		"\xB2C\ag\x2\x2\xB2C\xB44\a\x66\x2\x2\xB2D\xB2E\a\x30\x2\x2\xB2E\xB2F\a"+
		"K\x2\x2\xB2F\xB30\aH\x2\x2\xB30\xB31\aP\x2\x2\xB31\xB32\aW\x2\x2\xB32"+
		"\xB33\aU\x2\x2\xB33\xB34\aG\x2\x2\xB34\xB44\a\x46\x2\x2\xB35\xB36\ak\x2"+
		"\x2\xB36\xB37\ah\x2\x2\xB37\xB38\ap\x2\x2\xB38\xB39\aw\x2\x2\xB39\xB3A"+
		"\au\x2\x2\xB3A\xB3B\ag\x2\x2\xB3B\xB44\a\x66\x2\x2\xB3C\xB3D\aK\x2\x2"+
		"\xB3D\xB3E\aH\x2\x2\xB3E\xB3F\aP\x2\x2\xB3F\xB40\aW\x2\x2\xB40\xB41\a"+
		"U\x2\x2\xB41\xB42\aG\x2\x2\xB42\xB44\a\x46\x2\x2\xB43\xB25\x3\x2\x2\x2"+
		"\xB43\xB2D\x3\x2\x2\x2\xB43\xB35\x3\x2\x2\x2\xB43\xB3C\x3\x2\x2\x2\xB44"+
		"\x1A2\x3\x2\x2\x2\xB45\xB46\a\x30\x2\x2\xB46\xB47\ag\x2\x2\xB47\xB48\a"+
		"n\x2\x2\xB48\xB49\ak\x2\x2\xB49\xB50\ah\x2\x2\xB4A\xB4B\a\x30\x2\x2\xB4B"+
		"\xB4C\aG\x2\x2\xB4C\xB4D\aN\x2\x2\xB4D\xB4E\aK\x2\x2\xB4E\xB50\aH\x2\x2"+
		"\xB4F\xB45\x3\x2\x2\x2\xB4F\xB4A\x3\x2\x2\x2\xB50\x1A4\x3\x2\x2\x2\xB51"+
		"\xB52\a\x30\x2\x2\xB52\xB53\ag\x2\x2\xB53\xB54\an\x2\x2\xB54\xB55\au\x2"+
		"\x2\xB55\xB5C\ag\x2\x2\xB56\xB57\a\x30\x2\x2\xB57\xB58\aG\x2\x2\xB58\xB59"+
		"\aN\x2\x2\xB59\xB5A\aU\x2\x2\xB5A\xB5C\aG\x2\x2\xB5B\xB51\x3\x2\x2\x2"+
		"\xB5B\xB56\x3\x2\x2\x2\xB5C\x1A6\x3\x2\x2\x2\xB5D\xB5E\a\x30\x2\x2\xB5E"+
		"\xB5F\ag\x2\x2\xB5F\xB60\ap\x2\x2\xB60\xB61\a\x66\x2\x2\xB61\xB62\ak\x2"+
		"\x2\xB62\xB6A\ah\x2\x2\xB63\xB64\a\x30\x2\x2\xB64\xB65\aG\x2\x2\xB65\xB66"+
		"\aP\x2\x2\xB66\xB67\a\x46\x2\x2\xB67\xB68\aK\x2\x2\xB68\xB6A\aH\x2\x2"+
		"\xB69\xB5D\x3\x2\x2\x2\xB69\xB63\x3\x2\x2\x2\xB6A\x1A8\x3\x2\x2\x2\xB6B"+
		"\xB6C\a\x30\x2\x2\xB6C\xB6D\ah\x2\x2\xB6D\xB6E\aq\x2\x2\xB6E\xB7A\at\x2"+
		"\x2\xB6F\xB70\a\x30\x2\x2\xB70\xB71\aH\x2\x2\xB71\xB72\aQ\x2\x2\xB72\xB7A"+
		"\aT\x2\x2\xB73\xB74\ah\x2\x2\xB74\xB75\aq\x2\x2\xB75\xB7A\at\x2\x2\xB76"+
		"\xB77\aH\x2\x2\xB77\xB78\aQ\x2\x2\xB78\xB7A\aT\x2\x2\xB79\xB6B\x3\x2\x2"+
		"\x2\xB79\xB6F\x3\x2\x2\x2\xB79\xB73\x3\x2\x2\x2\xB79\xB76\x3\x2\x2\x2"+
		"\xB7A\x1AA\x3\x2\x2\x2\xB7B\xB7C\a\x30\x2\x2\xB7C\xB7D\av\x2\x2\xB7D\xB86"+
		"\aq\x2\x2\xB7E\xB7F\a\x30\x2\x2\xB7F\xB80\aV\x2\x2\xB80\xB86\aQ\x2\x2"+
		"\xB81\xB82\av\x2\x2\xB82\xB86\aq\x2\x2\xB83\xB84\aV\x2\x2\xB84\xB86\a"+
		"Q\x2\x2\xB85\xB7B\x3\x2\x2\x2\xB85\xB7E\x3\x2\x2\x2\xB85\xB81\x3\x2\x2"+
		"\x2\xB85\xB83\x3\x2\x2\x2\xB86\x1AC\x3\x2\x2\x2\xB87\xB88\a\x30\x2\x2"+
		"\xB88\xB89\au\x2\x2\xB89\xB8A\av\x2\x2\xB8A\xB8B\ag\x2\x2\xB8B\xB9A\a"+
		"r\x2\x2\xB8C\xB8D\a\x30\x2\x2\xB8D\xB8E\aU\x2\x2\xB8E\xB8F\aV\x2\x2\xB8F"+
		"\xB90\aG\x2\x2\xB90\xB9A\aR\x2\x2\xB91\xB92\au\x2\x2\xB92\xB93\av\x2\x2"+
		"\xB93\xB94\ag\x2\x2\xB94\xB9A\ar\x2\x2\xB95\xB96\aU\x2\x2\xB96\xB97\a"+
		"V\x2\x2\xB97\xB98\aG\x2\x2\xB98\xB9A\aR\x2\x2\xB99\xB87\x3\x2\x2\x2\xB99"+
		"\xB8C\x3\x2\x2\x2\xB99\xB91\x3\x2\x2\x2\xB99\xB95\x3\x2\x2\x2\xB9A\x1AE"+
		"\x3\x2\x2\x2\xB9B\xB9C\a\x30\x2\x2\xB9C\xB9D\ap\x2\x2\xB9D\xB9E\ag\x2"+
		"\x2\xB9E\xB9F\az\x2\x2\xB9F\xBA6\av\x2\x2\xBA0\xBA1\a\x30\x2\x2\xBA1\xBA2"+
		"\aP\x2\x2\xBA2\xBA3\aG\x2\x2\xBA3\xBA4\aZ\x2\x2\xBA4\xBA6\aV\x2\x2\xBA5"+
		"\xB9B\x3\x2\x2\x2\xBA5\xBA0\x3\x2\x2\x2\xBA6\x1B0\x3\x2\x2\x2\xBA7\xBA8"+
		"\ap\x2\x2\xBA8\xBA9\ag\x2\x2\xBA9\xBAA\az\x2\x2\xBAA\xBB0\av\x2\x2\xBAB"+
		"\xBAC\aP\x2\x2\xBAC\xBAD\aG\x2\x2\xBAD\xBAE\aZ\x2\x2\xBAE\xBB0\aV\x2\x2"+
		"\xBAF\xBA7\x3\x2\x2\x2\xBAF\xBAB\x3\x2\x2\x2\xBB0\x1B2\x3\x2\x2\x2\xBB1"+
		"\xBB2\a\x30\x2\x2\xBB2\xBB3\a\x64\x2\x2\xBB3\xBB4\at\x2\x2\xBB4\xBB5\a"+
		"g\x2\x2\xBB5\xBB6\a\x63\x2\x2\xBB6\xBBE\am\x2\x2\xBB7\xBB8\a\x30\x2\x2"+
		"\xBB8\xBB9\a\x44\x2\x2\xBB9\xBBA\aT\x2\x2\xBBA\xBBB\aG\x2\x2\xBBB\xBBC"+
		"\a\x43\x2\x2\xBBC\xBBE\aM\x2\x2\xBBD\xBB1\x3\x2\x2\x2\xBBD\xBB7\x3\x2"+
		"\x2\x2\xBBE\x1B4\x3\x2\x2\x2\xBBF\xBC0\a\x30\x2\x2\xBC0\xBC1\a\x65\x2"+
		"\x2\xBC1\xBC2\aq\x2\x2\xBC2\xBC3\ap\x2\x2\xBC3\xBC4\av\x2\x2\xBC4\xBC5"+
		"\ak\x2\x2\xBC5\xBC6\ap\x2\x2\xBC6\xBC7\aw\x2\x2\xBC7\xBD2\ag\x2\x2\xBC8"+
		"\xBC9\a\x30\x2\x2\xBC9\xBCA\a\x45\x2\x2\xBCA\xBCB\aQ\x2\x2\xBCB\xBCC\a"+
		"P\x2\x2\xBCC\xBCD\aV\x2\x2\xBCD\xBCE\aK\x2\x2\xBCE\xBCF\aP\x2\x2\xBCF"+
		"\xBD0\aW\x2\x2\xBD0\xBD2\aG\x2\x2\xBD1\xBBF\x3\x2\x2\x2\xBD1\xBC8\x3\x2"+
		"\x2\x2\xBD2\x1B6\x3\x2\x2\x2\xBD3\xBD4\a\x30\x2\x2\xBD4\xBD5\ao\x2\x2"+
		"\xBD5\xBD6\aq\x2\x2\xBD6\xBD7\a\x66\x2\x2\xBD7\xBD8\aw\x2\x2\xBD8\xBD9"+
		"\an\x2\x2\xBD9\xC04\ag\x2\x2\xBDA\xBDB\a\x30\x2\x2\xBDB\xBDC\aO\x2\x2"+
		"\xBDC\xBDD\aQ\x2\x2\xBDD\xBDE\a\x46\x2\x2\xBDE\xBDF\aW\x2\x2\xBDF\xBE0"+
		"\aN\x2\x2\xBE0\xC04\aG\x2\x2\xBE1\xBE2\ao\x2\x2\xBE2\xBE3\aq\x2\x2\xBE3"+
		"\xBE4\a\x66\x2\x2\xBE4\xBE5\aw\x2\x2\xBE5\xBE6\an\x2\x2\xBE6\xC04\ag\x2"+
		"\x2\xBE7\xBE8\aO\x2\x2\xBE8\xBE9\aQ\x2\x2\xBE9\xBEA\a\x46\x2\x2\xBEA\xBEB"+
		"\aW\x2\x2\xBEB\xBEC\aN\x2\x2\xBEC\xC04\aG\x2\x2\xBED\xBEE\a\x30\x2\x2"+
		"\xBEE\xBEF\au\x2\x2\xBEF\xBF0\a\x65\x2\x2\xBF0\xBF1\aq\x2\x2\xBF1\xBF2"+
		"\ar\x2\x2\xBF2\xC04\ag\x2\x2\xBF3\xBF4\a\x30\x2\x2\xBF4\xBF5\aU\x2\x2"+
		"\xBF5\xBF6\a\x45\x2\x2\xBF6\xBF7\aQ\x2\x2\xBF7\xBF8\aR\x2\x2\xBF8\xC04"+
		"\aG\x2\x2\xBF9\xBFA\au\x2\x2\xBFA\xBFB\a\x65\x2\x2\xBFB\xBFC\aq\x2\x2"+
		"\xBFC\xBFD\ar\x2\x2\xBFD\xC04\ag\x2\x2\xBFE\xBFF\aU\x2\x2\xBFF\xC00\a"+
		"\x45\x2\x2\xC00\xC01\aQ\x2\x2\xC01\xC02\aR\x2\x2\xC02\xC04\aG\x2\x2\xC03"+
		"\xBD3\x3\x2\x2\x2\xC03\xBDA\x3\x2\x2\x2\xC03\xBE1\x3\x2\x2\x2\xC03\xBE7"+
		"\x3\x2\x2\x2\xC03\xBED\x3\x2\x2\x2\xC03\xBF3\x3\x2\x2\x2\xC03\xBF9\x3"+
		"\x2\x2\x2\xC03\xBFE\x3\x2\x2\x2\xC04\x1B8\x3\x2\x2\x2\xC05\xC06\a\x30"+
		"\x2\x2\xC06\xC07\ag\x2\x2\xC07\xC08\ap\x2\x2\xC08\xC09\a\x66\x2\x2\xC09"+
		"\xC0A\ao\x2\x2\xC0A\xC0B\aq\x2\x2\xC0B\xC0C\a\x66\x2\x2\xC0C\xC0D\aw\x2"+
		"\x2\xC0D\xC0E\an\x2\x2\xC0E\xC96\ag\x2\x2\xC0F\xC10\a\x30\x2\x2\xC10\xC11"+
		"\aG\x2\x2\xC11\xC12\aP\x2\x2\xC12\xC13\a\x46\x2\x2\xC13\xC14\aO\x2\x2"+
		"\xC14\xC15\aQ\x2\x2\xC15\xC16\a\x46\x2\x2\xC16\xC17\aW\x2\x2\xC17\xC18"+
		"\aN\x2\x2\xC18\xC96\aG\x2\x2\xC19\xC1A\ag\x2\x2\xC1A\xC1B\ap\x2\x2\xC1B"+
		"\xC1C\a\x66\x2\x2\xC1C\xC1D\ao\x2\x2\xC1D\xC1E\aq\x2\x2\xC1E\xC1F\a\x66"+
		"\x2\x2\xC1F\xC20\aw\x2\x2\xC20\xC21\an\x2\x2\xC21\xC96\ag\x2\x2\xC22\xC23"+
		"\aG\x2\x2\xC23\xC24\aP\x2\x2\xC24\xC25\a\x46\x2\x2\xC25\xC26\aO\x2\x2"+
		"\xC26\xC27\aQ\x2\x2\xC27\xC28\a\x46\x2\x2\xC28\xC29\aW\x2\x2\xC29\xC2A"+
		"\aN\x2\x2\xC2A\xC96\aG\x2\x2\xC2B\xC2C\a\x30\x2\x2\xC2C\xC2D\ag\x2\x2"+
		"\xC2D\xC2E\ap\x2\x2\xC2E\xC2F\a\x66\x2\x2\xC2F\xC30\au\x2\x2\xC30\xC31"+
		"\a\x65\x2\x2\xC31\xC32\aq\x2\x2\xC32\xC33\ar\x2\x2\xC33\xC96\ag\x2\x2"+
		"\xC34\xC35\a\x30\x2\x2\xC35\xC36\aG\x2\x2\xC36\xC37\aP\x2\x2\xC37\xC38"+
		"\a\x46\x2\x2\xC38\xC39\aU\x2\x2\xC39\xC3A\a\x45\x2\x2\xC3A\xC3B\aQ\x2"+
		"\x2\xC3B\xC3C\aR\x2\x2\xC3C\xC96\aG\x2\x2\xC3D\xC3E\ag\x2\x2\xC3E\xC3F"+
		"\ap\x2\x2\xC3F\xC40\a\x66\x2\x2\xC40\xC41\au\x2\x2\xC41\xC42\a\x65\x2"+
		"\x2\xC42\xC43\aq\x2\x2\xC43\xC44\ar\x2\x2\xC44\xC96\ag\x2\x2\xC45\xC46"+
		"\aG\x2\x2\xC46\xC47\aP\x2\x2\xC47\xC48\a\x46\x2\x2\xC48\xC49\aU\x2\x2"+
		"\xC49\xC4A\a\x45\x2\x2\xC4A\xC4B\aQ\x2\x2\xC4B\xC4C\aR\x2\x2\xC4C\xC96"+
		"\aG\x2\x2\xC4D\xC4E\a\x30\x2\x2\xC4E\xC4F\ao\x2\x2\xC4F\xC50\aq\x2\x2"+
		"\xC50\xC51\a\x66\x2\x2\xC51\xC52\aw\x2\x2\xC52\xC53\an\x2\x2\xC53\xC54"+
		"\ag\x2\x2\xC54\xC55\ag\x2\x2\xC55\xC56\ap\x2\x2\xC56\xC96\a\x66\x2\x2"+
		"\xC57\xC58\a\x30\x2\x2\xC58\xC59\aO\x2\x2\xC59\xC5A\aQ\x2\x2\xC5A\xC5B"+
		"\a\x46\x2\x2\xC5B\xC5C\aW\x2\x2\xC5C\xC5D\aN\x2\x2\xC5D\xC5E\aG\x2\x2"+
		"\xC5E\xC5F\aG\x2\x2\xC5F\xC60\aP\x2\x2\xC60\xC96\a\x46\x2\x2\xC61\xC62"+
		"\ao\x2\x2\xC62\xC63\aq\x2\x2\xC63\xC64\a\x66\x2\x2\xC64\xC65\aw\x2\x2"+
		"\xC65\xC66\an\x2\x2\xC66\xC67\ag\x2\x2\xC67\xC68\ag\x2\x2\xC68\xC69\a"+
		"p\x2\x2\xC69\xC96\a\x66\x2\x2\xC6A\xC6B\aO\x2\x2\xC6B\xC6C\aQ\x2\x2\xC6C"+
		"\xC6D\a\x46\x2\x2\xC6D\xC6E\aW\x2\x2\xC6E\xC6F\aN\x2\x2\xC6F\xC70\aG\x2"+
		"\x2\xC70\xC71\aG\x2\x2\xC71\xC72\aP\x2\x2\xC72\xC96\a\x46\x2\x2\xC73\xC74"+
		"\a\x30\x2\x2\xC74\xC75\au\x2\x2\xC75\xC76\a\x65\x2\x2\xC76\xC77\aq\x2"+
		"\x2\xC77\xC78\ar\x2\x2\xC78\xC79\ag\x2\x2\xC79\xC7A\ag\x2\x2\xC7A\xC7B"+
		"\ap\x2\x2\xC7B\xC96\a\x66\x2\x2\xC7C\xC7D\a\x30\x2\x2\xC7D\xC7E\aU\x2"+
		"\x2\xC7E\xC7F\a\x45\x2\x2\xC7F\xC80\aQ\x2\x2\xC80\xC81\aR\x2\x2\xC81\xC82"+
		"\aG\x2\x2\xC82\xC83\aG\x2\x2\xC83\xC84\aP\x2\x2\xC84\xC96\a\x46\x2\x2"+
		"\xC85\xC86\au\x2\x2\xC86\xC87\a\x65\x2\x2\xC87\xC88\aq\x2\x2\xC88\xC89"+
		"\ar\x2\x2\xC89\xC8A\ag\x2\x2\xC8A\xC8B\ag\x2\x2\xC8B\xC8C\ap\x2\x2\xC8C"+
		"\xC96\a\x66\x2\x2\xC8D\xC8E\aU\x2\x2\xC8E\xC8F\a\x45\x2\x2\xC8F\xC90\a"+
		"Q\x2\x2\xC90\xC91\aR\x2\x2\xC91\xC92\aG\x2\x2\xC92\xC93\aG\x2\x2\xC93"+
		"\xC94\aP\x2\x2\xC94\xC96\a\x46\x2\x2\xC95\xC05\x3\x2\x2\x2\xC95\xC0F\x3"+
		"\x2\x2\x2\xC95\xC19\x3\x2\x2\x2\xC95\xC22\x3\x2\x2\x2\xC95\xC2B\x3\x2"+
		"\x2\x2\xC95\xC34\x3\x2\x2\x2\xC95\xC3D\x3\x2\x2\x2\xC95\xC45\x3\x2\x2"+
		"\x2\xC95\xC4D\x3\x2\x2\x2\xC95\xC57\x3\x2\x2\x2\xC95\xC61\x3\x2\x2\x2"+
		"\xC95\xC6A\x3\x2\x2\x2\xC95\xC73\x3\x2\x2\x2\xC95\xC7C\x3\x2\x2\x2\xC95"+
		"\xC85\x3\x2\x2\x2\xC95\xC8D\x3\x2\x2\x2\xC96\x1BA\x3\x2\x2\x2\xC97\xC98"+
		"\a\x30\x2\x2\xC98\xC99\au\x2\x2\xC99\xC9A\av\x2\x2\xC9A\xC9B\at\x2\x2"+
		"\xC9B\xC9C\aw\x2\x2\xC9C\xC9D\a\x65\x2\x2\xC9D\xCB2\av\x2\x2\xC9E\xC9F"+
		"\a\x30\x2\x2\xC9F\xCA0\aU\x2\x2\xCA0\xCA1\aV\x2\x2\xCA1\xCA2\aT\x2\x2"+
		"\xCA2\xCA3\aW\x2\x2\xCA3\xCA4\a\x45\x2\x2\xCA4\xCB2\aV\x2\x2\xCA5\xCA6"+
		"\au\x2\x2\xCA6\xCA7\av\x2\x2\xCA7\xCA8\at\x2\x2\xCA8\xCA9\aw\x2\x2\xCA9"+
		"\xCAA\a\x65\x2\x2\xCAA\xCB2\av\x2\x2\xCAB\xCAC\aU\x2\x2\xCAC\xCAD\aV\x2"+
		"\x2\xCAD\xCAE\aT\x2\x2\xCAE\xCAF\aW\x2\x2\xCAF\xCB0\a\x45\x2\x2\xCB0\xCB2"+
		"\aV\x2\x2\xCB1\xC97\x3\x2\x2\x2\xCB1\xC9E\x3\x2\x2\x2\xCB1\xCA5\x3\x2"+
		"\x2\x2\xCB1\xCAB\x3\x2\x2\x2\xCB2\x1BC\x3\x2\x2\x2\xCB3\xCB4\a\x30\x2"+
		"\x2\xCB4\xCB5\ag\x2\x2\xCB5\xCB6\ap\x2\x2\xCB6\xCB7\a\x66\x2\x2\xCB7\xCBE"+
		"\au\x2\x2\xCB8\xCB9\a\x30\x2\x2\xCB9\xCBA\aG\x2\x2\xCBA\xCBB\aP\x2\x2"+
		"\xCBB\xCBC\a\x46\x2\x2\xCBC\xCBE\aU\x2\x2\xCBD\xCB3\x3\x2\x2\x2\xCBD\xCB8"+
		"\x3\x2\x2\x2\xCBE\x1BE\x3\x2\x2\x2\xCBF\xCC0\a\x30\x2\x2\xCC0\xCC1\an"+
		"\x2\x2\xCC1\xCC2\aq\x2\x2\xCC2\xCC3\a\x65\x2\x2\xCC3\xCC4\a\x63\x2\x2"+
		"\xCC4\xCDB\an\x2\x2\xCC5\xCC6\a\x30\x2\x2\xCC6\xCC7\aN\x2\x2\xCC7\xCC8"+
		"\aQ\x2\x2\xCC8\xCC9\a\x45\x2\x2\xCC9\xCCA\a\x43\x2\x2\xCCA\xCDB\aN\x2"+
		"\x2\xCCB\xCCC\an\x2\x2\xCCC\xCCD\aq\x2\x2\xCCD\xCCE\a\x65\x2\x2\xCCE\xCCF"+
		"\a\x63\x2\x2\xCCF\xCDB\an\x2\x2\xCD0\xCD1\aN\x2\x2\xCD1\xCD2\aQ\x2\x2"+
		"\xCD2\xCD3\a\x45\x2\x2\xCD3\xCD4\a\x43\x2\x2\xCD4\xCDB\aN\x2\x2\xCD5\xCD6"+
		"\aN\x2\x2\xCD6\xCD7\aq\x2\x2\xCD7\xCD8\a\x65\x2\x2\xCD8\xCD9\a\x63\x2"+
		"\x2\xCD9\xCDB\an\x2\x2\xCDA\xCBF\x3\x2\x2\x2\xCDA\xCC5\x3\x2\x2\x2\xCDA"+
		"\xCCB\x3\x2\x2\x2\xCDA\xCD0\x3\x2\x2\x2\xCDA\xCD5\x3\x2\x2\x2\xCDB\x1C0"+
		"\x3\x2\x2\x2\xCDC\xCDD\a\x30\x2\x2\xCDD\xCDE\au\x2\x2\xCDE\xCDF\ak\x2"+
		"\x2\xCDF\xCE0\ap\x2\x2\xCE0\xCE1\ai\x2\x2\xCE1\xCE2\an\x2\x2\xCE2\xCE3"+
		"\ag\x2\x2\xCE3\xCE4\av\x2\x2\xCE4\xCE5\aq\x2\x2\xCE5\xCF1\ap\x2\x2\xCE6"+
		"\xCE7\a\x30\x2\x2\xCE7\xCE8\aU\x2\x2\xCE8\xCE9\aK\x2\x2\xCE9\xCEA\aP\x2"+
		"\x2\xCEA\xCEB\aI\x2\x2\xCEB\xCEC\aN\x2\x2\xCEC\xCED\aG\x2\x2\xCED\xCEE"+
		"\aV\x2\x2\xCEE\xCEF\aQ\x2\x2\xCEF\xCF1\aP\x2\x2\xCF0\xCDC\x3\x2\x2\x2"+
		"\xCF0\xCE6\x3\x2\x2\x2\xCF1\x1C2\x3\x2\x2\x2\xCF2\xCF3\av\x2\x2\xCF3\xCF4"+
		"\ag\x2\x2\xCF4\xCF5\az\x2\x2\xCF5\xCF6\av\x2\x2\xCF6\xCF7\aq\x2\x2\xCF7"+
		"\xCFF\ah\x2\x2\xCF8\xCF9\aV\x2\x2\xCF9\xCFA\aG\x2\x2\xCFA\xCFB\aZ\x2\x2"+
		"\xCFB\xCFC\aV\x2\x2\xCFC\xCFD\aQ\x2\x2\xCFD\xCFF\aH\x2\x2\xCFE\xCF2\x3"+
		"\x2\x2\x2\xCFE\xCF8\x3\x2\x2\x2\xCFF\x1C4\x3\x2\x2\x2\xD00\xD01\an\x2"+
		"\x2\xD01\xD02\av\x2\x2\xD02\xD03\ag\x2\x2\xD03\xD04\az\x2\x2\xD04\xD05"+
		"\av\x2\x2\xD05\xD06\aq\x2\x2\xD06\xD0F\ah\x2\x2\xD07\xD08\aN\x2\x2\xD08"+
		"\xD09\aV\x2\x2\xD09\xD0A\aG\x2\x2\xD0A\xD0B\aZ\x2\x2\xD0B\xD0C\aV\x2\x2"+
		"\xD0C\xD0D\aQ\x2\x2\xD0D\xD0F\aH\x2\x2\xD0E\xD00\x3\x2\x2\x2\xD0E\xD07"+
		"\x3\x2\x2\x2\xD0F\x1C6\x3\x2\x2\x2\xD10\xD11\aj\x2\x2\xD11\xD12\at\x2"+
		"\x2\xD12\xD13\ag\x2\x2\xD13\xD19\ai\x2\x2\xD14\xD15\aJ\x2\x2\xD15\xD16"+
		"\aT\x2\x2\xD16\xD17\aG\x2\x2\xD17\xD19\aI\x2\x2\xD18\xD10\x3\x2\x2\x2"+
		"\xD18\xD14\x3\x2\x2\x2\xD19\x1C8\x3\x2\x2\x2\xD1A\xD1B\an\x2\x2\xD1B\xD1C"+
		"\at\x2\x2\xD1C\xD1D\ag\x2\x2\xD1D\xD23\ai\x2\x2\xD1E\xD1F\aN\x2\x2\xD1F"+
		"\xD20\aT\x2\x2\xD20\xD21\aG\x2\x2\xD21\xD23\aI\x2\x2\xD22\xD1A\x3\x2\x2"+
		"\x2\xD22\xD1E\x3\x2\x2\x2\xD23\x1CA\x3\x2\x2\x2\xD24\xD25\a\x66\x2\x2"+
		"\xD25\xD26\ag\x2\x2\xD26\xD2B\ah\x2\x2\xD27\xD28\a\x46\x2\x2\xD28\xD29"+
		"\aG\x2\x2\xD29\xD2B\aH\x2\x2\xD2A\xD24\x3\x2\x2\x2\xD2A\xD27\x3\x2\x2"+
		"\x2\xD2B\x1CC\x3\x2\x2\x2\xD2C\xD2D\ak\x2\x2\xD2D\xD2E\au\x2\x2\xD2E\xD2F"+
		"\at\x2\x2\xD2F\xD30\ag\x2\x2\xD30\xD31\ai\x2\x2\xD31\xD39\a:\x2\x2\xD32"+
		"\xD33\aK\x2\x2\xD33\xD34\aU\x2\x2\xD34\xD35\aT\x2\x2\xD35\xD36\aG\x2\x2"+
		"\xD36\xD37\aI\x2\x2\xD37\xD39\a:\x2\x2\xD38\xD2C\x3\x2\x2\x2\xD38\xD32"+
		"\x3\x2\x2\x2\xD39\x1CE\x3\x2\x2\x2\xD3A\xD3B\ak\x2\x2\xD3B\xD3C\au\x2"+
		"\x2\xD3C\xD3D\at\x2\x2\xD3D\xD3E\ag\x2\x2\xD3E\xD3F\ai\x2\x2\xD3F\xD40"+
		"\a:\x2\x2\xD40\xD41\au\x2\x2\xD41\xD42\av\x2\x2\xD42\xD4D\a\x66\x2\x2"+
		"\xD43\xD44\aK\x2\x2\xD44\xD45\aU\x2\x2\xD45\xD46\aT\x2\x2\xD46\xD47\a"+
		"G\x2\x2\xD47\xD48\aI\x2\x2\xD48\xD49\a:\x2\x2\xD49\xD4A\aU\x2\x2\xD4A"+
		"\xD4B\aV\x2\x2\xD4B\xD4D\a\x46\x2\x2\xD4C\xD3A\x3\x2\x2\x2\xD4C\xD43\x3"+
		"\x2\x2\x2\xD4D\x1D0\x3\x2\x2\x2\xD4E\xD4F\ak\x2\x2\xD4F\xD50\au\x2\x2"+
		"\xD50\xD51\at\x2\x2\xD51\xD52\ag\x2\x2\xD52\xD53\ai\x2\x2\xD53\xD54\a"+
		":\x2\x2\xD54\xD55\au\x2\x2\xD55\xD56\ar\x2\x2\xD56\xD57\ag\x2\x2\xD57"+
		"\xD63\a\x65\x2\x2\xD58\xD59\aK\x2\x2\xD59\xD5A\aU\x2\x2\xD5A\xD5B\aT\x2"+
		"\x2\xD5B\xD5C\aG\x2\x2\xD5C\xD5D\aI\x2\x2\xD5D\xD5E\a:\x2\x2\xD5E\xD5F"+
		"\aU\x2\x2\xD5F\xD60\aR\x2\x2\xD60\xD61\aG\x2\x2\xD61\xD63\a\x45\x2\x2"+
		"\xD62\xD4E\x3\x2\x2\x2\xD62\xD58\x3\x2\x2\x2\xD63\x1D2\x3\x2\x2\x2\xD64"+
		"\xD65\ak\x2\x2\xD65\xD66\au\x2\x2\xD66\xD67\at\x2\x2\xD67\xD68\ag\x2\x2"+
		"\xD68\xD69\ai\x2\x2\xD69\xD6A\a:\x2\x2\xD6A\xD6B\ak\x2\x2\xD6B\xD6C\a"+
		"\x66\x2\x2\xD6C\xD77\az\x2\x2\xD6D\xD6E\aK\x2\x2\xD6E\xD6F\aU\x2\x2\xD6F"+
		"\xD70\aT\x2\x2\xD70\xD71\aG\x2\x2\xD71\xD72\aI\x2\x2\xD72\xD73\a:\x2\x2"+
		"\xD73\xD74\aK\x2\x2\xD74\xD75\a\x46\x2\x2\xD75\xD77\aZ\x2\x2\xD76\xD64"+
		"\x3\x2\x2\x2\xD76\xD6D\x3\x2\x2\x2\xD77\x1D4\x3\x2\x2\x2\xD78\xD79\ak"+
		"\x2\x2\xD79\xD7A\au\x2\x2\xD7A\xD7B\at\x2\x2\xD7B\xD7C\ag\x2\x2\xD7C\xD7D"+
		"\ai\x2\x2\xD7D\xD7E\a\x33\x2\x2\xD7E\xD87\a\x38\x2\x2\xD7F\xD80\aK\x2"+
		"\x2\xD80\xD81\aU\x2\x2\xD81\xD82\aT\x2\x2\xD82\xD83\aG\x2\x2\xD83\xD84"+
		"\aI\x2\x2\xD84\xD85\a\x33\x2\x2\xD85\xD87\a\x38\x2\x2\xD86\xD78\x3\x2"+
		"\x2\x2\xD86\xD7F\x3\x2\x2\x2\xD87\x1D6\x3\x2\x2\x2\xD88\xD89\ak\x2\x2"+
		"\xD89\xD8A\au\x2\x2\xD8A\xD8B\at\x2\x2\xD8B\xD8C\ag\x2\x2\xD8C\xD8D\a"+
		"i\x2\x2\xD8D\xD8E\a\x33\x2\x2\xD8E\xD8F\a\x38\x2\x2\xD8F\xD90\au\x2\x2"+
		"\xD90\xD91\av\x2\x2\xD91\xD9D\a\x66\x2\x2\xD92\xD93\aK\x2\x2\xD93\xD94"+
		"\aU\x2\x2\xD94\xD95\aT\x2\x2\xD95\xD96\aG\x2\x2\xD96\xD97\aI\x2\x2\xD97"+
		"\xD98\a\x33\x2\x2\xD98\xD99\a\x38\x2\x2\xD99\xD9A\aU\x2\x2\xD9A\xD9B\a"+
		"V\x2\x2\xD9B\xD9D\a\x46\x2\x2\xD9C\xD88\x3\x2\x2\x2\xD9C\xD92\x3\x2\x2"+
		"\x2\xD9D\x1D8\x3\x2\x2\x2\xD9E\xD9F\ak\x2\x2\xD9F\xDA0\au\x2\x2\xDA0\xDA1"+
		"\at\x2\x2\xDA1\xDA2\ag\x2\x2\xDA2\xDA3\ai\x2\x2\xDA3\xDA4\a\x33\x2\x2"+
		"\xDA4\xDA5\a\x38\x2\x2\xDA5\xDA6\ak\x2\x2\xDA6\xDA7\a\x66\x2\x2\xDA7\xDB3"+
		"\az\x2\x2\xDA8\xDA9\aK\x2\x2\xDA9\xDAA\aU\x2\x2\xDAA\xDAB\aT\x2\x2\xDAB"+
		"\xDAC\aG\x2\x2\xDAC\xDAD\aI\x2\x2\xDAD\xDAE\a\x33\x2\x2\xDAE\xDAF\a\x38"+
		"\x2\x2\xDAF\xDB0\aK\x2\x2\xDB0\xDB1\a\x46\x2\x2\xDB1\xDB3\aZ\x2\x2\xDB2"+
		"\xD9E\x3\x2\x2\x2\xDB2\xDA8\x3\x2\x2\x2\xDB3\x1DA\x3\x2\x2\x2\xDB4\xDB5"+
		"\ak\x2\x2\xDB5\xDB6\au\x2\x2\xDB6\xDB7\at\x2\x2\xDB7\xDB8\ag\x2\x2\xDB8"+
		"\xDB9\ai\x2\x2\xDB9\xDBA\ak\x2\x2\xDBA\xDBB\ap\x2\x2\xDBB\xDBC\a\x66\x2"+
		"\x2\xDBC\xDBD\ak\x2\x2\xDBD\xDBE\at\x2\x2\xDBE\xDBF\ag\x2\x2\xDBF\xDC0"+
		"\a\x65\x2\x2\xDC0\xDCF\av\x2\x2\xDC1\xDC2\aK\x2\x2\xDC2\xDC3\aU\x2\x2"+
		"\xDC3\xDC4\aT\x2\x2\xDC4\xDC5\aG\x2\x2\xDC5\xDC6\aI\x2\x2\xDC6\xDC7\a"+
		"K\x2\x2\xDC7\xDC8\aP\x2\x2\xDC8\xDC9\a\x46\x2\x2\xDC9\xDCA\aK\x2\x2\xDCA"+
		"\xDCB\aT\x2\x2\xDCB\xDCC\aG\x2\x2\xDCC\xDCD\a\x45\x2\x2\xDCD\xDCF\aV\x2"+
		"\x2\xDCE\xDB4\x3\x2\x2\x2\xDCE\xDC1\x3\x2\x2\x2\xDCF\x1DC\x3\x2\x2\x2"+
		"\xDD0\xDD1\ak\x2\x2\xDD1\xDD2\au\x2\x2\xDD2\xDD3\a\x65\x2\x2\xDD3\xDD4"+
		"\ar\x2\x2\xDD4\xDD5\aq\x2\x2\xDD5\xDD6\at\x2\x2\xDD6\xDDF\av\x2\x2\xDD7"+
		"\xDD8\aK\x2\x2\xDD8\xDD9\aU\x2\x2\xDD9\xDDA\a\x45\x2\x2\xDDA\xDDB\aR\x2"+
		"\x2\xDDB\xDDC\aQ\x2\x2\xDDC\xDDD\aT\x2\x2\xDDD\xDDF\aV\x2\x2\xDDE\xDD0"+
		"\x3\x2\x2\x2\xDDE\xDD7\x3\x2\x2\x2\xDDF\x1DE\x3\x2\x2\x2\xDE0\xDE1\ak"+
		"\x2\x2\xDE1\xDE2\au\x2\x2\xDE2\xDE3\ak\x2\x2\xDE3\xDE4\ap\x2\x2\xDE4\xDE5"+
		"\a\x66\x2\x2\xDE5\xDE6\ag\x2\x2\xDE6\xDE7\az\x2\x2\xDE7\xDE8\ag\x2\x2"+
		"\xDE8\xDE9\a\x66\x2\x2\xDE9\xDEA\a\x63\x2\x2\xDEA\xDEB\a\x66\x2\x2\xDEB"+
		"\xDEC\a\x66\x2\x2\xDEC\xDFB\at\x2\x2\xDED\xDEE\aK\x2\x2\xDEE\xDEF\aU\x2"+
		"\x2\xDEF\xDF0\aK\x2\x2\xDF0\xDF1\aP\x2\x2\xDF1\xDF2\a\x46\x2\x2\xDF2\xDF3"+
		"\aG\x2\x2\xDF3\xDF4\aZ\x2\x2\xDF4\xDF5\aG\x2\x2\xDF5\xDF6\a\x46\x2\x2"+
		"\xDF6\xDF7\a\x43\x2\x2\xDF7\xDF8\a\x46\x2\x2\xDF8\xDF9\a\x46\x2\x2\xDF9"+
		"\xDFB\aT\x2\x2\xDFA\xDE0\x3\x2\x2\x2\xDFA\xDED\x3\x2\x2\x2\xDFB\x1E0\x3"+
		"\x2\x2\x2\xDFC\xDFD\ak\x2\x2\xDFD\xDFE\au\x2\x2\xDFE\xDFF\a\x65\x2\x2"+
		"\xDFF\xE00\aq\x2\x2\xE00\xE01\ap\x2\x2\xE01\xE02\a\x66\x2\x2\xE02\xE03"+
		"\ak\x2\x2\xE03\xE04\av\x2\x2\xE04\xE05\ak\x2\x2\xE05\xE06\aq\x2\x2\xE06"+
		"\xE13\ap\x2\x2\xE07\xE08\aK\x2\x2\xE08\xE09\aU\x2\x2\xE09\xE0A\a\x45\x2"+
		"\x2\xE0A\xE0B\aQ\x2\x2\xE0B\xE0C\aP\x2\x2\xE0C\xE0D\a\x46\x2\x2\xE0D\xE0E"+
		"\aK\x2\x2\xE0E\xE0F\aV\x2\x2\xE0F\xE10\aK\x2\x2\xE10\xE11\aQ\x2\x2\xE11"+
		"\xE13\aP\x2\x2\xE12\xDFC\x3\x2\x2\x2\xE12\xE07\x3\x2\x2\x2\xE13\x1E2\x3"+
		"\x2\x2\x2\xE14\xE15\ak\x2\x2\xE15\xE16\au\x2\x2\xE16\xE17\ag\x2\x2\xE17"+
		"\xE18\az\x2\x2\xE18\xE19\ar\x2\x2\xE19\xE21\at\x2\x2\xE1A\xE1B\aK\x2\x2"+
		"\xE1B\xE1C\aU\x2\x2\xE1C\xE1D\aG\x2\x2\xE1D\xE1E\aZ\x2\x2\xE1E\xE1F\a"+
		"R\x2\x2\xE1F\xE21\aT\x2\x2\xE20\xE14\x3\x2\x2\x2\xE20\xE1A\x3\x2\x2\x2"+
		"\xE21\x1E4\x3\x2\x2\x2\xE22\xE23\ak\x2\x2\xE23\xE24\au\x2\x2\xE24\xE25"+
		"\at\x2\x2\xE25\xE26\ag\x2\x2\xE26\xE27\ai\x2\x2\xE27\xE2F\a\x63\x2\x2"+
		"\xE28\xE29\aK\x2\x2\xE29\xE2A\aU\x2\x2\xE2A\xE2B\aT\x2\x2\xE2B\xE2C\a"+
		"G\x2\x2\xE2C\xE2D\aI\x2\x2\xE2D\xE2F\a\x43\x2\x2\xE2E\xE22\x3\x2\x2\x2"+
		"\xE2E\xE28\x3\x2\x2\x2\xE2F\x1E6\x3\x2\x2\x2\xE30\xE31\ak\x2\x2\xE31\xE32"+
		"\au\x2\x2\xE32\xE33\at\x2\x2\xE33\xE34\ag\x2\x2\xE34\xE35\ai\x2\x2\xE35"+
		"\xE36\a\x63\x2\x2\xE36\xE3F\ah\x2\x2\xE37\xE38\aK\x2\x2\xE38\xE39\aU\x2"+
		"\x2\xE39\xE3A\aT\x2\x2\xE3A\xE3B\aG\x2\x2\xE3B\xE3C\aI\x2\x2\xE3C\xE3D"+
		"\a\x43\x2\x2\xE3D\xE3F\aH\x2\x2\xE3E\xE30\x3\x2\x2\x2\xE3E\xE37\x3\x2"+
		"\x2\x2\xE3F\x1E8\x3\x2\x2\x2\xE40\xE41\ak\x2\x2\xE41\xE42\au\x2\x2\xE42"+
		"\xE43\at\x2\x2\xE43\xE44\ag\x2\x2\xE44\xE45\ai\x2\x2\xE45\xE4D\a\x64\x2"+
		"\x2\xE46\xE47\aK\x2\x2\xE47\xE48\aU\x2\x2\xE48\xE49\aT\x2\x2\xE49\xE4A"+
		"\aG\x2\x2\xE4A\xE4B\aI\x2\x2\xE4B\xE4D\a\x44\x2\x2\xE4C\xE40\x3\x2\x2"+
		"\x2\xE4C\xE46\x3\x2\x2\x2\xE4D\x1EA\x3\x2\x2\x2\xE4E\xE4F\ak\x2\x2\xE4F"+
		"\xE50\au\x2\x2\xE50\xE51\at\x2\x2\xE51\xE52\ag\x2\x2\xE52\xE53\ai\x2\x2"+
		"\xE53\xE5B\a\x65\x2\x2\xE54\xE55\aK\x2\x2\xE55\xE56\aU\x2\x2\xE56\xE57"+
		"\aT\x2\x2\xE57\xE58\aG\x2\x2\xE58\xE59\aI\x2\x2\xE59\xE5B\a\x45\x2\x2"+
		"\xE5A\xE4E\x3\x2\x2\x2\xE5A\xE54\x3\x2\x2\x2\xE5B\x1EC\x3\x2\x2\x2\xE5C"+
		"\xE5D\ak\x2\x2\xE5D\xE5E\au\x2\x2\xE5E\xE5F\at\x2\x2\xE5F\xE60\ag\x2\x2"+
		"\xE60\xE61\ai\x2\x2\xE61\xE62\a\x64\x2\x2\xE62\xE6B\a\x65\x2\x2\xE63\xE64"+
		"\aK\x2\x2\xE64\xE65\aU\x2\x2\xE65\xE66\aT\x2\x2\xE66\xE67\aG\x2\x2\xE67"+
		"\xE68\aI\x2\x2\xE68\xE69\a\x44\x2\x2\xE69\xE6B\a\x45\x2\x2\xE6A\xE5C\x3"+
		"\x2\x2\x2\xE6A\xE63\x3\x2\x2\x2\xE6B\x1EE\x3\x2\x2\x2\xE6C\xE6D\ak\x2"+
		"\x2\xE6D\xE6E\au\x2\x2\xE6E\xE6F\at\x2\x2\xE6F\xE70\ag\x2\x2\xE70\xE71"+
		"\ai\x2\x2\xE71\xE79\a\x66\x2\x2\xE72\xE73\aK\x2\x2\xE73\xE74\aU\x2\x2"+
		"\xE74\xE75\aT\x2\x2\xE75\xE76\aG\x2\x2\xE76\xE77\aI\x2\x2\xE77\xE79\a"+
		"\x46\x2\x2\xE78\xE6C\x3\x2\x2\x2\xE78\xE72\x3\x2\x2\x2\xE79\x1F0\x3\x2"+
		"\x2\x2\xE7A\xE7B\ak\x2\x2\xE7B\xE7C\au\x2\x2\xE7C\xE7D\at\x2\x2\xE7D\xE7E"+
		"\ag\x2\x2\xE7E\xE7F\ai\x2\x2\xE7F\xE87\ag\x2\x2\xE80\xE81\aK\x2\x2\xE81"+
		"\xE82\aU\x2\x2\xE82\xE83\aT\x2\x2\xE83\xE84\aG\x2\x2\xE84\xE85\aI\x2\x2"+
		"\xE85\xE87\aG\x2\x2\xE86\xE7A\x3\x2\x2\x2\xE86\xE80\x3\x2\x2\x2\xE87\x1F2"+
		"\x3\x2\x2\x2\xE88\xE89\ak\x2\x2\xE89\xE8A\au\x2\x2\xE8A\xE8B\at\x2\x2"+
		"\xE8B\xE8C\ag\x2\x2\xE8C\xE8D\ai\x2\x2\xE8D\xE8E\a\x66\x2\x2\xE8E\xE97"+
		"\ag\x2\x2\xE8F\xE90\aK\x2\x2\xE90\xE91\aU\x2\x2\xE91\xE92\aT\x2\x2\xE92"+
		"\xE93\aG\x2\x2\xE93\xE94\aI\x2\x2\xE94\xE95\a\x46\x2\x2\xE95\xE97\aG\x2"+
		"\x2\xE96\xE88\x3\x2\x2\x2\xE96\xE8F\x3\x2\x2\x2\xE97\x1F4\x3\x2\x2\x2"+
		"\xE98\xE99\ak\x2\x2\xE99\xE9A\au\x2\x2\xE9A\xE9B\at\x2\x2\xE9B\xE9C\a"+
		"g\x2\x2\xE9C\xE9D\ai\x2\x2\xE9D\xEA5\aj\x2\x2\xE9E\xE9F\aK\x2\x2\xE9F"+
		"\xEA0\aU\x2\x2\xEA0\xEA1\aT\x2\x2\xEA1\xEA2\aG\x2\x2\xEA2\xEA3\aI\x2\x2"+
		"\xEA3\xEA5\aJ\x2\x2\xEA4\xE98\x3\x2\x2\x2\xEA4\xE9E\x3\x2\x2\x2\xEA5\x1F6"+
		"\x3\x2\x2\x2\xEA6\xEA7\ak\x2\x2\xEA7\xEA8\au\x2\x2\xEA8\xEA9\at\x2\x2"+
		"\xEA9\xEAA\ag\x2\x2\xEAA\xEAB\ai\x2\x2\xEAB\xEB3\an\x2\x2\xEAC\xEAD\a"+
		"K\x2\x2\xEAD\xEAE\aU\x2\x2\xEAE\xEAF\aT\x2\x2\xEAF\xEB0\aG\x2\x2\xEB0"+
		"\xEB1\aI\x2\x2\xEB1\xEB3\aN\x2\x2\xEB2\xEA6\x3\x2\x2\x2\xEB2\xEAC\x3\x2"+
		"\x2\x2\xEB3\x1F8\x3\x2\x2\x2\xEB4\xEB5\ak\x2\x2\xEB5\xEB6\au\x2\x2\xEB6"+
		"\xEB7\at\x2\x2\xEB7\xEB8\ag\x2\x2\xEB8\xEB9\ai\x2\x2\xEB9\xEBA\aj\x2\x2"+
		"\xEBA\xEC3\an\x2\x2\xEBB\xEBC\aK\x2\x2\xEBC\xEBD\aU\x2\x2\xEBD\xEBE\a"+
		"T\x2\x2\xEBE\xEBF\aG\x2\x2\xEBF\xEC0\aI\x2\x2\xEC0\xEC1\aJ\x2\x2\xEC1"+
		"\xEC3\aN\x2\x2\xEC2\xEB4\x3\x2\x2\x2\xEC2\xEBB\x3\x2\x2\x2\xEC3\x1FA\x3"+
		"\x2\x2\x2\xEC4\xEC5\ak\x2\x2\xEC5\xEC6\au\x2\x2\xEC6\xEC7\at\x2\x2\xEC7"+
		"\xEC8\ag\x2\x2\xEC8\xEC9\ai\x2\x2\xEC9\xED1\ak\x2\x2\xECA\xECB\aK\x2\x2"+
		"\xECB\xECC\aU\x2\x2\xECC\xECD\aT\x2\x2\xECD\xECE\aG\x2\x2\xECE\xECF\a"+
		"I\x2\x2\xECF\xED1\aK\x2\x2\xED0\xEC4\x3\x2\x2\x2\xED0\xECA\x3\x2\x2\x2"+
		"\xED1\x1FC\x3\x2\x2\x2\xED2\xED3\ak\x2\x2\xED3\xED4\au\x2\x2\xED4\xED5"+
		"\at\x2\x2\xED5\xED6\ag\x2\x2\xED6\xED7\ai\x2\x2\xED7\xEDF\at\x2\x2\xED8"+
		"\xED9\aK\x2\x2\xED9\xEDA\aU\x2\x2\xEDA\xEDB\aT\x2\x2\xEDB\xEDC\aG\x2\x2"+
		"\xEDC\xEDD\aI\x2\x2\xEDD\xEDF\aT\x2\x2\xEDE\xED2\x3\x2\x2\x2\xEDE\xED8"+
		"\x3\x2\x2\x2\xEDF\x1FE\x3\x2\x2\x2\xEE0\xEE1\ak\x2\x2\xEE1\xEE2\au\x2"+
		"\x2\xEE2\xEE3\at\x2\x2\xEE3\xEE4\ag\x2\x2\xEE4\xEE5\ai\x2\x2\xEE5\xEE6"+
		"\au\x2\x2\xEE6\xEEF\ar\x2\x2\xEE7\xEE8\aK\x2\x2\xEE8\xEE9\aU\x2\x2\xEE9"+
		"\xEEA\aT\x2\x2\xEEA\xEEB\aG\x2\x2\xEEB\xEEC\aI\x2\x2\xEEC\xEED\aU\x2\x2"+
		"\xEED\xEEF\aR\x2\x2\xEEE\xEE0\x3\x2\x2\x2\xEEE\xEE7\x3\x2\x2\x2\xEEF\x200"+
		"\x3\x2\x2\x2\xEF0\xEF1\ak\x2\x2\xEF1\xEF2\au\x2\x2\xEF2\xEF3\at\x2\x2"+
		"\xEF3\xEF4\ag\x2\x2\xEF4\xEF5\ai\x2\x2\xEF5\xEF6\az\x2\x2\xEF6\xEFF\a"+
		"j\x2\x2\xEF7\xEF8\aK\x2\x2\xEF8\xEF9\aU\x2\x2\xEF9\xEFA\aT\x2\x2\xEFA"+
		"\xEFB\aG\x2\x2\xEFB\xEFC\aI\x2\x2\xEFC\xEFD\aZ\x2\x2\xEFD\xEFF\aJ\x2\x2"+
		"\xEFE\xEF0\x3\x2\x2\x2\xEFE\xEF7\x3\x2\x2\x2\xEFF\x202\x3\x2\x2\x2\xF00"+
		"\xF01\ak\x2\x2\xF01\xF02\au\x2\x2\xF02\xF03\at\x2\x2\xF03\xF04\ag\x2\x2"+
		"\xF04\xF05\ai\x2\x2\xF05\xF06\az\x2\x2\xF06\xF0F\an\x2\x2\xF07\xF08\a"+
		"K\x2\x2\xF08\xF09\aU\x2\x2\xF09\xF0A\aT\x2\x2\xF0A\xF0B\aG\x2\x2\xF0B"+
		"\xF0C\aI\x2\x2\xF0C\xF0D\aZ\x2\x2\xF0D\xF0F\aN\x2\x2\xF0E\xF00\x3\x2\x2"+
		"\x2\xF0E\xF07\x3\x2\x2\x2\xF0F\x204\x3\x2\x2\x2\xF10\xF11\ak\x2\x2\xF11"+
		"\xF12\au\x2\x2\xF12\xF13\at\x2\x2\xF13\xF14\ag\x2\x2\xF14\xF15\ai\x2\x2"+
		"\xF15\xF16\ak\x2\x2\xF16\xF1F\az\x2\x2\xF17\xF18\aK\x2\x2\xF18\xF19\a"+
		"U\x2\x2\xF19\xF1A\aT\x2\x2\xF1A\xF1B\aG\x2\x2\xF1B\xF1C\aI\x2\x2\xF1C"+
		"\xF1D\aK\x2\x2\xF1D\xF1F\aZ\x2\x2\xF1E\xF10\x3\x2\x2\x2\xF1E\xF17\x3\x2"+
		"\x2\x2\xF1F\x206\x3\x2\x2\x2\xF20\xF21\ak\x2\x2\xF21\xF22\au\x2\x2\xF22"+
		"\xF23\at\x2\x2\xF23\xF24\ag\x2\x2\xF24\xF25\ai\x2\x2\xF25\xF26\a{\x2\x2"+
		"\xF26\xF2F\aj\x2\x2\xF27\xF28\aK\x2\x2\xF28\xF29\aU\x2\x2\xF29\xF2A\a"+
		"T\x2\x2\xF2A\xF2B\aG\x2\x2\xF2B\xF2C\aI\x2\x2\xF2C\xF2D\a[\x2\x2\xF2D"+
		"\xF2F\aJ\x2\x2\xF2E\xF20\x3\x2\x2\x2\xF2E\xF27\x3\x2\x2\x2\xF2F\x208\x3"+
		"\x2\x2\x2\xF30\xF31\ak\x2\x2\xF31\xF32\au\x2\x2\xF32\xF33\at\x2\x2\xF33"+
		"\xF34\ag\x2\x2\xF34\xF35\ai\x2\x2\xF35\xF36\a{\x2\x2\xF36\xF3F\an\x2\x2"+
		"\xF37\xF38\aK\x2\x2\xF38\xF39\aU\x2\x2\xF39\xF3A\aT\x2\x2\xF3A\xF3B\a"+
		"G\x2\x2\xF3B\xF3C\aI\x2\x2\xF3C\xF3D\a[\x2\x2\xF3D\xF3F\aN\x2\x2\xF3E"+
		"\xF30\x3\x2\x2\x2\xF3E\xF37\x3\x2\x2\x2\xF3F\x20A\x3\x2\x2\x2\xF40\xF41"+
		"\ak\x2\x2\xF41\xF42\au\x2\x2\xF42\xF43\at\x2\x2\xF43\xF44\ag\x2\x2\xF44"+
		"\xF45\ai\x2\x2\xF45\xF46\ak\x2\x2\xF46\xF4F\a{\x2\x2\xF47\xF48\aK\x2\x2"+
		"\xF48\xF49\aU\x2\x2\xF49\xF4A\aT\x2\x2\xF4A\xF4B\aG\x2\x2\xF4B\xF4C\a"+
		"I\x2\x2\xF4C\xF4D\aK\x2\x2\xF4D\xF4F\a[\x2\x2\xF4E\xF40\x3\x2\x2\x2\xF4E"+
		"\xF47\x3\x2\x2\x2\xF4F\x20C\x3\x2\x2\x2\xF50\xF55\a%\x2\x2\xF51\xF52\a"+
		"\x32\x2\x2\xF52\xF55\az\x2\x2\xF53\xF55\a&\x2\x2\xF54\xF50\x3\x2\x2\x2"+
		"\xF54\xF51\x3\x2\x2\x2\xF54\xF53\x3\x2\x2\x2\xF55\xF56\x3\x2\x2\x2\xF56"+
		"\xF58\x5\x235\x11B\x2\xF57\xF59\x5\x235\x11B\x2\xF58\xF57\x3\x2\x2\x2"+
		"\xF58\xF59\x3\x2\x2\x2\xF59\xF5B\x3\x2\x2\x2\xF5A\xF5C\x5\x235\x11B\x2"+
		"\xF5B\xF5A\x3\x2\x2\x2\xF5B\xF5C\x3\x2\x2\x2\xF5C\xF5E\x3\x2\x2\x2\xF5D"+
		"\xF5F\x5\x235\x11B\x2\xF5E\xF5D\x3\x2\x2\x2\xF5E\xF5F\x3\x2\x2\x2\xF5F"+
		"\xF70\x3\x2\x2\x2\xF60\xF62\x5\x239\x11D\x2\xF61\xF63\x5\x235\x11B\x2"+
		"\xF62\xF61\x3\x2\x2\x2\xF62\xF63\x3\x2\x2\x2\xF63\xF65\x3\x2\x2\x2\xF64"+
		"\xF66\x5\x235\x11B\x2\xF65\xF64\x3\x2\x2\x2\xF65\xF66\x3\x2\x2\x2\xF66"+
		"\xF68\x3\x2\x2\x2\xF67\xF69\x5\x235\x11B\x2\xF68\xF67\x3\x2\x2\x2\xF68"+
		"\xF69\x3\x2\x2\x2\xF69\xF6B\x3\x2\x2\x2\xF6A\xF6C\x5\x235\x11B\x2\xF6B"+
		"\xF6A\x3\x2\x2\x2\xF6B\xF6C\x3\x2\x2\x2\xF6C\xF6D\x3\x2\x2\x2\xF6D\xF6E"+
		"\t\t\x2\x2\xF6E\xF70\x3\x2\x2\x2\xF6F\xF54\x3\x2\x2\x2\xF6F\xF60\x3\x2"+
		"\x2\x2\xF70\x20E\x3\x2\x2\x2\xF71\xF75\a\'\x2\x2\xF72\xF73\a\x32\x2\x2"+
		"\xF73\xF75\a\x64\x2\x2\xF74\xF71\x3\x2\x2\x2\xF74\xF72\x3\x2\x2\x2\xF75"+
		"\xF77\x3\x2\x2\x2\xF76\xF78\a\x61\x2\x2\xF77\xF76\x3\x2\x2\x2\xF77\xF78"+
		"\x3\x2\x2\x2\xF78\xF79\x3\x2\x2\x2\xF79\xF7B\x5\x23B\x11E\x2\xF7A\xF7C"+
		"\x5\x23B\x11E\x2\xF7B\xF7A\x3\x2\x2\x2\xF7B\xF7C\x3\x2\x2\x2\xF7C\xF7E"+
		"\x3\x2\x2\x2\xF7D\xF7F\x5\x23B\x11E\x2\xF7E\xF7D\x3\x2\x2\x2\xF7E\xF7F"+
		"\x3\x2\x2\x2\xF7F\xF81\x3\x2\x2\x2\xF80\xF82\x5\x23B\x11E\x2\xF81\xF80"+
		"\x3\x2\x2\x2\xF81\xF82\x3\x2\x2\x2\xF82\xF84\x3\x2\x2\x2\xF83\xF85\x5"+
		"\x23B\x11E\x2\xF84\xF83\x3\x2\x2\x2\xF84\xF85\x3\x2\x2\x2\xF85\xF87\x3"+
		"\x2\x2\x2\xF86\xF88\x5\x23B\x11E\x2\xF87\xF86\x3\x2\x2\x2\xF87\xF88\x3"+
		"\x2\x2\x2\xF88\xF8A\x3\x2\x2\x2\xF89\xF8B\x5\x23B\x11E\x2\xF8A\xF89\x3"+
		"\x2\x2\x2\xF8A\xF8B\x3\x2\x2\x2\xF8B\xF8D\x3\x2\x2\x2\xF8C\xF8E\x5\x23B"+
		"\x11E\x2\xF8D\xF8C\x3\x2\x2\x2\xF8D\xF8E\x3\x2\x2\x2\xF8E\xF90\x3\x2\x2"+
		"\x2\xF8F\xF91\x5\x23B\x11E\x2\xF90\xF8F\x3\x2\x2\x2\xF90\xF91\x3\x2\x2"+
		"\x2\xF91\xF93\x3\x2\x2\x2\xF92\xF94\x5\x23B\x11E\x2\xF93\xF92\x3\x2\x2"+
		"\x2\xF93\xF94\x3\x2\x2\x2\xF94\xF96\x3\x2\x2\x2\xF95\xF97\x5\x23B\x11E"+
		"\x2\xF96\xF95\x3\x2\x2\x2\xF96\xF97\x3\x2\x2\x2\xF97\xF99\x3\x2\x2\x2"+
		"\xF98\xF9A\x5\x23B\x11E\x2\xF99\xF98\x3\x2\x2\x2\xF99\xF9A\x3\x2\x2\x2"+
		"\xF9A\xF9C\x3\x2\x2\x2\xF9B\xF9D\x5\x23B\x11E\x2\xF9C\xF9B\x3\x2\x2\x2"+
		"\xF9C\xF9D\x3\x2\x2\x2\xF9D\xF9F\x3\x2\x2\x2\xF9E\xFA0\x5\x23B\x11E\x2"+
		"\xF9F\xF9E\x3\x2\x2\x2\xF9F\xFA0\x3\x2\x2\x2\xFA0\xFA2\x3\x2\x2\x2\xFA1"+
		"\xFA3\x5\x23B\x11E\x2\xFA2\xFA1\x3\x2\x2\x2\xFA2\xFA3\x3\x2\x2\x2\xFA3"+
		"\xFA5\x3\x2\x2\x2\xFA4\xFA6\x5\x23B\x11E\x2\xFA5\xFA4\x3\x2\x2\x2\xFA5"+
		"\xFA6\x3\x2\x2\x2\xFA6\xFDB\x3\x2\x2\x2\xFA7\xFA9\a\x61\x2\x2\xFA8\xFA7"+
		"\x3\x2\x2\x2\xFA8\xFA9\x3\x2\x2\x2\xFA9\xFAA\x3\x2\x2\x2\xFAA\xFAC\x5"+
		"\x23B\x11E\x2\xFAB\xFAD\x5\x23B\x11E\x2\xFAC\xFAB\x3\x2\x2\x2\xFAC\xFAD"+
		"\x3\x2\x2\x2\xFAD\xFAF\x3\x2\x2\x2\xFAE\xFB0\x5\x23B\x11E\x2\xFAF\xFAE"+
		"\x3\x2\x2\x2\xFAF\xFB0\x3\x2\x2\x2\xFB0\xFB2\x3\x2\x2\x2\xFB1\xFB3\x5"+
		"\x23B\x11E\x2\xFB2\xFB1\x3\x2\x2\x2\xFB2\xFB3\x3\x2\x2\x2\xFB3\xFB5\x3"+
		"\x2\x2\x2\xFB4\xFB6\x5\x23B\x11E\x2\xFB5\xFB4\x3\x2\x2\x2\xFB5\xFB6\x3"+
		"\x2\x2\x2\xFB6\xFB8\x3\x2\x2\x2\xFB7\xFB9\x5\x23B\x11E\x2\xFB8\xFB7\x3"+
		"\x2\x2\x2\xFB8\xFB9\x3\x2\x2\x2\xFB9\xFBB\x3\x2\x2\x2\xFBA\xFBC\x5\x23B"+
		"\x11E\x2\xFBB\xFBA\x3\x2\x2\x2\xFBB\xFBC\x3\x2\x2\x2\xFBC\xFBE\x3\x2\x2"+
		"\x2\xFBD\xFBF\x5\x23B\x11E\x2\xFBE\xFBD\x3\x2\x2\x2\xFBE\xFBF\x3\x2\x2"+
		"\x2\xFBF\xFC1\x3\x2\x2\x2\xFC0\xFC2\x5\x23B\x11E\x2\xFC1\xFC0\x3\x2\x2"+
		"\x2\xFC1\xFC2\x3\x2\x2\x2\xFC2\xFC4\x3\x2\x2\x2\xFC3\xFC5\x5\x23B\x11E"+
		"\x2\xFC4\xFC3\x3\x2\x2\x2\xFC4\xFC5\x3\x2\x2\x2\xFC5\xFC7\x3\x2\x2\x2"+
		"\xFC6\xFC8\x5\x23B\x11E\x2\xFC7\xFC6\x3\x2\x2\x2\xFC7\xFC8\x3\x2\x2\x2"+
		"\xFC8\xFCA\x3\x2\x2\x2\xFC9\xFCB\x5\x23B\x11E\x2\xFCA\xFC9\x3\x2\x2\x2"+
		"\xFCA\xFCB\x3\x2\x2\x2\xFCB\xFCD\x3\x2\x2\x2\xFCC\xFCE\x5\x23B\x11E\x2"+
		"\xFCD\xFCC\x3\x2\x2\x2\xFCD\xFCE\x3\x2\x2\x2\xFCE\xFD0\x3\x2\x2\x2\xFCF"+
		"\xFD1\x5\x23B\x11E\x2\xFD0\xFCF\x3\x2\x2\x2\xFD0\xFD1\x3\x2\x2\x2\xFD1"+
		"\xFD3\x3\x2\x2\x2\xFD2\xFD4\x5\x23B\x11E\x2\xFD3\xFD2\x3\x2\x2\x2\xFD3"+
		"\xFD4\x3\x2\x2\x2\xFD4\xFD6\x3\x2\x2\x2\xFD5\xFD7\x5\x23B\x11E\x2\xFD6"+
		"\xFD5\x3\x2\x2\x2\xFD6\xFD7\x3\x2\x2\x2\xFD7\xFD8\x3\x2\x2\x2\xFD8\xFD9"+
		"\t\x5\x2\x2\xFD9\xFDB\x3\x2\x2\x2\xFDA\xF74\x3\x2\x2\x2\xFDA\xFA8\x3\x2"+
		"\x2\x2\xFDB\x210\x3\x2\x2\x2\xFDC\xFDE\x5\x237\x11C\x2\xFDD\xFDF\x5\x237"+
		"\x11C\x2\xFDE\xFDD\x3\x2\x2\x2\xFDE\xFDF\x3\x2\x2\x2\xFDF\xFE1\x3\x2\x2"+
		"\x2\xFE0\xFE2\x5\x237\x11C\x2\xFE1\xFE0\x3\x2\x2\x2\xFE1\xFE2\x3\x2\x2"+
		"\x2\xFE2\xFE4\x3\x2\x2\x2\xFE3\xFE5\x5\x237\x11C\x2\xFE4\xFE3\x3\x2\x2"+
		"\x2\xFE4\xFE5\x3\x2\x2\x2\xFE5\xFE7\x3\x2\x2\x2\xFE6\xFE8\x5\x237\x11C"+
		"\x2\xFE7\xFE6\x3\x2\x2\x2\xFE7\xFE8\x3\x2\x2\x2\xFE8\xFEA\x3\x2\x2\x2"+
		"\xFE9\xFEB\x5\x237\x11C\x2\xFEA\xFE9\x3\x2\x2\x2\xFEA\xFEB\x3\x2\x2\x2"+
		"\xFEB\xFEC\x3\x2\x2\x2\xFEC\xFED\t\x10\x2\x2\xFED\x212\x3\x2\x2\x2\xFEE"+
		"\xFF0\x5\x239\x11D\x2\xFEF\xFF1\x5\x239\x11D\x2\xFF0\xFEF\x3\x2\x2\x2"+
		"\xFF0\xFF1\x3\x2\x2\x2\xFF1\xFF3\x3\x2\x2\x2\xFF2\xFF4\x5\x239\x11D\x2"+
		"\xFF3\xFF2\x3\x2\x2\x2\xFF3\xFF4\x3\x2\x2\x2\xFF4\xFF6\x3\x2\x2\x2\xFF5"+
		"\xFF7\x5\x239\x11D\x2\xFF6\xFF5\x3\x2\x2\x2\xFF6\xFF7\x3\x2\x2\x2\xFF7"+
		"\xFF9\x3\x2\x2\x2\xFF8\xFFA\x5\x239\x11D\x2\xFF9\xFF8\x3\x2\x2\x2\xFF9"+
		"\xFFA\x3\x2\x2\x2\xFFA\x214\x3\x2\x2\x2\xFFB\xFFC\a&\x2\x2\xFFC\x216\x3"+
		"\x2\x2\x2\xFFD\xFFF\t\x11\x2\x2\xFFE\xFFD\x3\x2\x2\x2\xFFF\x1002\x3\x2"+
		"\x2\x2\x1000\xFFE\x3\x2\x2\x2\x1000\x1001\x3\x2\x2\x2\x1001\x1003\x3\x2"+
		"\x2\x2\x1002\x1000\x3\x2\x2\x2\x1003\x1005\x5Q)\x2\x1004\x1006\t\x11\x2"+
		"\x2\x1005\x1004\x3\x2\x2\x2\x1006\x1007\x3\x2\x2\x2\x1007\x1005\x3\x2"+
		"\x2\x2\x1007\x1008\x3\x2\x2\x2\x1008\x100A\x3\x2\x2\x2\x1009\x100B\x5"+
		"\x23D\x11F\x2\x100A\x1009\x3\x2\x2\x2\x100A\x100B\x3\x2\x2\x2\x100B\x1013"+
		"\x3\x2\x2\x2\x100C\x100E\t\x11\x2\x2\x100D\x100C\x3\x2\x2\x2\x100E\x100F"+
		"\x3\x2\x2\x2\x100F\x100D\x3\x2\x2\x2\x100F\x1010\x3\x2\x2\x2\x1010\x1011"+
		"\x3\x2\x2\x2\x1011\x1013\x5\x23D\x11F\x2\x1012\x1000\x3\x2\x2\x2\x1012"+
		"\x100D\x3\x2\x2\x2\x1013\x218\x3\x2\x2\x2\x1014\x1017\a)\x2\x2\x1015\x1018"+
		"\n\x12\x2\x2\x1016\x1018\x5\x22F\x118\x2\x1017\x1015\x3\x2\x2\x2\x1017"+
		"\x1016\x3\x2\x2\x2\x1018\x1019\x3\x2\x2\x2\x1019\x101A\a)\x2\x2\x101A"+
		"\x21A\x3\x2\x2\x2\x101B\x1020\a$\x2\x2\x101C\x101F\n\x12\x2\x2\x101D\x101F"+
		"\x5\x22F\x118\x2\x101E\x101C\x3\x2\x2\x2\x101E\x101D\x3\x2\x2\x2\x101F"+
		"\x1022\x3\x2\x2\x2\x1020\x101E\x3\x2\x2\x2\x1020\x1021\x3\x2\x2\x2\x1021"+
		"\x1023\x3\x2\x2\x2\x1022\x1020\x3\x2\x2\x2\x1023\x1024\a$\x2\x2\x1024"+
		"\x21C\x3\x2\x2\x2\x1025\x1028\x5\x21F\x110\x2\x1026\x1028\x5\x221\x111"+
		"\x2\x1027\x1025\x3\x2\x2\x2\x1027\x1026\x3\x2\x2\x2\x1028\x21E\x3\x2\x2"+
		"\x2\x1029\x102A\av\x2\x2\x102A\x102B\at\x2\x2\x102B\x102C\aw\x2\x2\x102C"+
		"\x103C\ag\x2\x2\x102D\x102E\a\x30\x2\x2\x102E\x102F\av\x2\x2\x102F\x1030"+
		"\at\x2\x2\x1030\x1031\aw\x2\x2\x1031\x103C\ag\x2\x2\x1032\x1033\aV\x2"+
		"\x2\x1033\x1034\aT\x2\x2\x1034\x1035\aW\x2\x2\x1035\x103C\aG\x2\x2\x1036"+
		"\x1037\a\x30\x2\x2\x1037\x1038\aV\x2\x2\x1038\x1039\aT\x2\x2\x1039\x103A"+
		"\aW\x2\x2\x103A\x103C\aG\x2\x2\x103B\x1029\x3\x2\x2\x2\x103B\x102D\x3"+
		"\x2\x2\x2\x103B\x1032\x3\x2\x2\x2\x103B\x1036\x3\x2\x2\x2\x103C\x220\x3"+
		"\x2\x2\x2\x103D\x103E\ah\x2\x2\x103E\x103F\a\x63\x2\x2\x103F\x1040\an"+
		"\x2\x2\x1040\x1041\au\x2\x2\x1041\x1054\ag\x2\x2\x1042\x1043\a\x30\x2"+
		"\x2\x1043\x1044\ah\x2\x2\x1044\x1045\a\x63\x2\x2\x1045\x1046\an\x2\x2"+
		"\x1046\x1047\au\x2\x2\x1047\x1054\ag\x2\x2\x1048\x1049\aH\x2\x2\x1049"+
		"\x104A\a\x43\x2\x2\x104A\x104B\aN\x2\x2\x104B\x104C\aU\x2\x2\x104C\x1054"+
		"\aG\x2\x2\x104D\x104E\a\x30\x2\x2\x104E\x104F\aH\x2\x2\x104F\x1050\a\x43"+
		"\x2\x2\x1050\x1051\aN\x2\x2\x1051\x1052\aU\x2\x2\x1052\x1054\aG\x2\x2"+
		"\x1053\x103D\x3\x2\x2\x2\x1053\x1042\x3\x2\x2\x2\x1053\x1048\x3\x2\x2"+
		"\x2\x1053\x104D\x3\x2\x2\x2\x1054\x222\x3\x2\x2\x2\x1055\x1056\a&\x2\x2"+
		"\x1056\x1057\a\x65\x2\x2\x1057\x1058\ap\x2\x2\x1058\x1066\av\x2\x2\x1059"+
		"\x105A\a&\x2\x2\x105A\x105B\a\x45\x2\x2\x105B\x105C\aP\x2\x2\x105C\x1066"+
		"\aV\x2\x2\x105D\x105E\a\x30\x2\x2\x105E\x105F\a\x65\x2\x2\x105F\x1060"+
		"\ap\x2\x2\x1060\x1066\av\x2\x2\x1061\x1062\a\x30\x2\x2\x1062\x1063\a\x45"+
		"\x2\x2\x1063\x1064\aP\x2\x2\x1064\x1066\aV\x2\x2\x1065\x1055\x3\x2\x2"+
		"\x2\x1065\x1059\x3\x2\x2\x2\x1065\x105D\x3\x2\x2\x2\x1065\x1061\x3\x2"+
		"\x2\x2\x1066\x224\x3\x2\x2\x2\x1067\x106B\x5\x227\x114\x2\x1068\x106A"+
		"\x5\x229\x115\x2\x1069\x1068\x3\x2\x2\x2\x106A\x106D\x3\x2\x2\x2\x106B"+
		"\x1069\x3\x2\x2\x2\x106B\x106C\x3\x2\x2\x2\x106C\x226\x3\x2\x2\x2\x106D"+
		"\x106B\x3\x2\x2\x2\x106E\x106F\t\x13\x2\x2\x106F\x228\x3\x2\x2\x2\x1070"+
		"\x1071\t\x14\x2\x2\x1071\x22A\x3\x2\x2\x2\x1072\x1073\a&\x2\x2\x1073\x1074"+
		"\a>\x2\x2\x1074\x1075\ap\x2\x2\x1075\x1076\aq\x2\x2\x1076\x1077\ap\x2"+
		"\x2\x1077\x1078\ag\x2\x2\x1078\x1079\a@\x2\x2\x1079\x107A\a&\x2\x2\x107A"+
		"\x22C\x3\x2\x2\x2\x107B\x107C\v\x2\x2\x2\x107C\x22E\x3\x2\x2\x2\x107D"+
		"\x1080\x5\x231\x119\x2\x107E\x1080\x5\x233\x11A\x2\x107F\x107D\x3\x2\x2"+
		"\x2\x107F\x107E\x3\x2\x2\x2\x1080\x230\x3\x2\x2\x2\x1081\x1082\a^\x2\x2"+
		"\x1082\x109F\ak\x2\x2\x1083\x1084\a^\x2\x2\x1084\x109F\ar\x2\x2\x1085"+
		"\x1086\a^\x2\x2\x1086\x109F\ah\x2\x2\x1087\x1088\a^\x2\x2\x1088\x109F"+
		"\a\x64\x2\x2\x1089\x108A\a^\x2\x2\x108A\x109F\aK\x2\x2\x108B\x108C\a^"+
		"\x2\x2\x108C\x109F\aq\x2\x2\x108D\x108E\a^\x2\x2\x108E\x109F\a\x63\x2"+
		"\x2\x108F\x1090\a^\x2\x2\x1090\x109F\av\x2\x2\x1091\x1092\a^\x2\x2\x1092"+
		"\x109F\aR\x2\x2\x1093\x1094\a^\x2\x2\x1094\x109F\a\x45\x2\x2\x1095\x1096"+
		"\a^\x2\x2\x1096\x109F\a)\x2\x2\x1097\x1098\a^\x2\x2\x1098\x109F\a$\x2"+
		"\x2\x1099\x109A\a^\x2\x2\x109A\x109F\a^\x2\x2\x109B\x109C\a^\x2\x2\x109C"+
		"\x109F\a\x32\x2\x2\x109D\x109F\a^\x2\x2\x109E\x1081\x3\x2\x2\x2\x109E"+
		"\x1083\x3\x2\x2\x2\x109E\x1085\x3\x2\x2\x2\x109E\x1087\x3\x2\x2\x2\x109E"+
		"\x1089\x3\x2\x2\x2\x109E\x108B\x3\x2\x2\x2\x109E\x108D\x3\x2\x2\x2\x109E"+
		"\x108F\x3\x2\x2\x2\x109E\x1091\x3\x2\x2\x2\x109E\x1093\x3\x2\x2\x2\x109E"+
		"\x1095\x3\x2\x2\x2\x109E\x1097\x3\x2\x2\x2\x109E\x1099\x3\x2\x2\x2\x109E"+
		"\x109B\x3\x2\x2\x2\x109E\x109D\x3\x2\x2\x2\x109F\x232\x3\x2\x2\x2\x10A0"+
		"\x10A1\a^\x2\x2\x10A1\x10A2\az\x2\x2\x10A2\x10A3\x3\x2\x2\x2\x10A3\x10AB"+
		"\x5\x235\x11B\x2\x10A4\x10A5\a^\x2\x2\x10A5\x10A6\az\x2\x2\x10A6\x10A7"+
		"\x3\x2\x2\x2\x10A7\x10A8\x5\x235\x11B\x2\x10A8\x10A9\x5\x235\x11B\x2\x10A9"+
		"\x10AB\x3\x2\x2\x2\x10AA\x10A0\x3\x2\x2\x2\x10AA\x10A4\x3\x2\x2\x2\x10AB"+
		"\x234\x3\x2\x2\x2\x10AC\x10AE\t\x15\x2\x2\x10AD\x10AC\x3\x2\x2\x2\x10AE"+
		"\x236\x3\x2\x2\x2\x10AF\x10B0\t\x16\x2\x2\x10B0\x238\x3\x2\x2\x2\x10B1"+
		"\x10B4\x5\x237\x11C\x2\x10B2\x10B4\x4:;\x2\x10B3\x10B1\x3\x2\x2\x2\x10B3"+
		"\x10B2\x3\x2\x2\x2\x10B4\x23A\x3\x2\x2\x2\x10B5\x10B7\x4\x32\x33\x2\x10B6"+
		"\x10B8\a\x61\x2\x2\x10B7\x10B6\x3\x2\x2\x2\x10B7\x10B8\x3\x2\x2\x2\x10B8"+
		"\x23C\x3\x2\x2\x2\x10B9\x10BC\t\b\x2\x2\x10BA\x10BD\x5!\x11\x2\x10BB\x10BD"+
		"\x5#\x12\x2\x10BC\x10BA\x3\x2\x2\x2\x10BC\x10BB\x3\x2\x2\x2\x10BC\x10BD"+
		"\x3\x2\x2\x2\x10BD\x10BF\x3\x2\x2\x2\x10BE\x10C0\t\x11\x2\x2\x10BF\x10BE"+
		"\x3\x2\x2\x2\x10C0\x10C1\x3\x2\x2\x2\x10C1\x10BF\x3\x2\x2\x2\x10C1\x10C2"+
		"\x3\x2\x2\x2\x10C2\x23E\x3\x2\x2\x2\x11A\x2\x242\x24C\x256\x25B\x25F\x263"+
		"\x265\x2E1\x2F0\x2FF\x30E\x314\x31A\x320\x326\x32C\x332\x338\x340\x348"+
		"\x34E\x354\x35A\x366\x370\x37A\x382\x38A\x392\x39A\x3A2\x3AA\x3B4\x3BC"+
		"\x3C4\x3CA\x3D0\x3D8\x3E2\x3EC\x3F4\x3FC\x404\x40C\x414\x41E\x426\x42E"+
		"\x436\x440\x44A\x454\x45E\x468\x472\x47C\x486\x490\x496\x49E\x4A6\x4AC"+
		"\x4B4\x4BC\x4C4\x4CC\x4D4\x4DC\x4E2\x4E8\x4F2\x4F8\x4FE\x508\x510\x51A"+
		"\x522\x528\x530\x536\x53E\x546\x54C\x552\x55A\x562\x56A\x572\x57A\x582"+
		"\x58A\x59A\x5A2\x5AC\x5BA\x5C4\x5D4\x5E2\x5EC\x5F8\x602\x60E\x61E\x62E"+
		"\x63A\x648\x65C\x6B9\x6CD\x6E1\x6F1\x705\x715\x727\x73B\x759\x777\x795"+
		"\x7B3\x7D1\x7F7\x815\x81A\x81F\x83D\x851\x86D\x88B\x8A3\x8BB\x8D3\x8FB"+
		"\x913\x92B\x94F\x96F\x987\x9FB\xA27\xA47\xA5F\xA75\xA81\xA97\xAA3\xAB9"+
		"\xAC9\xAD7\xAE5\xAFB\xB07\xB23\xB43\xB4F\xB5B\xB69\xB79\xB85\xB99\xBA5"+
		"\xBAF\xBBD\xBD1\xC03\xC95\xCB1\xCBD\xCDA\xCF0\xCFE\xD0E\xD18\xD22\xD2A"+
		"\xD38\xD4C\xD62\xD76\xD86\xD9C\xDB2\xDCE\xDDE\xDFA\xE12\xE20\xE2E\xE3E"+
		"\xE4C\xE5A\xE6A\xE78\xE86\xE96\xEA4\xEB2\xEC2\xED0\xEDE\xEEE\xEFE\xF0E"+
		"\xF1E\xF2E\xF3E\xF4E\xF54\xF58\xF5B\xF5E\xF62\xF65\xF68\xF6B\xF6F\xF74"+
		"\xF77\xF7B\xF7E\xF81\xF84\xF87\xF8A\xF8D\xF90\xF93\xF96\xF99\xF9C\xF9F"+
		"\xFA2\xFA5\xFA8\xFAC\xFAF\xFB2\xFB5\xFB8\xFBB\xFBE\xFC1\xFC4\xFC7\xFCA"+
		"\xFCD\xFD0\xFD3\xFD6\xFDA\xFDE\xFE1\xFE4\xFE7\xFEA\xFF0\xFF3\xFF6\xFF9"+
		"\x1000\x1007\x100A\x100F\x1012\x1017\x101E\x1020\x1027\x103B\x1053\x1065"+
		"\x106B\x107F\x109E\x10AA\x10AD\x10B3\x10B7\x10BC\x10C1\x3\x2\x3\x2";
	public static readonly ATN _ATN =
		new ATNDeserializer().Deserialize(_serializedATN.ToCharArray());
}
} // namespace Spect.Net.Assembler.Generated


<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/Commands/DebugDefaultProgramCommand.cs<|end_filename|>
﻿using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Spect.Net.VsPackage.VsxLibrary.Command;

namespace Spect.Net.VsPackage.Commands
{
    /// <summary>
    /// This command debugs the default program within the active project.
    /// </summary>
    [CommandId(0x0807)]
    public class DebugDefaultProgramCommand : DebugProgramCommand
    {
        /// <summary>
        /// The item is allowed only when there is a default code file selected
        /// </summary>
        protected override void OnQueryStatus(OleMenuCommand mc)
        {
            base.OnQueryStatus(mc);
            if (!mc.Visible) return;

            var project = HostPackage.ActiveProject;
            var visible = project.DefaultProgramItem != null;
            if (visible)
            {
                project.GetHierarchyByIdentity(project.DefaultProgramItem.Identity, out var hierarchy, out _);
                visible &= hierarchy != null;
            }
            mc.Visible = visible;
        }

        /// <summary>
        /// Gets the document that this command should use
        /// </summary>
        /// <param name="hierarchy"></param>
        /// <param name="itemId"></param>
        protected override void GetAffectedItem(out IVsHierarchy hierarchy, out uint itemId)
        {
            // --- We have a project item, let's query the default code file
            var currentProject = SpectNetPackage.Default.Solution.ActiveProject;
            currentProject.GetHierarchyByIdentity(currentProject.DefaultProgramItem.Identity,
                out hierarchy, out itemId);
        }
    }
}

<|start_filename|>v2/Core/Spect.Net.SpectrumEmu/Abstraction/ISpectrumMachine.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using Spect.Net.SpectrumEmu.Abstraction.Configuration;
using Spect.Net.SpectrumEmu.Abstraction.Devices.Screen;
using Spect.Net.SpectrumEmu.Abstraction.Machine;
using Spect.Net.SpectrumEmu.Abstraction.Providers;
using Spect.Net.SpectrumEmu.Machine;

namespace Spect.Net.SpectrumEmu.Abstraction
{
    /// <summary>
    /// This class represents the API of a ZX Spectrum virtual machine.
    /// </summary>
    public interface ISpectrumMachine: ISpectrumVmController
    {
        /// <summary>
        /// The current machine's model key.
        /// </summary>
        string ModelKey { get; }

        /// <summary>
        /// The current machine's edition key.
        /// </summary>
        string EditionKey { get; }

        /// <summary>
        /// Indicates if fast tape mode is allowed.
        /// </summary>
        bool FastTapeMode { get; set; }

        /// <summary>
        /// The CPU of the machine
        /// </summary>
        CpuZ80 Cpu { get; }

        /// <summary>
        /// Provides access to the individual ROM pages of the machine
        /// </summary>
        IReadOnlyList<ReadOnlyMemorySlice> Roms { get; }

        /// <summary>
        /// Gets the number of ROM pages
        /// </summary>
        int RomCount { get; }

        /// <summary>
        /// Allows to obtain paging information about the memory
        /// </summary>
        MemoryPagingInfo PagingInfo { get; }

        /// <summary>
        /// The current Contents of the machine's 64K addressable memory
        /// </summary>
        SpectrumMemoryContents Memory { get; }

        /// <summary>
        /// Provides access to the individual RAM banks of the machine
        /// </summary>
        IReadOnlyList<MemorySlice> RamBanks { get; }

        /// <summary>
        /// Gets the number of RAM banks
        /// </summary>
        int RamBankCount { get; }

        /// <summary>
        /// Allows to emulate keyboard keys and query the keyboard state
        /// </summary>
        KeyboardEmulator Keyboard { get; }

        /// <summary>
        /// Allows read-only access to screen rendering configuration
        /// </summary>
        ScreenConfiguration ScreenConfiguration { get; }

        /// <summary>
        /// Allows read-only access to the screen rendering table
        /// </summary>
        ScreenRenderingTable ScreenRenderingTable { get; }

        /// <summary>
        /// A bitmap that represents the current visible screen's pixels, including the border
        /// </summary>
        ScreenBitmap ScreenBitmap { get; }

        /// <summary>
        /// Gets the current screen rendering status of the machine.
        /// </summary>
        ScreenRenderingStatus ScreenRenderingStatus { get; }

        /// <summary>
        /// Gets the beeper configuration of the machine
        /// </summary>
        IAudioConfiguration BeeperConfiguration { get; }

        /// <summary>
        /// Gets the beeper samples of the current rendering frame
        /// </summary>
        AudioSamples BeeperSamples { get; }

        /// <summary>
        /// The beeper provider associated with the machine
        /// </summary>
        IBeeperProvider BeeperProvider { get; }

        /// <summary>
        /// Gets the sound (PSG) configuration of the machine
        /// </summary>
        IAudioConfiguration SoundConfiguration { get; }

        /// <summary>
        /// Gets the sound (PSG) samples of the current rendering frame
        /// </summary>
        AudioSamples AudioSamples { get; }

        /// <summary>
        /// The beeper provider associated with the machine
        /// </summary>
        ISoundProvider SoundProvider { get; }

        /// <summary>
        /// The collection of breakpoints
        /// </summary>
        CodeBreakpoints Breakpoints { get; }

        /// <summary>
        /// Gets the reason that tells why the machine has been stopped or paused
        /// </summary>
        ExecutionCompletionReason ExecutionCompletionReason { get; }

        /// <summary>
        /// The number of CPU frame counts since the machine has started.
        /// </summary>
        int CpuFrameCount { get; }

        /// <summary>
        /// The number of render frame counts since the machine has started.
        /// </summary>
        int RenderFrameCount { get; }

        /// <summary>
        /// The length of last CPU frame in ticks
        /// </summary>
        long LastCpuFrameTicks { get; }

        /// <summary>
        /// The length of last render frame in ticks
        /// </summary>
        long LastRenderFrameTicks { get; }

        /// <summary>
        /// The CPU tact at which the last execution cycle started
        /// </summary>
        long LastExecutionStartTact { get; }

        /// <summary>
        /// The current screen rendering frame tact
        /// </summary>
        int CurrentFrameTact { get; }

        /// <summary>
        /// This event is raised when the state of the virtual machine has been changed.
        /// </summary>
        event EventHandler<VmStateChangedEventArgs> VmStateChanged;

        /// <summary>
        /// This event is executed when it is time to scan the ZX Spectrum keyboard.
        /// </summary>
        event EventHandler<KeyStatusEventArgs> KeyScanning;

        /// <summary>
        /// This event is executed whenever the CPU frame has been completed.
        /// </summary>
        event EventHandler<CancelEventArgs> CpuFrameCompleted;

        /// <summary>
        /// This event is executed whenever the render frame has been completed.
        /// </summary>
        event EventHandler<RenderFrameEventArgs> RenderFrameCompleted;

        /// <summary>
        /// This event is raised when a fast load operation has been completed.
        /// </summary>
        event EventHandler FastLoadCompleted;

        /// <summary>
        /// This event fires when the virtual machine engine raised an exception.
        /// </summary>
        event EventHandler<VmExceptionArgs> ExceptionRaised;

        /// <summary>
        /// Starts the machine in a background thread with the specified options.
        /// </summary>
        /// <remarks>
        /// Reports completion when the machine starts executing its cycles. The machine can
        /// go into Paused or Stopped state, if the execution options allow, for example, 
        /// when it runs to a predefined breakpoint.
        /// </remarks>
        void StartWithOptions(ExecuteCycleOptions options);

        /// <summary>
        /// Starts the machine in a background thread in continuous running mode.
        /// </summary>
        /// <remarks>
        /// Reports completion when the machine starts executing its cycles. The machine can
        /// go into Paused or Stopped state, if the execution options allow, for example, 
        /// when it runs to a predefined breakpoint.
        /// </remarks>
        void Start();

        /// <summary>
        /// Starts the Spectrum machine and runs it on a background thread unless it reaches a breakpoint.
        /// </summary>
        void StartDebug();

        /// <summary>
        /// Executes the subsequent Z80 instruction.
        /// </summary>
        /// <remarks>
        /// The task completes when the machine has completed its execution cycle.
        /// </remarks>
        Task StepInto();

        /// <summary>
        /// Executes the subsequent Z80 CALL, RST, or block instruction entirely.
        /// </summary>
        /// <remarks>
        /// The task completes when the machine has completed its execution cycle.
        /// </remarks>
        Task StepOver();

        /// <summary>
        /// Executes the subsequent Z80 CALL, RST, or block instruction entirely.
        /// </summary>
        /// <remarks>
        /// The task completes when the machine has completed its execution cycle.
        /// </remarks>
        Task StepOut();
    }
}

<|start_filename|>v2/Tests/Spect.Net.Assembler.Test/Assembler/MacroArgumentEmitTests.cs<|end_filename|>
﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shouldly;
using Spect.Net.Assembler.Assembler;

namespace Spect.Net.Assembler.Test.Assembler
{
    [TestClass]
    public class MacroArgumentEmitTests: AssemblerTestBed
    {
        [TestMethod]
        public void MacroArgumentInGlobalScopeFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                {{MyParam}}
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0420);
        }

        [TestMethod]
        public void MacroArgumentInLocalScopeFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                .loop 3
                {{MyParam}}
                .endl
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0420);
        }

        [TestMethod]
        public void MacroArgumentInArgumentlessMacroDeclarationFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro()
                {{MyParam}}
                .endm
                MyMacro()
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(2);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0403);
        }

        [TestMethod]
        public void SingleMacroArgumentWithNumberWorks()
        {
            const string SOURCE = @"
                MyMacro: .macro(MyArg)
                ld a,{{MyArg}}
                .endm
                MyMacro(#A3)";

            CodeEmitWorks(SOURCE, 0x3E, 0xA3);
        }

        [TestMethod]
        public void SingleMacroArgumentWithNumberWorksCs1()
        {
            const string SOURCE = @"
                MyMacro: .macro(MyArg)
                ld a,{{MyArg}}
                .endm
                MyMacro(#A3)";

            CodeEmitWorksWithOptions(new AssemblerOptions { UseCaseSensitiveSymbols = true },  SOURCE, 0x3E, 0xA3);
        }

        [TestMethod]
        public void SingleMacroArgumentWithNumberWorksCs2()
        {
            const string SOURCE = @"
                MyMacro: .macro(myArg)
                ld a,{{MyArg}}
                .endm
                myMacro(#A3)";

            CodeEmitWorksWithOptions(new AssemblerOptions { UseCaseSensitiveSymbols = false }, SOURCE, 0x3E, 0xA3);
        }

        [TestMethod]
        public void SingleMacroArgumentWithNumberWorksCs3()
        {
            const string SOURCE = @"
                MyMacro: .macro(myArg)
                ld a,{{MyArg}}
                .endm
                myMacro(#A3)";

            CodeRaisesMultipleErrors(SOURCE, new AssemblerOptions { UseCaseSensitiveSymbols = true }, 
                Errors.Z0403, Errors.Z0418);
        }

        [TestMethod]
        [DataRow("a", 0x7F)]
        [DataRow("b", 0x78)]
        [DataRow("c", 0x79)]
        [DataRow("d", 0x7A)]
        [DataRow("e", 0x7B)]
        [DataRow("h", 0x7C)]
        [DataRow("l", 0x7D)]
        public void SingleMacroArgumentWith8BitRegisterWorks(string reg, int expected)
        {
            var source = @"
                MyMacro: .macro(MyArg)
                ld a,{{MyArg}}
                .endm
                MyMacro(" + reg + @")";

            CodeEmitWorks(source, (byte)expected);
        }

        [TestMethod]
        [DataRow("xl", 0xDD, 0x6F)]
        [DataRow("ixl", 0xDD, 0x6F)]
        [DataRow("xh", 0xDD, 0x67)]
        [DataRow("ixh", 0xDD, 0x67)]
        [DataRow("yl", 0xFD, 0x6F)]
        [DataRow("iyl", 0xFD, 0x6F)]
        [DataRow("yh", 0xFD, 0x67)]
        [DataRow("iyh", 0xFD, 0x67)]
        public void SingleMacroArgumentWith8BitIndexRegisterWorks(string reg, int exp1, int exp2)
        {
            var source = @"
                MyMacro: .macro(MyArg)
                ld {{MyArg}},a
                .endm
                MyMacro(" + reg + @")";

            CodeEmitWorks(source, (byte)exp1, (byte)exp2);
        }

        [TestMethod]
        [DataRow("i", 0x47)]
        [DataRow("r", 0x4F)]
        public void SingleMacroArgumentWith8BitSpecRegisterWorks(string reg, int expected)
        {
            var source = @"
                MyMacro: .macro(MyArg)
                ld {{MyArg}},a
                .endm
                MyMacro(" + reg + @")";

            CodeEmitWorks(source, 0xED, (byte)expected);
        }

        [TestMethod]
        [DataRow("bc", 0x03)]
        [DataRow("de", 0x13)]
        [DataRow("hl", 0x23)]
        [DataRow("sp", 0x33)]
        public void SingleMacroArgumentWith16BitRegisterWorks(string reg, int expected)
        {
            var source = @"
                MyMacro: .macro(MyArg)
                inc {{MyArg}}
                .endm
                MyMacro(" + reg + @")";

            CodeEmitWorks(source, (byte)expected);
        }

        [TestMethod]
        [DataRow("push {{MyArg}}", "af", 0xF5)]
        [DataRow("ex af,{{MyArg}}", "af'", 0x08)]
        public void SingleMacroArgumentWith16BitSpecRegisterWorks(string instr, string reg, int expected)
        {
            var source = @"
                MyMacro: .macro(MyArg)
                " + instr + @"
                .endm
                MyMacro(" + reg + @")";

            CodeEmitWorks(source, (byte)expected);
        }

        [TestMethod]
        [DataRow("(bc)", 0x0A)]
        [DataRow("(de)", 0x1A)]
        [DataRow("(hl)", 0x7E)]
        public void SingleMacroArgumentWith16BitRegIndirectWorks(string reg, int expected)
        {
            var source = @"
                MyMacro: .macro(MyArg)
                ld a,{{MyArg}}
                .endm
                MyMacro(" + reg + @")";

            CodeEmitWorks(source, (byte)expected);
        }

        [TestMethod]
        public void SingleMacroArgumentWithCPortWorks()
        {
            const string SOURCE = @"
                MyMacro: .macro(MyArg)
                out {{MyArg}},a
                .endm
                MyMacro((c))";

            CodeEmitWorks(SOURCE, 0xED, 0x79);
        }

        [TestMethod]
        [DataRow("(#1000)", 0x00, 0x10)]
        [DataRow("(#1000+#0800)", 0x00, 0x18)]
        public void SingleMacroArgumentWithMemIndirectWorks(string memind, int exp1, int exp2)
        {
            var source = @"
                MyMacro: .macro(MyArg)
                ld a,{{MyArg}}
                .endm
                MyMacro(" + memind + @")";

            CodeEmitWorks(source, 0x3A, (byte)exp1, (byte)exp2);
        }

        [TestMethod]
        [DataRow("(ix+#12)", 0xDD, 0x7E, 0x12)]
        [DataRow("(ix-#12)", 0xDD, 0x7E, 0xEE)]
        [DataRow("(iy+#12)", 0xFD, 0x7E, 0x12)]
        [DataRow("(iy-#12)", 0xFD, 0x7E, 0xEE)]
        [DataRow("(ix)", 0xDD, 0x7E, 0x00)]
        [DataRow("(iy)", 0xFD, 0x7E, 0x00)]
        public void SingleMacroArgumentWithIndexedAddrWorks(string memind, int exp1, int exp2, int exp3)
        {
            var source = @"
                MyMacro: .macro(MyArg)
                ld a,{{MyArg}}
                .endm
                MyMacro(" + memind + @")";

            CodeEmitWorks(source, (byte)exp1, (byte)exp2, (byte)exp3);
        }

        [TestMethod]
        [DataRow("z", 0xCC)]
        [DataRow("nz", 0xC4)]
        [DataRow("c", 0xDC)]
        [DataRow("nc", 0xD4)]
        [DataRow("pe", 0xEC)]
        [DataRow("po", 0xE4)]
        [DataRow("m", 0xFC)]
        [DataRow("p", 0xF4)]
        public void SingleMacroArgumentWithConditionWorks(string cond, int expected)
        {
            var source = @"
                MyMacro: .macro(MyArg)
                call {{MyArg}},#1000
                .endm
                MyMacro(" + cond + @")";

            CodeEmitWorks(source, (byte)expected, 0x00, 0x10);
        }

        [TestMethod]
        [DataRow("a", "#A3", 0x3E, 0xA3)]
        [DataRow("b", "#A4", 0x06, 0xA4)]
        public void MultipleMacroArgumentWithNumberWorks(string reg, string expr, int exp1, int exp2)
        {
            var source = @"
                MyMacro: .macro(first, second)
                ld {{first}},{{second}}
                .endm
                MyMacro(" + reg + "," + expr + ")";

            CodeEmitWorks(source, (byte)exp1, (byte)exp2);
        }

        [TestMethod]
        public void MacroWithInstructionWorks()
        {
            const string SOURCE = @"
                MyMacro: .macro(MyArg)
                {{MyArg}}
                .endm
                MyMacro(""ld a,b"")";

            CodeEmitWorks(SOURCE, 0x78);
        }

        [TestMethod]
        public void MacroWithMultilineInstructionWorks()
        {
            const string SOURCE = @"
                MyMacro: .macro(MyArg)
                {{MyArg}}
                .endm
                MyMacro(""ld a,b"" & ""ld a,c"")";

            CodeEmitWorks(SOURCE, 0x78, 0x79);
        }

        [TestMethod]
        public void MacroWithLabeledInstructionWorks()
        {
            const string SOURCE = @"
                MyMacro: .macro(MyArg)
                {{MyArg}}
                .endm
                MyMacro(""MyLabel: jp MyLabel"")";

            CodeEmitWorks(SOURCE, 0xC3, 0x00, 0x80);
        }

        [TestMethod]
        public void MacroWithDoubleLabeledInstructionFails()
        {
            const string SOURCE = @"
                MyMacro: .macro(MyArg)
                Label: {{MyArg}}
                .endm
                MyMacro(""MyLabel: jp MyLabel"")";

            CodeRaisesError(SOURCE, Errors.Z0100);
        }

        [TestMethod]
        public void MacroWithLabeledInstructionAndMultipleInvokeWorks()
        {
            const string SOURCE = @"
                MyMacro: .macro(MyArg)
                {{MyArg}}
                .endm
                MyMacro(""MyLabel: jp MyLabel"")
                MyMacro(""MyLabel: jp MyLabel"")";

            CodeEmitWorks(SOURCE, 0xC3, 0x00, 0x80, 0xC3, 0x03, 0x80);
        }

        [TestMethod]
        public void MacroWithLoopInjectionWorks()
        {
            const string SOURCE = @"
                MyMacro: .macro(MyArg)
                {{MyArg}}
                .endm
                MyMacro("".loop 3"" & ""ld a,b"" & "".endl"")";

            CodeEmitWorks(SOURCE, 0x78, 0x78, 0x78);
        }

        [TestMethod]
        public void MacroLoopWithArgumentInjectionWorks()
        {
            const string SOURCE = @"
                Repeat: .macro(count, body)
                    .loop {{count}}
                    {{body}}
                    .endl
                .endm
                Repeat(3, ""ld a,b"")";

            CodeEmitWorks(SOURCE, 0x78, 0x78, 0x78);
        }

        [TestMethod]
        public void LregAndHregWorksWithMacroParam()
        {
            const string SOURCE = @"
                LdHl: .macro(reg16)
                    ld h,hreg({{reg16}})
                    ld l,lreg({{reg16}})
                .endm
                LdHl(de)";

            CodeEmitWorks(SOURCE, 0x62, 0x6B);
        }


    }
}


<|start_filename|>v2/Assembler/Spect.Net.Assembler/SyntaxTree/Pragmas/InjectOptionPragma.cs<|end_filename|>
﻿using Spect.Net.Assembler.Generated;

namespace Spect.Net.Assembler.SyntaxTree.Pragmas
{
    /// <summary>
    /// This class represents the MODEL pragma
    /// </summary>
    public sealed class InjectOptionPragma : PragmaBase
    {
        /// <summary>
        /// The Spectrum model to use
        /// </summary>
        public string Option { get; set; }

        public InjectOptionPragma(Z80AsmParser.InjectOptPragmaContext context)
        {
            if (context.IDENTIFIER() != null)
            {
                Option = context.IDENTIFIER().NormalizeToken();
            }
        }
    }
}


<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/Dialogs/Export/ExportFormat.cs<|end_filename|>
﻿namespace Spect.Net.VsPackage.Dialogs.Export
{
    /// <summary>
    /// Enum for tape file formats
    /// </summary>
    public enum ExportFormat
    {
        Unknown,
        Tap,
        Tzx,
        IntelHex,
    }
}


<|start_filename|>v2/Assembler/Spect.Net.Assembler/Assembler/Z80Assembler.Emit.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Antlr4.Runtime;
using Spect.Net.Assembler.Generated;
using Spect.Net.Assembler.SyntaxTree;
using Spect.Net.Assembler.SyntaxTree.Expressions;
using Spect.Net.Assembler.SyntaxTree.Operations;
using Spect.Net.Assembler.SyntaxTree.Pragmas;
using Spect.Net.Assembler.SyntaxTree.Statements;

// ReSharper disable IdentifierTypo
// ReSharper disable CommentTypo
// ReSharper disable StringLiteralTypo
// ReSharper disable InlineOutVariableDeclaration
// ReSharper disable UsePatternMatching

namespace Spect.Net.Assembler.Assembler
{
    /// <summary>
    /// This class implements the Z80 assembler
    /// </summary>
    public partial class Z80Assembler
    {
        public static readonly Regex MacroParamRegex = new Regex(@"{{\s*([_a-zA-Z][_a-zA-Z0-9]*)\s*}}");

        /// <summary>
        /// A structure body can contain only these instruction types
        /// </summary>
        public static readonly HashSet<Type> StructBodyStatementTypes = new HashSet<Type>
        {
            typeof(NoInstructionLine),
            typeof(DefbPragma),
            typeof(DefwPragma),
            typeof(DefmnPragma),
            typeof(DefhPragma),
            typeof(DefsPragma),
            typeof(FillbPragma),
            typeof(FillwPragma),
            typeof(DefgxPragma),
            typeof(DefgPragma)
        };

        /// <summary>
        /// The current output segment of the emitted code
        /// </summary>
        public BinarySegment CurrentSegment { get; private set; }

        /// <summary>
        /// The current source line being processed
        /// </summary>
        public SourceLineBase CurrentSourceLine { get; private set; }

        /// <summary>
        /// A label that overflew from a label-only line
        /// </summary>
        public NoInstructionLine OverflowLabelLine { get; private set; }

        /// <summary>
        /// The current list item being processed.
        /// </summary>
        public ListFileItem CurrentListFileItem { get; private set; }

        /// <summary>
        /// Gets the current assembly address (represented by the "$" sign
        /// in the assembly language)
        /// </summary>
        /// <returns></returns>
        public ushort GetCurrentAssemblyAddress()
        {
            EnsureCodeSegment();
            return (ushort)(CurrentSegment.StartAddress 
                + (CurrentSegment?.Displacement ?? 0)
                + CurrentSegment.EmittedCode.Count);
        }

        /// <summary>
        /// Gets the current assembly address (represented by the "$" sign
        /// in the assembly language)
        /// </summary>
        /// <returns></returns>
        public ushort GetCurrentInstructionAddress()
        {
            EnsureCodeSegment();
            return (ushort)(CurrentSegment.StartAddress
                            + (CurrentSegment?.Displacement ?? 0)
                            + CurrentSegment.CurrentInstructionOffset);
        }

        /// <summary>
        /// Signs if the compiler is in struct invocation mode
        /// </summary>
        private StructDefinition _currentStructInvocation;

        /// <summary>
        /// The current line that invokes the struct
        /// </summary>
        private MacroOrStructInvocation _currentStructLine;

        /// <summary>
        /// The current bytes to emit for the structure being invoked
        /// </summary>
        private Dictionary<ushort, byte> _currentStructBytes;

        /// <summary>
        /// Start offset of the current struct invocation
        /// </summary>
        private ushort _currentStructStartOffset;

        /// <summary>
        /// Offset of the current strcuture invocation
        /// </summary>
        private int _currentStructOffset;

        /// <summary>
        /// Checks if the compiler is in structure invocation mode
        /// </summary>
        private bool IsInStructInvocation => _currentStructInvocation != null;

        /// <summary>
        /// Signs that the compiler is currently cloning a structure byte pattern
        /// </summary>
        private bool _isInStructCloning;

        /// <summary>
        /// Emits the code after processing the directives
        /// </summary>
        /// <returns></returns>
        private bool EmitCode(List<SourceLineBase> lines)
        {
            // --- Initialize code emission
            Output.Segments.Clear();
            EnsureCodeSegment();

            // --- Iterate through all parsed lines
            var currentLineIndex = 0;
            while (currentLineIndex < lines.Count)
            {
                var asmLine = lines[currentLineIndex];
                EmitSingleLine(lines, lines, asmLine, ref currentLineIndex);

                // --- Next line
                currentLineIndex++;
            }

            // --- Handle the orphan hanging label
            if (OverflowLabelLine != null)
            {
                CreateCurrentPointLabel(OverflowLabelLine);
                OverflowLabelLine = null;
            }

            // --- Handle unclosed field definitions
            if (IsInStructInvocation)
            {
                // --- Check for structure size
                if (_currentStructOffset > _currentStructInvocation.Size)
                {
                    ReportError(Errors.Z0442, _currentStructLine, _currentStructInvocation.StructName,
                        _currentStructInvocation.Size, _currentStructOffset);
                    return false;
                }
                RecordFixup(_currentStructLine, FixupType.Struct, null, null, 
                    _currentStructBytes, _currentStructStartOffset);
            }

            // --- Ok, it's time to return with the result
            return Output.ErrorCount == 0;
        }

        /// <summary>
        /// Emits a single line
        /// </summary>
        /// <param name="allLines">All parsed lines</param>
        /// <param name="scopeLines">Lines to process in the current scope</param>
        /// <param name="asmLine">The line to emit</param>
        /// <param name="currentLineIndex">The index of the line to emit</param>
        /// <param name="fromMacroEmit">Is the method called during macro emit?</param>
        /// <returns></returns>
        private void EmitSingleLine(List<SourceLineBase> allLines, List<SourceLineBase> scopeLines, 
            SourceLineBase asmLine, ref int currentLineIndex, 
            bool fromMacroEmit = false)
        {
            CurrentSourceLine = asmLine;
            CurrentListFileItem = new ListFileItem
            {
                FileIndex = asmLine.FileIndex,
                Address = GetCurrentAssemblyAddress(),
                LineNumber = asmLine.SourceLine,
                SegmentIndex = Output.Segments.Count - 1,
                CodeStartIndex = CurrentSegment.EmittedCode.Count,
                SourceText = asmLine.SourceText,
                CodeLength = 0
            };

            // --- Report any parse-time function issue
            if (asmLine.IssueToEmit != null)
            {
                ReportError(asmLine.IssueToEmit, asmLine);
                return;
            }

            // --- No parse-time issue, process the line
            if (asmLine is NoInstructionLine noInstrLine)
            {
                EmitListItem();
                if (noInstrLine.Label == null) return;

                // --- This is a label-only line
                if (OverflowLabelLine != null)
                {
                    // --- Create a label point for the previous label
                    CreateCurrentPointLabel(OverflowLabelLine);
                }

                OverflowLabelLine = noInstrLine;
            }
            else
            {
                string currentLabel;
                if (OverflowLabelLine == null)
                {
                    // --- No hanging label, use the one in the current line
                    currentLabel = asmLine.Label;
                }
                else
                {
                    if (asmLine.Label == null)
                    {
                        // --- No current label, use the hanging label
                        currentLabel = OverflowLabelLine.Label;
                    }
                    else 
                    {
                        // --- Create a point for the hanging label, and use the current label
                        if (!(_isInStructCloning
                              || asmLine is ISupportsFieldAssignment && IsInStructInvocation))
                        {
                            CreateCurrentPointLabel(OverflowLabelLine);
                        }
                        currentLabel = asmLine.Label;
                        OverflowLabelLine = null;
                    }
                }

                // --- Check if there's a label to create
                if (currentLabel != null)
                {
                    // --- There's a label, we clear the previous hanging label
                    OverflowLabelLine = null;

                    // --- Create the label unless the current pragma does it
                    if (!(asmLine is ILabelSetter 
                        || _isInStructCloning
                        || asmLine is ISupportsFieldAssignment && IsInStructInvocation))
                    {
                        if (!currentLabel.StartsWith("`")
                            && CurrentModule.LocalScopes.Count > 0)
                        {
                            // --- Check if temporary scope should be fixed and disposed
                            var topScope = CurrentModule.LocalScopes.Peek();
                            if (topScope.IsTemporaryScope)
                            {
                                FixupSymbols(topScope.Fixups, topScope.Symbols, false);
                                CurrentModule.LocalScopes.Pop();
                            }
                        }
                        AddSymbol(currentLabel, asmLine, new ExpressionValue(GetCurrentAssemblyAddress()));
                    }
                }

                // --- Let's handle assembly lines with macro parameters
                if (asmLine.MacroParamSpans != null && asmLine.MacroParamSpans.Count > 0)
                {
                    if (fromMacroEmit)
                    {
                        // --- Macro parameters cannot be passed in macro parameters
                        ReportError(Errors.Z0422, asmLine);
                    }
                    if (IsInGlobalScope)
                    {
                        // --- Macro parameters cannot be used in the global scope
                        ReportError(Errors.Z0420, asmLine);
                    }
                    else
                    {
                        // --- Macro argument used outside of a macro definition
                        var scope = CurrentModule.LocalScopes.Peek();
                        if (scope.IsMacroContext) return;

                        if (ShouldReportErrorInCurrentScope(Errors.Z0420))
                        {
                            ReportError(Errors.Z0420, asmLine);
                        }
                    }
                    return;
                }

                // --- Handle field assignment statement
                var isFieldAssignment = asmLine is ISupportsFieldAssignment fieldAsgn
                    && fieldAsgn.IsFieldAssignment;
                if (IsInStructInvocation)
                {
                    // --- We are in a .struct invocation...
                    if (!isFieldAssignment)
                    {
                        // --- ...and just left the invocation scope.
                        // --- Check for structure size
                        if (_currentStructOffset > _currentStructInvocation.Size)
                        {
                            ReportError(Errors.Z0442, asmLine, _currentStructInvocation.StructName,
                                _currentStructInvocation.Size, _currentStructOffset);
                            return;
                        }

                        // --- Complete emitting the structure
                        RecordFixup(_currentStructLine, FixupType.Struct, null, null, 
                            _currentStructBytes, _currentStructStartOffset);
                        _currentStructInvocation = null;
                    }
                    else
                    {
                        if (currentLabel != null)
                        {
                            // --- If there's a label that should be a field
                            if (!_currentStructInvocation.Fields.TryGetValue(currentLabel, out var fieldDefinition))
                            {
                                ReportError(Errors.Z0441, asmLine, _currentStructInvocation.StructName, currentLabel);
                                return;
                            }

                            // --- Use the field offset as the current one for the subsequent emits
                            _currentStructOffset = fieldDefinition.Offset;
                        }
                    }
                }
                else
                {
                    // --- We are outside of a .struct invocation...
                    if (isFieldAssignment)
                    {
                        // --- ... so field assignment is ivalid here.
                        ReportError(Errors.Z0440, asmLine);
                        return;
                    }
                }

                // --- Now, it's time to deal with the assembly line
                if (asmLine is PragmaBase pragmaLine)
                {
                    // --- Process a pragma
                    GetCurrentAssemblyAddress();
                    CurrentSegment.CurrentInstructionOffset = CurrentSegment.EmittedCode.Count;
                    ApplyPragma(pragmaLine, currentLabel);
                    EmitListItem();
                }
                else if (asmLine is StatementBase statement)
                {
                    ProcessStatement(allLines, scopeLines, statement, currentLabel, ref currentLineIndex);
                }
                else if (asmLine is OperationBase opLine)
                {
                    // --- Emit the code output
                    var addr = GetCurrentAssemblyAddress();
                    CurrentSegment.CurrentInstructionOffset = CurrentSegment.EmittedCode.Count;
                    EmitAssemblyOperationCode(opLine);

                    // --- Generate source map information
                    var sourceInfo = (opLine.FileIndex, opLine.SourceLine);
                    Output.SourceMap[addr] = sourceInfo;
                    Output.AddToAddressMap(opLine.FileIndex, opLine.SourceLine, addr);
                    EmitListItem();
                }
            }

            // --- Emits the current list item
            void EmitListItem()
            {
                CurrentListFileItem.CodeLength = CurrentSegment.EmittedCode.Count
                    - CurrentListFileItem.CodeStartIndex;
                Output.ListFileItems.Add(CurrentListFileItem);
            }
        }

        /// <summary>
        /// Creates a label at the current point
        /// </summary>
        /// <param name="asmLine">Assembly line with a label</param>
        private void CreateCurrentPointLabel(SourceLineBase asmLine)
        {
           AddSymbol(asmLine.Label, asmLine, new ExpressionValue(GetCurrentAssemblyAddress()));
        }

        #region Statement processing

        /// <summary>
        /// Processes a compiler statement
        /// </summary>
        /// <param name="allLines">All parsed lines</param>
        /// <param name="scopeLines">Lines to process in the current scope</param>
        /// <param name="stmt">Statement to process</param>
        /// <param name="label">Label to process</param>
        /// <param name="currentLineIndex">Current line index</param>
        private void ProcessStatement(List<SourceLineBase> allLines, List<SourceLineBase> scopeLines, 
            StatementBase stmt, string label, ref int currentLineIndex)
        {
            switch (stmt)
            {
                case ModuleStatement moduleStatement:
                    ProcessModuleStatement(moduleStatement, label, allLines, scopeLines, ref currentLineIndex);
                    break;

                case ModuleEndStatement moduleEndStmt:
                    ReportError(Errors.Z0405, moduleEndStmt, "ENDMODULE/MODULEEND", "MODULE");
                    break;

                case MacroStatement macroStmt:
                    CollectMacroDefinition(macroStmt, label, allLines, ref currentLineIndex);
                    break;

                case MacroEndStatement macroEndStmt:
                    ReportError(Errors.Z0405, macroEndStmt, "ENDM/MEND", "MACRO");
                    break;

                case StructStatement structStmt:
                    CollectStructDefinition(structStmt, label, allLines, ref currentLineIndex);
                    break;

                case StructEndStatement structEndStmt:
                    ReportError(Errors.Z0405, structEndStmt, "ENDS", "STRUCT");
                    break;

                case ProcStatement procStatement:
                    ProcessProcStatement(procStatement, allLines, scopeLines, ref currentLineIndex);
                    break;

                case ProcEndStatement procEndStmt:
                    ReportError(Errors.Z0405, procEndStmt, "ENDP/PEND", "PROC");
                    break;

                case LoopStatement loopStatement:
                    ProcessLoopStatement(loopStatement, allLines, scopeLines, ref currentLineIndex);
                    break;

                case LoopEndStatement loopEndStmt:
                    ReportError(Errors.Z0405, loopEndStmt, "ENDL/LEND", "LOOP");
                    break;

                case RepeatStatement repeatStatement:
                    ProcessRepeatStatement(repeatStatement, allLines, scopeLines, ref currentLineIndex);
                    break;

                case UntilStatement untilStmt:
                    ReportError(Errors.Z0405, untilStmt, "UNTIL", "REPEAT");
                    break;

                case WhileStatement whileStatement:
                    ProcessWhileStatement(whileStatement, allLines, scopeLines, ref currentLineIndex);
                    break;

                case WhileEndStatement whileEndStmt:
                    ReportError(Errors.Z0405, whileEndStmt, "ENDW/WEND", "WHILE");
                    break;

                case ForStatement forStatement:
                    ProcessForStatement(forStatement, allLines, scopeLines, ref currentLineIndex);
                    break;

                case NextStatement ifEndStmt:
                    ReportError(Errors.Z0405, ifEndStmt, "NEXT", "FOR");
                    break;

                case ElifStatement elifStmt:
                    ReportError(Errors.Z0405, elifStmt, "ELIF", "IF");
                    break;

                case IfStatement ifStatement:
                    ProcessIfStatement(ifStatement, allLines, scopeLines, ref currentLineIndex);
                    break;

                case ElseStatement elseStmt:
                    ReportError(Errors.Z0405, elseStmt, "ELSE", "IF");
                    break;

                case IfEndStatement ifEndStmt:
                    ReportError(Errors.Z0405, ifEndStmt, "ENDIF", "IF");
                    break;

                case BreakStatement breakStmt:
                    ProcessBreakStatement(breakStmt);
                    break;

                case ContinueStatement continueStmt:
                    ProcessContinueStatement(continueStmt);
                    break;

                case MacroOrStructInvocation macroInvokeStmt:
                    ProcessMacroOrStructInvocation(macroInvokeStmt, allLines);
                    break;

                case LocalStatement localStmt:
                    ProcessLocalStatement(localStmt);
                    break;
            }
        }

        /// <summary>
        /// Checks and collects the current macro definition
        /// </summary>
        /// <param name="macro">Statement for the macro</param>
        /// <param name="label">Label of the macro</param>
        /// <param name="allLines">All parsed lines</param>
        /// <param name="currentLineIndex">Index of the macro definition line</param>
        private void CollectMacroDefinition(MacroStatement macro, string label,
            List<SourceLineBase> allLines, ref int currentLineIndex)
        {
            var errorFound = false;
            // --- Check for parameter uniqueness
            var args = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
            foreach (var macroArg in macro.Arguments)
            {
                if (args.Contains(macroArg))
                {
                    ReportError(Errors.Z0417, macro, macroArg);
                    errorFound = true;
                }
                args.Add(macroArg);
            }

            if (label == null)
            {
                errorFound = true;
                ReportError(Errors.Z0400, macro);
            }
            else if (label.StartsWith("`"))
            {
                errorFound = true;
                ReportError(Errors.Z0427, macro, label);
            }
            else if (CurrentModule.Macros.ContainsKey(label) 
                || CurrentModule.Symbols.ContainsKey(label)
                || CurrentModule.NestedModules.ContainsKey(label)
                || CurrentModule.Structs.ContainsKey(label)) 
            {
                errorFound = true;
                ReportError(Errors.Z0402, macro, label);
            }

            // --- Search for the end of the macro
            var firstLine = currentLineIndex;
            if (!macro.SearchForEnd(this, allLines, ref currentLineIndex, out var endLabel)) return;

            // --- Create macro definition
            var macroDef = new MacroDefinition(label, firstLine, currentLineIndex, 
                macro.Arguments, endLabel);

            // --- Check each macro line for invalid macro parameter names
            // --- or nested macro
            for (var i = firstLine + 1; i < currentLineIndex; i++)
            {
                var macroLine = allLines[i];
                if (macroLine.IssueToEmit != null)
                {
                    ReportError(macroLine.IssueToEmit, macroLine);
                    errorFound = true;
                    continue;
                }

                if (macroLine is MacroStatement)
                {
                    ReportError(Errors.Z0404, macroLine);
                    errorFound = true;
                    continue;
                }

                if (macroLine.MacroParamNames != null)
                {
                    foreach (var paramName in macroLine.MacroParamNames)
                    {
                        var comparer = IsCaseSensitive
                            ? StringComparer.InvariantCulture
                            : StringComparer.InvariantCultureIgnoreCase;
                        if (macro.Arguments.Contains(paramName, comparer)) continue;

                        errorFound = true;
                        ReportError(Errors.Z0403, macroLine, paramName);
                    }
                }
            }

            // --- If macro is OK, store it
            if (!errorFound)
            {
                CurrentModule.Macros[label] = macroDef;
            }
        }

        /// <summary>
        /// Checks and collects the current structure definition
        /// </summary>
        /// <param name="structStmt">Statement for the structure</param>
        /// <param name="label">Label of the structure</param>
        /// <param name="allLines">All parsed lines</param>
        /// <param name="currentLineIndex">Index of the macro definition line</param>
        private void CollectStructDefinition(StructStatement structStmt, string label, 
            List<SourceLineBase> allLines, ref int currentLineIndex)
        {
            var errorFound = false;

            if (label == null)
            {
                errorFound = true;
                ReportError(Errors.Z0432, structStmt);
            }
            else if (label.StartsWith("`"))
            {
                errorFound = true;
                ReportError(Errors.Z0433, structStmt, label);
            }
            else if (CurrentModule.Macros.ContainsKey(label)
                     || CurrentModule.Symbols.ContainsKey(label)
                     || CurrentModule.NestedModules.ContainsKey(label)
                     || CurrentModule.Structs.ContainsKey(label))
            {
                errorFound = true;
                ReportError(Errors.Z0434, structStmt, label);
            }

            // --- Search for the end of the struct
            var firstLine = currentLineIndex;
            if (!structStmt.SearchForEnd(this, allLines, ref currentLineIndex, out var endLabel)) return;

            if (endLabel != null)
            {
                errorFound = true;
                ReportError(Errors.Z0436, structStmt);
            }

            // --- Create structure definition
            var structDef = new StructDefinition(label, firstLine, currentLineIndex, IsCaseSensitive);

            // --- Check each macro line for valid instruction type
            var structErrors = 0;
            var structOffset = 0;
            for (var i = firstLine + 1; i < currentLineIndex; i++)
            {
                var structLine = allLines[i];
                if (!StructBodyStatementTypes.Contains(structLine.GetType()))
                {
                    ReportError(Errors.Z0435, structLine);
                    errorFound = true;
                    structErrors++;
                    if (structErrors > 16) break;
                }

                // --- Check for field definition
                if (structLine.Label != null)
                {
                    var fieldLabel = structLine.Label;
                    if (structDef.Fields.ContainsKey(fieldLabel))
                    {
                        ReportError(Errors.Z0438, structLine, fieldLabel);
                        errorFound = true;
                    }
                    else
                    {
                        structDef.Fields.Add(fieldLabel, new FieldDefinition((ushort)structOffset));
                    }
                }

                // --- We use this fuction to emit a byte
                void EmitAction(byte data)
                {
                    // ReSharper disable once AccessToModifiedClosure
                    structOffset++;
                }

                // --- Determine structure size
                switch (structLine)
                {
                    case DefbPragma defbPragma:
                        structOffset += defbPragma.Exprs.Count;
                        break;

                    case DefwPragma defwPragma:
                        structOffset += defwPragma.Exprs.Count * 2;
                        break;

                    case DefmnPragma defmnPragma:
                        ProcessDefmnPragma(defmnPragma, EmitAction);
                        break;

                    case DefhPragma defhPragma:
                        ProcessDefhPragma(defhPragma, EmitAction);
                        break;

                    case DefsPragma defsPragma:
                        ProcessDefsPragma(defsPragma, EmitAction);
                        break;

                    case FillwPragma fillwPragma:
                        ProcessFillwPragma(fillwPragma, EmitAction);
                        break;

                    case FillbPragma fillbPragma:
                        ProcessFillbPragma(fillbPragma, EmitAction);
                        break;

                    case DefgPragma defgPragma:
                        ProcessDefgPragma(defgPragma, EmitAction);
                        break;

                    case DefgxPragma defgxPragma:
                        ProcessDefgxPragma(defgxPragma, EmitAction);
                        break;
                }
            }

            // --- Store the structure size
            structDef.Size = structOffset;

            // -- Stop, if error found
            if (errorFound) return;

            // --- Register the structure and the structure symbol
            CurrentModule.Structs[label] = structDef;
            CurrentModule.Symbols[label] = AssemblySymbolInfo.CreateLabel(label, new ExpressionValue(structOffset));
        }

        /// <summary>
        /// Processes the LOCAL statement
        /// </summary>
        /// <param name="stmt"></param>
        private void ProcessLocalStatement(LocalStatement stmt)
        {
            if (IsInGlobalScope)
            {
                ReportError(Errors.Z0448, stmt);
                return;
            }

            var localScopes = CurrentModule.LocalScopes;
            var scope = localScopes.Peek();
            if (scope.IsTemporaryScope)
            {
                var tmpScope = localScopes.Pop();
                scope = localScopes.Count > 0 ? localScopes.Peek(): null;
                localScopes.Push(tmpScope);
            }

            if (scope == null || !scope.IsProcScope)
            {
                ReportError(Errors.Z0448, stmt);
            }
        }


        /// <summary>
        /// Processes the LOOP statement
        /// </summary>
        /// <param name="loop">LOOP statement</param>
        /// <param name="allLines">All parsed lines</param>
        /// <param name="scopeLines">Lines to process in the current scope</param>
        /// <param name="currentLineIndex">Index of the LOOP definition line</param>
        private void ProcessLoopStatement(LoopStatement loop, List<SourceLineBase> allLines, 
            List<SourceLineBase> scopeLines, ref int currentLineIndex)
        {
            // --- Search for the end of the loop
            var firstLine = currentLineIndex;
            if (!loop.SearchForEnd(this, scopeLines, ref currentLineIndex, out var endLabel)) return;

            // --- End found
            var lastLine = currentLineIndex;

            // --- Now, we can process the loop
            var loopCounter = EvalImmediate(loop, loop.Expression);
            if (!loopCounter.IsValid) return;
            if (loopCounter.Type == ExpressionValueType.String)
            {
                ReportError(Errors.Z0305, loop);
                return;
            }

            // --- Check the loop counter
            var counter = loopCounter.AsLong();
            if (counter >= 0x10000)
            {
                ReportError(Errors.Z0406, loop);
                counter = 1;
            }

            // --- Create a scope for the loop
            var loopScope = new SymbolScope(null, IsCaseSensitive);
            CurrentModule.LocalScopes.Push(loopScope);
            var errorsBefore = Output.ErrorCount;

            for (var i = 0; i < counter; i++)
            {
                // --- Create a local scope for the loop body
                var iterationScope = new SymbolScope(loopScope, IsCaseSensitive);
                CurrentModule.LocalScopes.Push(iterationScope);
                iterationScope.LoopCounter = i + 1;

                var loopLineIndex = firstLine + 1;
                while (loopLineIndex < lastLine)
                {
                    var curLine = scopeLines[loopLineIndex];
                    EmitSingleLine(allLines, scopeLines, curLine, ref loopLineIndex);
                    if (iterationScope.BreakReached || iterationScope.ContinueReached)
                    {
                        break;
                    }
                    loopLineIndex++;
                }

                // --- Add the end label to the local scope
                if (endLabel != null)
                {
                    // --- Add the end label to the loop scope
                    var endLine = scopeLines[currentLineIndex];
                    AddSymbol(endLabel, endLine, new ExpressionValue(GetCurrentAssemblyAddress()));
                }

                // --- Clean up the hanging label
                OverflowLabelLine = null;

                // --- Fixup the temporary scope over the iteration scope, if there is any
                var topScope = CurrentModule.LocalScopes.Peek();
                if (topScope != iterationScope && topScope.IsTemporaryScope)
                {
                    FixupSymbols(topScope.Fixups, topScope.Symbols, false);
                    CurrentModule.LocalScopes.Pop();
                }

                // --- Fixup the symbols locally
                FixupSymbols(iterationScope.Fixups, iterationScope.Symbols, false);

                // --- Remove the local scope
                CurrentModule.LocalScopes.Pop();

                // --- Check for the maximum number of error
                if (Output.ErrorCount - errorsBefore >= _options.MaxLoopErrorsToReport)
                {
                    ReportError(Errors.Z0408, loop);
                    break;
                }

                // --- BREAK reached, exit the loop
                if (iterationScope.BreakReached)
                {
                    break;
                }
            }

            // --- Clean up the loop's scope
            CurrentModule.LocalScopes.Pop();
        }

        /// <summary>
        /// Processes the PROC statement
        /// </summary>
        /// <param name="proc">LOOP statement</param>
        /// <param name="allLines">All parsed lines</param>
        /// <param name="scopeLines">Lines to process in the current scope</param>
        /// <param name="currentLineIndex">Index of the LOOP definition line</param>
        private void ProcessProcStatement(ProcStatement proc, List<SourceLineBase> allLines,
            List<SourceLineBase> scopeLines, ref int currentLineIndex)
        {
            // --- Search for the end of the loop
            var firstLine = currentLineIndex;
            if (!proc.SearchForEnd(this, scopeLines, ref currentLineIndex, out var endLabel)) return;

            // --- End found
            var lastLine = currentLineIndex;

            // --- Create a scope for the proc
            var procScope = new SymbolScope(null, IsCaseSensitive)
            {
                IsLoopScope = false, IsProcScope = true
            };
            CurrentModule.LocalScopes.Push(procScope);

            // --- Collect and process LOCAL statements

            for (var line = firstLine + 1; line < lastLine; line++)
            {
                var localLine = scopeLines[line] as LocalStatement;
                if (localLine == null) continue;


                foreach (var symbol in localLine.Locals)
                {
                    if (symbol.StartsWith("`"))
                    {
                        ReportError(Errors.Z0447, localLine, symbol);
                    }
                    if (procScope.LocalSymbolBookings.Contains(symbol))
                    {
                        ReportError(Errors.Z0449, localLine, symbol);
                    }
                    procScope.LocalSymbolBookings.Add(symbol);
                }
            }

            // --- Create a local scope for the loop body
            var loopLineIndex = firstLine + 1;
            while (loopLineIndex < lastLine)
            {
                var curLine = scopeLines[loopLineIndex];
                EmitSingleLine(allLines, scopeLines, curLine, ref loopLineIndex);
                loopLineIndex++;
            }

            // --- Add the end label to the local scope
            if (endLabel != null)
            {
                // --- Add the end label to the loop scope
                var endLine = scopeLines[currentLineIndex];
                AddSymbol(endLabel, endLine, new ExpressionValue(GetCurrentAssemblyAddress()));
            }

            // --- Clean up the hanging label
            OverflowLabelLine = null;

            // --- Fixup the temporary scope over the iteration scope, if there is any
            var topScope = CurrentModule.LocalScopes.Peek();
            if (topScope != procScope && topScope.IsTemporaryScope)
            {
                FixupSymbols(topScope.Fixups, topScope.Symbols, false);
                CurrentModule.LocalScopes.Pop();
            }

            // --- Fixup the symbols locally
            FixupSymbols(procScope.Fixups, procScope.Symbols, false);

            // --- Clean up the loop's scope
            CurrentModule.LocalScopes.Pop();
        }

        /// <summary>
        /// Processes the MODULE statement
        /// </summary>
        /// <param name="module">MODULE statement</param>
        /// <param name="label">MODULE label</param>
        /// <param name="allLines">All parsed lines</param>
        /// <param name="scopeLines">Lines to process in the current scope</param>
        /// <param name="currentLineIndex">Index of the LOOP definition line</param>
        private void ProcessModuleStatement(ModuleStatement module, string label,
            List<SourceLineBase> allLines, List<SourceLineBase> scopeLines,
            ref int currentLineIndex)
        {
            // --- Search for the end of the loop
            var firstLine = currentLineIndex;
            if (!module.SearchForEnd(this, scopeLines, ref currentLineIndex, out var endLabel)) return;

            // --- End found
            var lastLine = currentLineIndex;

            // --- Process label
            var moduleName = module.Name ?? label;
            if (moduleName == null)
            {
                ReportError(Errors.Z0428, module);
                return;
            }
            if (moduleName.StartsWith("`"))
            {
                ReportError(Errors.Z0430, module, moduleName);
                return;
            }
            if (CurrentModule.NestedModules.ContainsKey(moduleName))
            {
                ReportError(Errors.Z0429, module, moduleName);
                return;
            }

            // --- Create a new nested module
            var newModule = new AssemblyModule(CurrentModule, IsCaseSensitive);
            CurrentModule.NestedModules.Add(moduleName, newModule);
            CurrentModule = newModule;

            // --- The module has a label, so create a temporary scope, too
            newModule.LocalScopes.Push(new SymbolScope(null, IsCaseSensitive)
            {
                IsTemporaryScope = true
            });

            // --- Create a local scope for the loop body
            var loopLineIndex = firstLine + 1;
            while (loopLineIndex < lastLine)
            {
                var curLine = scopeLines[loopLineIndex];
                EmitSingleLine(allLines, scopeLines, curLine, ref loopLineIndex);
                loopLineIndex++;
            }

            // --- Add the end label to the local scope
            if (endLabel != null)
            {
                // --- Add the end label to the loop scope
                var endLine = scopeLines[currentLineIndex];
                AddSymbol(endLabel, endLine, new ExpressionValue(GetCurrentAssemblyAddress()));
            }

            // --- Clean up the hanging label
            OverflowLabelLine = null;

            // --- Fixup the temporary scope over the iteration scope, if there is any
            if (CurrentModule.LocalScopes.Count > 0)
            {
                var topScope = CurrentModule.LocalScopes.Peek();
                if (topScope.IsTemporaryScope)
                {
                    FixupSymbols(topScope.Fixups, topScope.Symbols, false);
                    CurrentModule.LocalScopes.Pop();
                }
            }

            // --- Fixup the symbols locally
            FixupSymbols(newModule.Fixups, newModule.Symbols, false);

            // --- Step back to the outer module
            CurrentModule = newModule.ParentModule;
        }

        /// <summary>
        /// Processes the REPEAT statement
        /// </summary>
        /// <param name="repeat">REPEAT statement</param>
        /// <param name="allLines">All parsed lines</param>
        /// <param name="scopeLines">Lines to process in the current scope</param>
        /// <param name="currentLineIndex">Index of the REPEAT definition line</param>
        private void ProcessRepeatStatement(RepeatStatement repeat,
            List<SourceLineBase> allLines,
            List<SourceLineBase> scopeLines, ref int currentLineIndex)
        {
            // --- Search for the end of the loop
            var firstLine = currentLineIndex;
            if (!repeat.SearchForEnd(this, scopeLines, ref currentLineIndex, out var endLabel)) return;

            // --- End found
            var lastLine = currentLineIndex;
            var untilStmt = scopeLines[lastLine] as UntilStatement;

            // --- Create a scope for the repeat loop
            var loopScope = new SymbolScope(null, IsCaseSensitive);
            CurrentModule.LocalScopes.Push(loopScope);
            var errorsBefore = Output.ErrorCount;

            // --- Execute the REPEAT body
            var loopCount = 1;
            bool condition;
            do
            {
                // --- Create a local scope for the repeat body
                var iterationScope = new SymbolScope(loopScope, IsCaseSensitive);
                CurrentModule.LocalScopes.Push(iterationScope);
                iterationScope.LoopCounter = loopCount;

                var loopLineIndex = firstLine + 1;
                while (loopLineIndex < lastLine)
                {
                    var curLine = scopeLines[loopLineIndex];
                    EmitSingleLine(allLines, scopeLines, curLine, ref loopLineIndex);
                    if (iterationScope.BreakReached || iterationScope.ContinueReached)
                    {
                        break;
                    }
                    loopLineIndex++;
                }

                // --- Add the end label to the local scope
                if (endLabel != null)
                {
                    // --- Add the end label to the loop scope
                    var endLine = scopeLines[currentLineIndex];
                    AddSymbol(endLabel, endLine, new ExpressionValue(GetCurrentAssemblyAddress()));
                }

                // --- Clean up the hanging label
                OverflowLabelLine = null;

                // --- Fixup the temporary scope over the iteration scope, if there is any
                var topScope = CurrentModule.LocalScopes.Peek();
                if (topScope != iterationScope && topScope.IsTemporaryScope)
                {
                    FixupSymbols(topScope.Fixups, topScope.Symbols, false);
                    CurrentModule.LocalScopes.Pop();
                }

                // --- Fixup the symbols locally
                FixupSymbols(iterationScope.Fixups, iterationScope.Symbols, false);

                // --- Check for the maximum number of error
                if (Output.ErrorCount - errorsBefore >= _options.MaxLoopErrorsToReport)
                {
                    ReportError(Errors.Z0408, repeat);
                    break;
                }

                // --- Evaluate the loop expression
                var loopExitCondition = EvalImmediate(untilStmt, untilStmt?.Expression);
                if (!loopExitCondition.IsValid) return;
                if (loopExitCondition.Type == ExpressionValueType.String)
                {
                    ReportError(Errors.Z0305, untilStmt);
                    break;
                }
                condition = loopExitCondition.AsBool();

                // --- Increment counter, check loop safety
                loopCount++;
                iterationScope.LoopCounter = loopCount;
                if (loopCount >= 0x10000)
                {
                    ReportError(Errors.Z0409, repeat);
                    break;
                }

                // --- Remove the local scope
                CurrentModule.LocalScopes.Pop();

                // --- BREAK reached, exit the loop
                if (iterationScope.BreakReached)
                {
                    break;
                }
            } while (!condition);

            // --- Clean up the loop's scope
            CurrentModule.LocalScopes.Pop();
        }

        /// <summary>
        /// Processes the WHILE statement
        /// </summary>
        /// <param name="whileStmt">WHILE statement</param>
        /// <param name="allLines">All parsed lines</param>
        /// <param name="scopeLines">Lines to process in the current scope</param>
        /// <param name="currentLineIndex">Index of the WHILE definition line</param>
        private void ProcessWhileStatement(WhileStatement whileStmt,
            List<SourceLineBase> allLines,
            List<SourceLineBase> scopeLines, ref int currentLineIndex)
        {
            // --- Search for the end of the loop
            var firstLine = currentLineIndex;
            if (!whileStmt.SearchForEnd(this, scopeLines, ref currentLineIndex, out var endLabel)) return;

            // --- End found
            var lastLine = currentLineIndex;
            
            // --- Create a scope for the while loop
            var loopScope = new SymbolScope(null, IsCaseSensitive);
            CurrentModule.LocalScopes.Push(loopScope);
            var errorsBefore = Output.ErrorCount;

            // --- Execute the WHILE body
            var loopCount = 1;
            while (true)
            {
                // --- Create a local scope for the repeat body
                var iterationScope = new SymbolScope(loopScope, IsCaseSensitive);
                CurrentModule.LocalScopes.Push(iterationScope);
                iterationScope.LoopCounter = loopCount;

                // --- Evaluate the loop expression
                var loopCondition = EvalImmediate(whileStmt, whileStmt.Expr);
                if (!loopCondition.IsValid) return;
                if (loopCondition.Type == ExpressionValueType.String)
                {
                    ReportError(Errors.Z0305, whileStmt);
                    break;
                }

                // --- Exit if while condition fails
                if (!loopCondition.AsBool()) break;

                var loopLineIndex = firstLine + 1;
                while (loopLineIndex < lastLine)
                {
                    var curLine = scopeLines[loopLineIndex];
                    EmitSingleLine(allLines, scopeLines, curLine, ref loopLineIndex);
                    if (iterationScope.BreakReached || iterationScope.ContinueReached)
                    {
                        break;
                    }
                    loopLineIndex++;
                }

                // --- Add the end label to the local scope
                if (endLabel != null)
                {
                    // --- Add the end label to the loop scope
                    var endLine = scopeLines[currentLineIndex];
                    AddSymbol(endLabel, endLine, new ExpressionValue(GetCurrentAssemblyAddress()));
                }

                // --- Clean up the hanging label
                OverflowLabelLine = null;

                // --- Fixup the temporary scope over the iteration scope, if there is any
                var topScope = CurrentModule.LocalScopes.Peek();
                if (topScope != iterationScope && topScope.IsTemporaryScope)
                {
                    FixupSymbols(topScope.Fixups, topScope.Symbols, false);
                    CurrentModule.LocalScopes.Pop();
                }

                // --- Fixup the symbols locally
                FixupSymbols(iterationScope.Fixups, iterationScope.Symbols, false);

                // --- Remove the local scope
                CurrentModule.LocalScopes.Pop();

                // --- Check for the maximum number of error
                if (Output.ErrorCount - errorsBefore >= _options.MaxLoopErrorsToReport)
                {
                    ReportError(Errors.Z0408, whileStmt);
                    break;
                }

                // --- Increment counter, check loop safety
                loopCount++;
                if (loopCount >= 0xFFFF)
                {
                    ReportError(Errors.Z0409, whileStmt);
                    break;
                }

                // --- BREAK reached, exit the loop
                if (iterationScope.BreakReached)
                {
                    break;
                }
            }

            // --- Clean up the loop's scope
            CurrentModule.LocalScopes.Pop();
        }

        /// <summary>
        /// Processes the FOR statement
        /// </summary>
        /// <param name="forStmt">FOR statement</param>
        /// <param name="allLines">All parsed lines</param>
        /// <param name="scopeLines">Lines to process in the current scope</param>
        /// <param name="currentLineIndex">Index of the FOR definition line</param>
        private void ProcessForStatement(ForStatement forStmt,
            List<SourceLineBase> allLines,
            List<SourceLineBase> scopeLines, ref int currentLineIndex)
        {
            // --- Search for the end of the loop
            var firstLine = currentLineIndex;
            if (!forStmt.SearchForEnd(this, scopeLines, ref currentLineIndex, out var endLabel)) return;

            // --- End found
            var lastLine = currentLineIndex;

            // --- Evaluate FROM, TO, and STEP expressions
            var fromValue = EvalImmediate(forStmt, forStmt.From);
            if (!fromValue.IsValid) return;
            if (fromValue.Type == ExpressionValueType.String)
            {
                ReportError(Errors.Z0305, forStmt);
                return;
            }

            var toValue = EvalImmediate(forStmt, forStmt.To);
            if (!toValue.IsValid) return;
            if (toValue.Type == ExpressionValueType.String)
            {
                ReportError(Errors.Z0305, forStmt);
                return;
            }

            var stepValue = new ExpressionValue(1);
            if (forStmt.Step != null)
            {
                stepValue = EvalImmediate(forStmt, forStmt.Step);
                if (!stepValue.IsValid) return;
                if (stepValue.Type == ExpressionValueType.String)
                {
                    ReportError(Errors.Z0305, forStmt);
                    return;
                }
                if (Math.Abs(stepValue.AsReal()) < double.Epsilon)
                {
                    ReportError(Errors.Z0413, forStmt);
                    return;
                }
            }

            // --- Check the FOR variable
            if (VariableExists(forStmt.ForVariable))
            {
                ReportError(Errors.Z0414, forStmt, forStmt.ForVariable);
                return;
            }

            // --- Create a scope for the FOR loop
            var loopScope = new SymbolScope(null, IsCaseSensitive);
            CurrentModule.LocalScopes.Push(loopScope);

            // --- Init the FOR variable
            loopScope.Symbols.Add(forStmt.ForVariable, 
                AssemblySymbolInfo.CreateVar(forStmt.ForVariable, fromValue));
            var errorsBefore = Output.ErrorCount;

            var isIntLoop =
                (fromValue.Type == ExpressionValueType.Bool || fromValue.Type == ExpressionValueType.Integer)
                && (toValue.Type == ExpressionValueType.Bool || toValue.Type == ExpressionValueType.Integer)
                && (stepValue.Type == ExpressionValueType.Bool || stepValue.Type == ExpressionValueType.Integer);

            var loopIntValue = fromValue.AsLong();
            var endIntValue = toValue.AsLong();
            var incIntValue = stepValue.AsLong();
            var loopRealValue = fromValue.AsReal();
            var endRealValue = toValue.AsReal();
            var incRealValue = stepValue.AsReal();

            // --- Execute the FOR body
            var loopCount = 0;
            while (true)
            {
                // --- Check the loop's exit condition
                if (isIntLoop)
                {
                    if (incIntValue > 0 && loopIntValue > endIntValue) break;
                    if (incIntValue < 0 && loopIntValue < endIntValue) break;
                }
                else
                {
                    if (incRealValue > 0 && loopRealValue > endRealValue) break;
                    if (incRealValue < 0 && loopRealValue < endRealValue) break;
                }

                // --- Increment counter, check loop safety
                loopCount++;
                if (loopCount >= 0xFFFF)
                {
                    ReportError(Errors.Z0409, forStmt);
                    break;
                }

                // --- Create a local scope for the FOR body
                var iterationScope = new SymbolScope(loopScope, IsCaseSensitive);
                CurrentModule.LocalScopes.Push(iterationScope);
                iterationScope.LoopCounter = loopCount;

                var loopLineIndex = firstLine + 1;
                while (loopLineIndex < lastLine)
                {
                    var curLine = scopeLines[loopLineIndex];
                    EmitSingleLine(allLines, scopeLines, curLine, ref loopLineIndex);
                    if (iterationScope.BreakReached || iterationScope.ContinueReached)
                    {
                        break;
                    }
                    loopLineIndex++;
                }

                // --- Add the end label to the local scope
                if (endLabel != null)
                {
                    // --- Add the end label to the loop scope
                    var endLine = scopeLines[currentLineIndex];
                    AddSymbol(endLabel, endLine, new ExpressionValue(GetCurrentAssemblyAddress()));
                }

                // --- Clean up the hanging label
                OverflowLabelLine = null;

                // --- Fixup the temporary scope over the iteration scope, if there is any
                var topScope = CurrentModule.LocalScopes.Peek();
                if (topScope != iterationScope && topScope.IsTemporaryScope)
                {
                    FixupSymbols(topScope.Fixups, topScope.Symbols, false);
                    CurrentModule.LocalScopes.Pop();
                }

                // --- Fixup the symbols locally
                FixupSymbols(iterationScope.Fixups, iterationScope.Symbols, false);

                // --- Remove the local scope
                CurrentModule.LocalScopes.Pop();

                // --- Check for the maximum number of error
                if (Output.ErrorCount - errorsBefore >= _options.MaxLoopErrorsToReport)
                {
                    ReportError(Errors.Z0408, forStmt);
                    break;
                }

                // --- BREAK reached, exit the loop
                if (iterationScope.BreakReached)
                {
                    break;
                }

                // --- Increment cycle variable
                if (isIntLoop)
                {
                    loopIntValue += incIntValue;
                    loopScope.Symbols[forStmt.ForVariable].Value = new ExpressionValue(loopIntValue);
                }
                else
                {
                    loopRealValue += incRealValue;
                    loopScope.Symbols[forStmt.ForVariable].Value = new ExpressionValue(loopRealValue);
                }
            }

            // --- Clean up the loop's scope
            CurrentModule.LocalScopes.Pop();
        }

        /// <summary>
        /// Processes the BREAK statement
        /// </summary>
        /// <param name="breakStmt">BREAK statement</param>
        private void ProcessBreakStatement(SourceLineBase breakStmt)
        {
            if (IsInGlobalScope || !CurrentModule.LocalScopes.Peek().IsLoopScope)
            {
                ReportError(Errors.Z0415, breakStmt);
                return;
            }
            CurrentModule.LocalScopes.Peek().BreakReached = true;
        }

        /// <summary>
        /// Processes the CONTINUE statement
        /// </summary>
        /// <param name="continueStmt">CONTINUE statement</param>
        private void ProcessContinueStatement(SourceLineBase continueStmt)
        {
            if (IsInGlobalScope || !CurrentModule.LocalScopes.Peek().IsLoopScope)
            {
                ReportError(Errors.Z0416, continueStmt);
                return;
            }
            CurrentModule.LocalScopes.Peek().ContinueReached = true;
        }

        /// <summary>
        /// Processes the if statement
        /// </summary>
        /// <param name="ifStmt">IF statement</param>
        /// <param name="allLines">All parsed lines</param>
        /// <param name="scopeLines">Lines to process in the current scope</param>
        /// <param name="currentLineIndex">Index of the IF definition line</param>
        private void ProcessIfStatement(IfStatement ifStmt,
            List<SourceLineBase> allLines,
            List<SourceLineBase> scopeLines, ref int currentLineIndex)
        {
            // --- Search for the end of the loop
            var ifDef = GetIfSections(ifStmt, scopeLines, ref currentLineIndex, out var endLabel);
            if (ifDef == null) return;

            // --- Process the IF definition
            IfSection sectionToCompile = null;
            foreach (var ifSection in ifDef.IfSections)
            {
                // --- Evaluate the condition
                ExpressionValue conditionValue;
                if (ifSection.IfStatement is ElifStatement elifStmt)
                {
                    conditionValue = EvalImmediate(ifSection.IfStatement, elifStmt.Expression);
                }
                else
                {
                    switch (ifStmt.Type)
                    {
                        case IfStatementType.If:
                            conditionValue = EvalImmediate(ifSection.IfStatement, ifStmt.Expr);
                            break;
                        case IfStatementType.IfUsed:
                        case IfStatementType.IfNotUsed:
                            var idSymbol = ifStmt.Symbol;
                            var (expressionValue, usageInfo) = GetSymbolValue(idSymbol.SymbolName, idSymbol.StartFromGlobal);
                            var isUsed = expressionValue != null && usageInfo != null && usageInfo.IsUsed;
                            conditionValue = new ExpressionValue(ifStmt.Type == IfStatementType.IfUsed ? isUsed : !isUsed);
                            break;
                        default:
                            // --- Just for the sake of completeness
                            conditionValue = new ExpressionValue(false);
                            break;
                    }
                }

                // --- Handle evaluation errors
                if (!conditionValue.IsValid) continue;
                if (conditionValue.Type == ExpressionValueType.String)
                {
                    ReportError(Errors.Z0305, ifSection.IfStatement);
                    continue;
                }

                // --- Check the condition
                if (conditionValue.AsBool())
                {
                    sectionToCompile = ifSection;
                }
            }

            // --- Check if there is any section to compile
            sectionToCompile = sectionToCompile ?? ifDef.ElseSection;
            if (sectionToCompile == null)
            {
                // --- No matching IF, ELIF, and no ELSE, so there's nothing to emit
                return;
            }

            // --- Emit the matching section
            var loopLineIndex = sectionToCompile.Section.FirstLine + 1;
            while (loopLineIndex < sectionToCompile.Section.LastLine)
            {
                var curLine = scopeLines[loopLineIndex];
                EmitSingleLine(allLines, scopeLines, curLine, ref loopLineIndex);
                loopLineIndex++;
            }

            // --- Add the end label to the local scope
            if (endLabel != null)
            {
                // --- Add the end label to the loop scope
                var endLine = scopeLines[currentLineIndex];
                AddSymbol(endLabel, endLine, new ExpressionValue(GetCurrentAssemblyAddress()));
            }

            // --- Clean up the hanging label
            OverflowLabelLine = null;
        }

        /// <summary>
        /// Collects the strcuture information of an IF statement and makes fundamental syntax checks
        /// </summary>
        /// <param name="ifStmt">IF statement</param>
        /// <param name="lines">Parsed assembly lines</param>
        /// <param name="currentLineIndex">Index of the LOOP definition line</param>
        /// <param name="endLabel">Optional label of the ENDIF statement</param>
        /// <returns></returns>
        private IfDefinition GetIfSections(IfStatement ifStmt, List<SourceLineBase> lines, ref int currentLineIndex, out string endLabel)
        {
            endLabel = null;
            if (currentLineIndex >= lines.Count)
            {
                return null;
            }

            var ifDef = new IfDefinition();
            var firstLine = currentLineIndex;
            var sectionStart = firstLine;
            var sectionStmt = lines[sectionStart] as StatementBase;
            var elseDetected = false;
            var errorDetected = false;
            currentLineIndex++;

            // --- Iterate through lines
            while (currentLineIndex < lines.Count)
            {
                var curLine = lines[currentLineIndex];

                // --- Check for ENDIF
                if (curLine is IfEndStatement)
                {
                    // --- We have found the end line, get its label
                    endLabel = curLine.Label ?? endLabel;
                    if (elseDetected)
                    {
                        // --- Store the ELSE section
                        ifDef.ElseSection = new IfSection(null, sectionStart, currentLineIndex);
                    }
                    else
                    {
                        // --- Store the IF/ELIF section
                        ifDef.IfSections.Add(new IfSection(sectionStmt, sectionStart, currentLineIndex));
                    }

                    // --- Calculate the entire IF section and return with it
                    ifDef.FullSection = new DefinitionSection(firstLine, currentLineIndex);
                    return errorDetected ? null : ifDef;
                }

                // --- Check for ELIF section
                if (curLine is ElifStatement elifStmt)
                {
                    endLabel = curLine.Label ?? endLabel;
                    if (endLabel != null)
                    {
                        ReportError(Errors.Z0411, sectionStmt, "ELIF");
                    }
                    if (elseDetected)
                    {
                        errorDetected = true;
                        ReportError(Errors.Z0410, curLine, "ELIF");
                    }
                    else
                    {
                        // --- Store the previous section
                        ifDef.IfSections.Add(new IfSection(sectionStmt, sectionStart, currentLineIndex));
                        sectionStmt = elifStmt;
                        sectionStart = currentLineIndex;
                    }
                }

                // --- Check for ELSE section
                else if (curLine is ElseStatement)
                {
                    endLabel = curLine.Label ?? endLabel;
                    if (endLabel != null)
                    {
                        ReportError(Errors.Z0411, sectionStmt, "ELSE");
                    }
                    if (elseDetected)
                    {
                        errorDetected = true;
                        ReportError(Errors.Z0410, curLine, "ELSE");
                    }
                    else
                    {
                        // --- Store the previous section
                        ifDef.IfSections.Add(new IfSection(sectionStmt, sectionStart, currentLineIndex));
                        sectionStart = currentLineIndex;
                    }
                    elseDetected = true;
                }

                if (curLine is NoInstructionLine noinstrLine)
                {
                    // --- Record the last hanging label
                    endLabel = noinstrLine.Label;
                }
                else
                {
                    endLabel = null;
                    if (curLine is BlockStatementBase blockStmt)
                    {
                        // --- Search for the end of an embedded block statement
                        var success = blockStmt.SearchForEnd(this, lines, ref currentLineIndex, out endLabel);
                        if (!success)
                        {
                            ReportError(Errors.Z0401, lines[firstLine], blockStmt.EndStatementName);
                            return null;
                        }
                    }
                }

                currentLineIndex++;
            }
            ReportError(Errors.Z0401, lines[firstLine], ifStmt.EndStatementName);
            return null;
        }

        /// <summary>
        /// Handles the invocation of a MACRO
        /// </summary>
        /// <param name="macroOrStructStmt">MACRO invocation statement</param>
        /// <param name="allLines">All parsed lines</param>
        private void ProcessMacroOrStructInvocation(MacroOrStructInvocation macroOrStructStmt,
            List<SourceLineBase> allLines)
        {
            // --- Check for structure invocation
            if (CurrentModule.Structs.TryGetValue(macroOrStructStmt.Name, out var structDef))
            {
                ProcessStructInvocation(macroOrStructStmt, structDef, allLines);
                return;
            }
            
            // --- Check if macro definition exists
            if (!CurrentModule.Macros.TryGetValue(macroOrStructStmt.Name, out var macroDef))
            {
                ReportError(Errors.Z0418, macroOrStructStmt, macroOrStructStmt.Name);
                return;
            }

            // --- Match parameters
            if (macroDef.ArgumentNames.Count < macroOrStructStmt.Parameters.Count)
            {
                ReportError(Errors.Z0419, macroOrStructStmt, macroDef.MacroName, macroDef.ArgumentNames.Count, macroOrStructStmt.Parameters.Count);
                return;
            }

            // --- Evaluate arguments
            var arguments = new Dictionary<string, ExpressionValue>(StringComparer.InvariantCultureIgnoreCase);
            var errorFound = false;
            var emptyArgValue = new ExpressionValue("$<none>$");
            for (var i = 0; i < macroDef.ArgumentNames.Count; i++)
            {
                if (i >= macroOrStructStmt.Parameters.Count)
                {
                    arguments.Add(macroDef.ArgumentNames[i], emptyArgValue);
                    continue;
                }
                var op = macroOrStructStmt.Parameters[i];
                ExpressionValue argValue;
                switch (op.Type)
                {
                    case OperandType.Reg8:
                    case OperandType.Reg8Idx:
                    case OperandType.Reg8Spec:
                    case OperandType.Reg16:
                    case OperandType.Reg16Idx:
                    case OperandType.Reg16Spec:
                    case OperandType.RegIndirect:
                        argValue = new ExpressionValue(op.Register);
                        break;
                    case OperandType.Expr:
                        argValue = Eval(macroOrStructStmt, op.Expression);
                        if (argValue.IsNonEvaluated)
                        {
                            argValue = new ExpressionValue(op.Expression.SourceText);
                        }
                        break;
                    case OperandType.MemIndirect:
                        argValue = EvalImmediate(macroOrStructStmt, op.Expression);
                        if (!argValue.IsValid) errorFound = true;
                        else
                        {
                            argValue = new ExpressionValue($"({argValue.AsString()})");
                        } 
                        break;
                    case OperandType.CPort:
                        argValue = new ExpressionValue("(C)");
                        break;
                    case OperandType.IndexedAddress:
                        if (op.Expression == null)
                        {
                            argValue = new ExpressionValue($"({op.Register})");
                        }
                        else
                        {
                            argValue = EvalImmediate(macroOrStructStmt, op.Expression);
                            if (!argValue.IsValid) errorFound = true;
                            else
                            {
                                argValue = new ExpressionValue($"({op.Register}{op.Sign}{argValue.AsString()})");
                            }
                        }
                        break;
                    case OperandType.Condition:
                        argValue = new ExpressionValue(op.Condition);
                        break;
                    default:
                        argValue = emptyArgValue;
                        break;
                }
                if (errorFound) continue;

                arguments.Add(macroDef.ArgumentNames[i], argValue);
            }
            if (errorFound) return;

            // --- Create a scope for the macro
            var macroScope = new SymbolScope(null, IsCaseSensitive)
            {
                MacroArguments = arguments
            };
            CurrentModule.LocalScopes.Push(macroScope);

            // --- The macro name will serve as its starting label
            macroScope.Symbols.Add(macroDef.MacroName, 
                AssemblySymbolInfo.CreateLabel(macroDef.MacroName, new ExpressionValue(GetCurrentAssemblyAddress())));

            var lineIndex = macroDef.Section.FirstLine + 1;
            var lastLine = macroDef.Section.LastLine;

            // --- Create source info for the macro invocation
            var currentAddress = GetCurrentAssemblyAddress();
            Output.AddToAddressMap(macroOrStructStmt.FileIndex, macroOrStructStmt.SourceLine, currentAddress);
            Output.SourceMap[currentAddress] = (macroOrStructStmt.FileIndex, macroOrStructStmt.SourceLine);

            // --- We store the original source file information to
            // --- assign it later with the re-parsed macro code
            var sourceInfo = new List<(int fileIndex, int line)>();

            // --- Setup the macro source
            var macroSource = new StringBuilder(4096);
            while (lineIndex < lastLine)
            {
                // --- Replace all macro arguments by their actual value
                var curLine = allLines[lineIndex];
                var lineText = curLine.MacroSourceText;
                var matches = MacroParamRegex.Matches(lineText);
                foreach (Match match in matches)
                {
                    var toReplace = match.Groups[0].Value;
                    var argName = match.Groups[1].Value;
                    if (!arguments.TryGetValue(argName, out var argValue))
                    {
                        continue;
                    }
                    lineText = lineText.Replace(toReplace, argValue.AsString());
                }

                // --- Store the source information for the currently processed macro line
                var newLines = lineText.Split(new[] {"\r\n"}, StringSplitOptions.None).Length;
                for (var i = 0; i < newLines; i++)
                {
                    sourceInfo.Add((curLine.FileIndex, curLine.SourceLine));
                }
                macroSource.AppendLine(lineText);
                lineIndex++;
            }

            // --- Now we have the source text to compile
            var inputStream = new AntlrInputStream(macroSource.ToString());
            var lexer = new Z80AsmLexer(inputStream);
            var tokenStream = new CommonTokenStream(lexer);
            var parser = new Z80AsmParser(tokenStream);
            var context = parser.compileUnit();
            var visitor = new Z80AsmVisitor(inputStream)
            {
                MacroParsingPhase = true
            };
            visitor.Visit(context);
            var visitedLines = visitor.Compilation;

            // --- Store any tasks defined by the user
            StoreTasks(Output.SourceItem, visitedLines.Lines);

            // --- Collect syntax errors
            foreach (var error in parser.SyntaxErrors)
            {
                // --- Translate the syntax error location
                if (error.SourceLine > 0 && error.SourceLine < sourceInfo.Count)
                {
                    var (fileIndex, line) = sourceInfo[error.SourceLine - 1];
                    error.SourceLine = line;
                    ReportError(Output.SourceFileList[fileIndex], error);
                }
                else
                {
                    ReportError(Output.SourceItem, error);
                }
                errorFound = true;
            }

            if (errorFound)
            {
                // --- Stop compilation, if macro contains error
                return;
            }

            // --- Set the source line information
            for (var i = 0; i < sourceInfo.Count; i++)
            {
                if (i < visitedLines.Lines.Count)
                {
                    var lineInfo = sourceInfo[i];
                    var line = visitedLines.Lines[i];
                    line.FileIndex = lineInfo.fileIndex;
                    line.SourceLine = lineInfo.line;
                }
            }

            // --- Now, emit the compiled lines
            lineIndex = 0;
            while (lineIndex < visitedLines.Lines.Count)
            {
                var macroLine = visitedLines.Lines[lineIndex];
                EmitSingleLine(allLines, visitedLines.Lines, macroLine, ref lineIndex, true);

                // --- Next line
                lineIndex++;
            }

            // --- Add the end label to the local scope
            var endLabel = macroDef.EndLabel;
            if (endLabel != null)
            {
                // --- Add the end label to the macro scope
                var endLine = allLines[lastLine];
                AddSymbol(endLabel, endLine, new ExpressionValue(GetCurrentAssemblyAddress()));
            }

            // --- Clean up the hanging label
            OverflowLabelLine = null;

            // --- Fixup the temporary scope over the iteration scope, if there is any
            var topScope = CurrentModule.LocalScopes.Peek();
            if (topScope != macroScope && topScope.IsTemporaryScope)
            {
                FixupSymbols(topScope.Fixups, topScope.Symbols, false);
                CurrentModule.LocalScopes.Pop();
            }

            // --- Fixup the symbols locally
            FixupSymbols(macroScope.Fixups, macroScope.Symbols, false);

            // --- Remove the macro's scope
            CurrentModule.LocalScopes.Pop();
        }

        /// <summary>
        /// Handles the invocation of a STRUCT
        /// </summary>
        /// <param name="structStmt">STRUCT invocation statement</param>
        /// <param name="structDef">Structure definition</param>
        /// <param name="allLines">All parsed lines</param>
        private void ProcessStructInvocation(MacroOrStructInvocation structStmt, StructDefinition structDef,
            List<SourceLineBase> allLines)
        {
            if (structStmt.Parameters.Count > 0)
            {
                ReportError(Errors.Z0439, structStmt, structStmt.Name);
            }

            // --- Store the structure start offset so that we can use it later for fixup.
            EnsureCodeSegment();
            _currentStructStartOffset = (ushort)CurrentSegment.CurrentOffset;

            // --- Emit the default pattern of the structure (including fixups)
            try
            {
                _isInStructCloning = true;
                for (var lineIndex = structDef.Section.FirstLine + 1; lineIndex < structDef.Section.LastLine; lineIndex++)
                {
                    var structLineIndex = lineIndex;
                    var curLine = allLines[lineIndex];
                    EmitSingleLine(allLines, allLines, curLine, ref structLineIndex);
                }
            }
            finally
            {
                _isInStructCloning = false;
            }

            // --- Sign that we are inside a struct invocation
            _currentStructInvocation = structDef;
            _currentStructLine = structStmt;
            _currentStructBytes = new Dictionary<ushort, byte>();
            _currentStructOffset = 0;
        }

        #endregion

        #region Pragma processing

        /// <summary>
        /// Applies a pragma in the assembly source code
        /// </summary>
        /// <param name="pragmaLine">Assembly line that represents a pragma</param>
        /// <param name="label">Label to use with the pragme</param>
        private void ApplyPragma(PragmaBase pragmaLine, string label)
        {
            switch (pragmaLine)
            {
                case OrgPragma orgPragma:
                    ProcessOrgPragma(orgPragma, label);
                    return;

                case BankPragma bankPragma:
                    ProcessBankPragma(bankPragma, label);
                    return;
                case XorgPragma xorgPragma:
                    ProcessXorgPragma(xorgPragma);
                    return;

                case EntPragma entPragma:
                    ProcessEntPragma(entPragma);
                    return;

                case XentPragma xentPragma:
                    ProcessXentPragma(xentPragma);
                    return;

                case DispPragma dispPragma:
                    ProcessDispPragma(dispPragma);
                    return;

                case EquPragma equPragma:
                    ProcessEquPragma(equPragma, label);
                    return;

                case VarPragma varPragma:
                    ProcessVarPragma(varPragma, label);
                    return;

                case SkipPragma skipPragma:
                    ProcessSkipPragma(skipPragma);
                    return;

                case DefbPragma defbPragma:
                    if (IsInStructInvocation)
                    {
                        ProcessDefbPragma(defbPragma, EmitStructByte);
                    }
                    else
                    {
                        ProcessDefbPragma(defbPragma);
                    }
                    return;

                case DefwPragma defwPragma:
                    if (IsInStructInvocation)
                    {
                        ProcessDefwPragma(defwPragma, EmitStructByte);
                    }
                    else
                    {
                        ProcessDefwPragma(defwPragma);
                    }
                    return;

                case DefmnPragma defmnPragma:
                    if (IsInStructInvocation)
                    {
                        ProcessDefmnPragma(defmnPragma, EmitStructByte);
                    }
                    else
                    {
                        ProcessDefmnPragma(defmnPragma);
                    }
                    break;

                case DefhPragma defhPragma:
                    if (IsInStructInvocation)
                    {
                        ProcessDefhPragma(defhPragma, EmitStructByte);
                    }
                    else
                    {
                        ProcessDefhPragma(defhPragma);
                    }
                    break;

                case DefsPragma defsPragma:
                    if (IsInStructInvocation)
                    {
                        ProcessDefsPragma(defsPragma, EmitStructByte);
                    }
                    else
                    {
                        ProcessDefsPragma(defsPragma);
                    }
                    break;

                case FillwPragma fillwPragma:
                    if (IsInStructInvocation)
                    {
                        ProcessFillwPragma(fillwPragma, EmitStructByte);
                    }
                    else
                    {
                        ProcessFillwPragma(fillwPragma);
                    }
                    break;

                case FillbPragma fillbPragma:
                    if (IsInStructInvocation)
                    {
                        ProcessFillbPragma(fillbPragma, EmitStructByte);
                    }
                    else
                    {
                        ProcessFillbPragma(fillbPragma);
                    }
                    break;

                case AlignPragma alignPragma:
                    ProcessAlignPragma(alignPragma);
                    break;

                case TracePragma tracePragma:
                    ProcessTracePragma(tracePragma);
                    break;

                case RndSeedPragma rndSeedPragma:
                    ProcessRndSeedPragma(rndSeedPragma);
                    break;

                case DefgPragma defgPragma:
                    if (IsInStructInvocation)
                    {
                        ProcessDefgPragma(defgPragma, EmitStructByte);
                    }
                    else
                    {
                        ProcessDefgPragma(defgPragma);
                    }
                    break;

                case DefgxPragma defgxPragma:
                    if (IsInStructInvocation)
                    {
                        ProcessDefgxPragma(defgxPragma, EmitStructByte);
                    }
                    else
                    {
                        ProcessDefgxPragma(defgxPragma);
                    }
                    break;

                case ErrorPragma errorPragma:
                    ProcessErrorPragma(errorPragma);
                    break;

                case IncludeBinPragma incBinPragma:
                    ProcessIncBinPragma(incBinPragma);
                    break;

                case CompareBinPragma compareBinPragma:
                    ProcessCompareBinPragma(compareBinPragma);
                    break;

                case InjectOptionPragma injectOptPragma:
                    ProcessInjectOptPragma(injectOptPragma);
                    break;
            }
        }

        /// <summary>
        /// Emits a new byte for a structure
        /// </summary>
        /// <param name="data"></param>
        private void EmitStructByte(byte data)
        {
            _currentStructBytes[(ushort)_currentStructOffset++] = data;
        }

        /// <summary>
        /// Processes the BANK pragma
        /// </summary>
        /// <param name="pragma">Assembly line of ORG pragma</param>
        /// <param name="label">Label to use</param>
        private void ProcessBankPragma(BankPragma pragma, string label)
        {
            if (!string.IsNullOrWhiteSpace(label))
            {
                // --- No label is allowed
                ReportError(Errors.Z0451, pragma);
                return;
            }

            // --- Check pragma value
            var value = EvalImmediate(pragma, pragma.Expression);
            if (!value.IsValid) return;
            if (value.AsWord() > 7)
            {
                ReportError(Errors.Z0453, pragma);
                return;
            }

            // --- Check offsetValue
            ushort offset = 0;
            if (pragma.StartOffset != null)
            {
                var offsetValue = EvalImmediate(pragma, pragma.StartOffset);
                if (!offsetValue.IsValid) return;
                offset = offsetValue.AsWord();
                if (offset > 0x3fff)
                {
                    ReportError(Errors.Z0455, pragma);
                    return;
                }
            }

            // --- Check for appropriate model type
            if (Output.ModelType == null || Output.ModelType == SpectrumModelType.Spectrum48)
            {
                ReportError(Errors.Z0452, pragma);
                return;
            }

            EnsureCodeSegment((ushort)(0xC000 + offset));
            if (CurrentSegment.CurrentOffset != 0 || CurrentSegment.Bank != null)
            {
                // --- There is already code emitted for the current segment,
                // --- thus create a new segment
                CurrentSegment = new BinarySegment();
                Output.Segments.Add(CurrentSegment);
            }
            if (Output.Segments.Any(s => s.Bank == value.Value))
            {
                // --- A bank can be used only once
                ReportError(Errors.Z0454, pragma, value.Value);
                return;
            }
            CurrentSegment.StartAddress = (ushort)(0xC000 + offset);
            CurrentSegment.Bank = value.Value;
            CurrentSegment.BankOffset = offset;
            CurrentSegment.MaxCodeLength = 0x4000 - offset;
        }

        /// <summary>
        /// Processes the INJECTOPT pragma
        /// </summary>
        /// <param name="pragma">Assembly line of INJECTOPT pragma</param>
        private void ProcessInjectOptPragma(InjectOptionPragma pragma)
        {
            Output.InjectOptions.Add(pragma.Option);
        }

        /// <summary>
        /// Processes the ORG pragma
        /// </summary>
        /// <param name="pragma">Assembly line of ORG pragma</param>
        /// <param name="label">Label to use</param>
        private void ProcessOrgPragma(OrgPragma pragma, string label)
        {
            var value = EvalImmediate(pragma, pragma.Expression);
            if (!value.IsValid) return;

            EnsureCodeSegment();
            if (CurrentSegment.CurrentOffset != 0)
            {
                // --- There is already code emitted for the current segment
                CurrentSegment = new BinarySegment
                {
                    StartAddress = value.Value,
                    MaxCodeLength = 0x10000
                };
                Output.Segments.Add(CurrentSegment);
            }
            else
            {
                CurrentSegment.StartAddress = value.Value;
            }

            if (label == null)
            {
                return;
            }
            FixupTemporaryScope();

            // --- There is a label, set its value
            AddSymbol(label, pragma, value);
        }

        /// <summary>
        /// Processes the ENT pragma
        /// </summary>
        /// <param name="pragma">Assembly line of ENT pragma</param>
        private void ProcessEntPragma(EntPragma pragma)
        {
            if (!IsInGlobalScope && ShouldReportErrorInCurrentScope(Errors.Z0407))
            {
                ReportError(Errors.Z0407, pragma, "ENT");
            }
            var value = Eval(pragma, pragma.Expression);
            if (value.IsNonEvaluated)
            {
                RecordFixup(pragma, FixupType.Ent, pragma.Expression);
                return;
            }
            Output.EntryAddress = value.Value;
        }

        /// <summary>
        /// Processes the XENT pragma
        /// </summary>
        /// <param name="pragma">Assembly line of XENT pragma</param>
        private void ProcessXentPragma(XentPragma pragma)
        {
            if (!IsInGlobalScope && ShouldReportErrorInCurrentScope(Errors.Z0407))
            {
                ReportError(Errors.Z0407, pragma, "XENT");
            }
            var value = Eval(pragma, pragma.Expression);
            if (value.IsNonEvaluated)
            {
                RecordFixup(pragma, FixupType.Xent, pragma.Expression);
                return;
            }
            Output.ExportEntryAddress = value.Value;
        }

        /// <summary>
        /// Processes the DISP pragma
        /// </summary>
        /// <param name="pragma">Assembly line of DISP pragma</param>
        private void ProcessDispPragma(DispPragma pragma)
        {
            var value = EvalImmediate(pragma, pragma.Expression);
            if (!value.IsValid) return;

            EnsureCodeSegment();
            CurrentSegment.Displacement = value.Value;
            CurrentSegment.DispPragmaOffset = (ushort)(CurrentSegment.StartAddress + CurrentSegment.CurrentOffset);
        }

        /// <summary>
        /// Processes the XORG pragma
        /// </summary>
        /// <param name="pragma">Assembly line of DISP pragma</param>
        private void ProcessXorgPragma(XorgPragma pragma)
        {
            var value = EvalImmediate(pragma, pragma.Expression);
            if (!value.IsValid) return;

            EnsureCodeSegment();
            if (CurrentSegment.CurrentOffset != 0 && CurrentSegment.XorgValue.HasValue)
            {
                ReportError(Errors.Z0431, pragma);
                return;
            }
            CurrentSegment.XorgValue = value.Value;
        }

        /// <summary>
        /// Processes the EQU pragma
        /// </summary>
        /// <param name="pragma">Assembly line of EQU pragma</param>
        /// <param name="label">Label to use</param>
        private void ProcessEquPragma(EquPragma pragma, string label)
        {
            // --- Check label validity
            if (label == null)
            {
                ReportError(Errors.Z0082, pragma);
                return;
            }
            FixupTemporaryScope();

            // --- Do not allow duplicate labels
            if (SymbolExists(label))
            {
                ReportError(Errors.Z0040, pragma, label);
                return;
            }

            // --- Evaluate EQU value
            var value = Eval(pragma, pragma.Expression);
            if (value.IsNonEvaluated)
            {
                RecordFixup(pragma, FixupType.Equ, pragma.Expression, label);
            }
            else
            {
                AddSymbol(label, pragma, value);
            }
        }

        /// <summary>
        /// Checks if there's a temporary scope, and disposes it after a fixup.
        /// </summary>
        private void FixupTemporaryScope()
        {
            if (CurrentModule.LocalScopes.Count <= 0) return;
            var topScope = CurrentModule.LocalScopes.Peek();
            if (!topScope.IsTemporaryScope) return;
            FixupSymbols(topScope.Fixups, topScope.Symbols, false);
            CurrentModule.LocalScopes.Pop();
        }

        /// <summary>
        /// Processes the VAR pragma
        /// </summary>
        /// <param name="pragma">Assembly line of VAR pragma</param>
        /// <param name="label">Label to use</param>
        private void ProcessVarPragma(VarPragma pragma, string label)
        {
            if (label == null)
            {
                ReportError(Errors.Z0086, pragma);
                return;
            }
            FixupTemporaryScope();

            var value = EvalImmediate(pragma, pragma.Expression);
            if (!value.IsValid) return;

            // --- Allow reusing a symbol already declared
            if (SymbolExists(label))
            {
                ReportError(Errors.Z0087, pragma);
                return;
            }
            SetVariable(label, value);
        }

        /// <summary>
        /// Processes the SKIP pragma
        /// </summary>
        /// <param name="pragma">Assembly line of SKIP pragma</param>
        private void ProcessSkipPragma(SkipPragma pragma)
        {
            var skipAddr = EvalImmediate(pragma, pragma.Expression);
            if (!skipAddr.IsValid) return;

            var currentAddr = GetCurrentAssemblyAddress();
            if (skipAddr.Value < currentAddr)
            {
                ReportError(Errors.Z0081, pragma, $"{skipAddr:X4}", $"{currentAddr:X4}");
                return;
            }
            var fillByte = 0xff;
            if (pragma.Fill != null)
            {
                var fillValue = EvalImmediate(pragma, pragma.Fill);
                if (fillValue == null) return;
                fillByte = fillValue.Value;
            }

            while (currentAddr < skipAddr.Value)
            {
                EmitByte((byte)fillByte);
                currentAddr++;
            }
        }

        /// <summary>
        /// Processes the DEFB pragma
        /// </summary>
        /// <param name="pragma">Assembly line of DEFB pragma</param>
        /// <param name="emitAction">Action to emit a code byte</param>
        private void ProcessDefbPragma(DefbPragma pragma, Action<byte> emitAction = null)
        {
            foreach (var expr in pragma.Exprs)
            {
                var value = Eval(pragma, expr);
                if (value.IsValid)
                {
                    if (value.Type == ExpressionValueType.String)
                    {
                        if (_options.FlexibleDefPragmas)
                        {
                            // --- In flexible mode, we allow strings...
                            EmitString(value, false, false, emitAction);
                        }
                        else
                        {
                            // --- ...otherwise, we accept only numeric values
                            ReportError(Errors.Z0305, pragma);
                        }
                    }
                    else
                    {
                        Emit((byte)value.Value);
                    }
                }
                else if (value.IsNonEvaluated)
                {
                    RecordFixup(pragma, FixupType.Bit8, expr);
                    Emit(0x00);
                }
            }

            // --- Emits a byte
            void Emit(byte value)
            {
                if (emitAction != null)
                {
                    emitAction(value);
                }
                else
                {
                    EmitByte(value);
                }
            }
        }

        /// <summary>
        /// Processes the DEFW pragma
        /// </summary>
        /// <param name="pragma">Assembly line of DEFW pragma</param>
        /// <param name="emitAction">Action to emit a code byte</param>
        private void ProcessDefwPragma(DefwPragma pragma, Action<byte> emitAction = null)
        {
            foreach (var expr in pragma.Exprs)
            {
                var value = Eval(pragma, expr);
                if (value.IsValid)
                {
                    if (value.Type == ExpressionValueType.String)
                    {
                        ReportError(Errors.Z0305, pragma);
                        return;
                    }
                    Emit(value.Value);
                }
                else if (value.IsNonEvaluated)
                {
                    RecordFixup(pragma, FixupType.Bit16, expr);
                    Emit(0x0000);
                }
            }

            // --- Emits a word
            void Emit(ushort value)
            {
                if (emitAction != null)
                {
                    emitAction((byte)value);
                    emitAction((byte)(value >> 8));
                }
                else
                {
                    EmitWord(value);
                }
            }
        }

        /// <summary>
        /// Processes the DEFN pragma
        /// </summary>
        /// <param name="pragma">Assembly line of DEFN pragma</param>
        /// <param name="emitAction">Action to emit a code byte</param>
        // ReSharper disable once UnusedParameter.Local
        private void ProcessDefmnPragma(DefmnPragma pragma, Action<byte> emitAction = null)
        {
            var message = EvalImmediate(pragma, pragma.Message);
            if (message.IsValid && message.Type != ExpressionValueType.String)
            {
                if (_options.FlexibleDefPragmas)
                {
                    // --- In flexible mode, the argument expression can be numeric...
                    var value = (byte)(message.AsByte() | (pragma.Bit7Terminator ? 0x80 : 0x00));
                    if (emitAction != null)
                    {
                        emitAction(value);
                        if (pragma.NullTerminator) emitAction(0x00);
                    }
                    else
                    {
                        EmitByte(value);
                        if (pragma.NullTerminator) EmitByte(0x00);
                    }
                }
                else
                {
                    // --- otherwise, only string is accepted.
                    ReportError(Errors.Z0091, pragma);
                }
            } else
            {
                EmitString(message, pragma.Bit7Terminator, pragma.NullTerminator, emitAction);
            }
        }

        /// <summary>
        /// Emits a string
        /// </summary>
        /// <param name="message">Expression with the string</param>
        /// <param name="bit7Terminator">Bit 7 terminator flag</param>
        /// <param name="nullTerminator">Null terminator flag</param>
        /// <param name="emitAction">Action to emit a code byte</param>
        private void EmitString(ExpressionValue message, bool bit7Terminator, bool nullTerminator, Action<byte> emitAction = null)
        {
            var bytes = SpectrumStringToBytes(message.AsString());
            if (bytes.Count > 1)
            {
                for (var i = 0; i < bytes.Count - 1; i++)
                {
                    Emit(bytes[i]);
                }
            }
            var lastByte = (byte)(bytes[bytes.Count - 1] | (bit7Terminator ? 0x80 : 0x00));
            Emit(lastByte);
            if (nullTerminator)
            {
                Emit(0x00);
            }

            // --- Emits a byte
            void Emit(byte value)
            {
                if (emitAction != null)
                {
                    emitAction(value);
                }
                else
                {
                    EmitByte(value);
                }
            }
        }

        /// <summary>
        /// Processes the DEFH pragma
        /// </summary>
        /// <param name="pragma">Assembly line of DEFH pragma</param>
        /// <param name="emitAction">Action to emit a code byte</param>
        // ReSharper disable once UnusedParameter.Local
        private void ProcessDefhPragma(DefhPragma pragma, Action<byte> emitAction = null)
        {
            var byteVector = EvalImmediate(pragma, pragma.ByteVector);
            if (byteVector.IsValid && byteVector.Type != ExpressionValueType.String)
            {
                ReportError(Errors.Z0093, pragma);
                return;
            }

            // --- Check if the byte vector is valid
            var bytesString = byteVector.AsString();
            if (bytesString.Length % 2 != 0)
            {
                ReportError(Errors.Z0094, pragma);
                return;
            }

            // --- Convert the byte vector
            try
            {
                var bytes = Enumerable.Range(0, bytesString.Length)
                    .Where(x => x % 2 == 0)
                    .Select(x => Convert.ToByte(bytesString.Substring(x, 2), 16))
                    .ToArray();
                foreach (var msgByte in bytes)
                {
                    Emit(msgByte);
                }
            }
            catch (Exception)
            {
                ReportError(Errors.Z0094, pragma);
            }

            // --- Emits a byte
            void Emit(byte value)
            {
                if (emitAction != null)
                {
                    emitAction(value);
                }
                else
                {
                    EmitByte(value);
                }
            }
        }

        /// <summary>
        /// Processes the DEFS pragma
        /// </summary>
        /// <param name="pragma">Assembly line of DEFS pragma</param>
        /// <param name="emitAction">Action to emit a code byte</param>
        private void ProcessDefsPragma(DefsPragma pragma, Action<byte> emitAction = null)
        {
            var count = Eval(pragma, pragma.Count);
            if (!count.IsValid)
            {
                ReportError(Errors.Z0201, pragma, ExpressionNode.SymbolErrors);
                return;
            }
            var fillValue = (byte)0x00;
            if (pragma.Value != null)
            {
                var value = Eval(pragma, pragma.Value);
                if (!value.IsValid)
                {
                    ReportError(Errors.Z0201, pragma, ExpressionNode.SymbolErrors);
                    return;
                }
                fillValue = value.AsByte();
            }
            for (var i = 0; i < count.Value; i++)
            {
                if (emitAction != null)
                {
                    emitAction(0x00);
                }
                else
                {
                    EmitByte(fillValue);
                }
            }
        }

        /// <summary>
        /// Processes the FILLB pragma
        /// </summary>
        /// <param name="pragma">Assembly line of FILLB pragma</param>
        /// <param name="emitAction">Action to emit a code byte</param>
        private void ProcessFillbPragma(FillbPragma pragma, Action<byte> emitAction = null)
        {
            var count = Eval(pragma, pragma.Count);
            if (!count.IsValid)
            {
                ReportError(Errors.Z0201, pragma, ExpressionNode.SymbolErrors);
            }
            var value = Eval(pragma, pragma.Expression);
            if (!value.IsValid)
            {
                ReportError(Errors.Z0201, pragma, ExpressionNode.SymbolErrors);
            }
            if (!count.IsValid || !value.IsValid)
            {
                return;
            }

            for (var i = 0; i < count.Value; i++)
            {
                if (emitAction != null)
                {
                    emitAction(value.AsByte());
                }
                else
                {
                    EmitByte(value.AsByte());
                }
            }
        }

        /// <summary>
        /// Processes the FILLW pragma
        /// </summary>
        /// <param name="pragma">Assembly line of FILLW pragma</param>
        /// <param name="emitAction">Action to emit a code byte</param>
        private void ProcessFillwPragma(FillwPragma pragma, Action<byte> emitAction = null)
        {
            var count = Eval(pragma, pragma.Count);
            var value = Eval(pragma, pragma.Expression);
            if (!count.IsValid || !value.IsValid)
            {
                ReportError(Errors.Z0201, pragma, ExpressionNode.SymbolErrors);
                return;
            }

            for (var i = 0; i < count.Value; i++)
            {
                var word = value.AsWord();
                if (emitAction != null)
                {
                    emitAction((byte)word);
                    emitAction((byte)(word >> 8));
                }
                else
                {
                    EmitWord(word);
                }
            }
        }

        /// <summary>
        /// Processes the MODEL pragma
        /// </summary>
        /// <param name="pragma">Assembly line of MODEL pragma</param>
        private void ProcessModelPragma(ModelPragma pragma)
        {
            if (Output.ModelType != null)
            {
                ReportError(Errors.Z0088, pragma);
                return;
            }

            SpectrumModelType modelType;
            switch (pragma.Model.ToUpper())
            {
                case "SPECTRUM48":
                    modelType = SpectrumModelType.Spectrum48;
                    break;
                case "SPECTRUM128":
                    modelType = SpectrumModelType.Spectrum128;
                    break;
                case "SPECTRUMP3":
                    modelType = SpectrumModelType.SpectrumP3;
                    break;
                case "NEXT":
                    modelType = SpectrumModelType.Next;
                    break;
                default:
                    ReportError(Errors.Z0089, pragma);
                    return;
            }

            Output.ModelType = modelType;
        }

        /// <summary>
        /// Processes the ALIGN pragma
        /// </summary>
        /// <param name="pragma">Assembly line of ALIGN pragma</param>
        private void ProcessAlignPragma(AlignPragma pragma)
        {
            var alignment = 0x0100;
            if (pragma.Expression != null)
            {
                var alignValue = EvalImmediate(pragma, pragma.Expression);
                if (!alignValue.IsValid) return;
                alignment = alignValue.Value;
                if (alignment < 1 || alignment > 0x4000)
                {
                    ReportError(Errors.Z0092, pragma, alignment);
                    return;
                }
            }

            var currentAddress = GetCurrentAssemblyAddress();
            var newAddress = currentAddress % alignment == 0
                                 ? currentAddress
                                 : (currentAddress / alignment + 1) * alignment;
            for (var i = currentAddress; i < newAddress; i++)
            {
                EmitByte(0x00);
            }
        }

        /// <summary>
        /// Processes the TRACE pragma
        /// </summary>
        /// <param name="pragma">Assembly line of TRACE pragma</param>
        private void ProcessTracePragma(TracePragma pragma)
        {
            var message = new StringBuilder(1024);
            foreach (var expr in pragma.Exprs)
            {
                var exprValue = EvalImmediate(pragma, expr);
                if (!exprValue.IsValid) return;

                switch (exprValue.Type)
                {
                    case ExpressionValueType.Bool:
                        message.Append(exprValue.AsBool());
                        break;
                    case ExpressionValueType.Integer:
                        var intValue = exprValue.AsLong();
                        if (pragma.IsHex)
                        {
                            var valueStr = intValue > 0x10000
                                ? $"{intValue:X8}"
                                : $"{intValue:X4}";
                            message.Append(valueStr);
                        }
                        else
                        {
                            message.Append(intValue);
                        }
                        break;
                    case ExpressionValueType.Real:
                        message.AppendFormat(CultureInfo.InvariantCulture, "{0}", exprValue.AsReal());
                        break;
                    case ExpressionValueType.String:
                        if (pragma.IsHex)
                        {
                            var bytes = SpectrumStringToBytes(exprValue.AsString());
                            foreach (var msgByte in bytes)
                            {
                                message.Append($"{msgByte:X2}");
                            }
                        }
                        else
                        {
                            message.Append(exprValue.AsString());
                        }
                        break;
                }
            }
            OnAssemblerMessageCreated(message.ToString());
        }

        /// <summary>
        /// Processes the RNDSEED pragma
        /// </summary>
        /// <param name="pragma">Assembly line of RNDSEED pragma</param>
        private void ProcessRndSeedPragma(RndSeedPragma pragma)
        {
            if (pragma.Expression == null)
            {
                FunctionInvocationNode.SetRandomSeed(null);
                return;
            }

            var seedValue = EvalImmediate(pragma, pragma.Expression);
            FunctionInvocationNode.SetRandomSeed(seedValue);
        }

        /// <summary>
        /// Processes the DEFG pragma
        /// </summary>
        /// <param name="pragma">Assembly line of DEFG pragma</param>
        /// <param name="emitAction">Action to emit a code byte</param>
        private void ProcessDefgPragma(DefgPragma pragma, Action<byte> emitAction = null)
        {
            // --- Obtain and check the DEFG pattern expression
            var pattern = pragma.Pattern;
            EmitDefgBytes(pragma, pattern, false, emitAction);
        }

        /// <summary>
        /// Processes the DEFG pragma
        /// </summary>
        /// <param name="pragma">Assembly line of DEFG pragma</param>
        /// <param name="emitAction">Action to emit a code byte</param>
        private void ProcessDefgxPragma(DefgxPragma pragma, Action<byte> emitAction = null)
        {
            // --- Obtain and check the DEFG pattern expression
            var value = EvalImmediate(pragma, pragma.Expression);
            if (!value.IsValid) return;

            if (value.Type != ExpressionValueType.String)
            {
                ReportError(Errors.Z0306, pragma);
                return;
            }

            var pattern = value.AsString().Trim();
            EmitDefgBytes(pragma, pattern, true, emitAction);
        }

        /// <summary>
        /// Emits the pattern bytes for DEFG/DEFGX
        /// </summary>
        /// <param name="pragma">Pragma instance</param>
        /// <param name="pattern">Pattern to emit</param>
        /// <param name="allowAlign">Signs if alignment indicators are allowed or not.</param>
        /// <param name="emitAction">Action to emit a code byte</param>
        private void EmitDefgBytes(SourceLineBase pragma, string pattern, 
            bool allowAlign = true, Action<byte> emitAction = null)
        {
            if (string.IsNullOrEmpty(pattern))
            {
                ReportError(Errors.Z0307, pragma);
                return;
            }

            // --- Go through all values
            var alignToLeft = true;
            if (pattern[0] == '<' && allowAlign)
            {
                pattern = pattern.Substring(1);
            }
            else if (pattern[0] == '>' && allowAlign)
            {
                alignToLeft = false;
                pattern = pattern.Substring(1);
            }
            pattern = pattern.Replace(" ", "");
            if (pattern.Length == 0) return;

            var remainingBits = pattern.Length % 8;
            if (remainingBits > 0)
            {
                pattern = alignToLeft
                    ? pattern.PadRight(pattern.Length + 8 - remainingBits, '_')
                    : pattern.PadLeft(pattern.Length + 8 - remainingBits, '_');
            }

            var bitPattern = 0x00;
            for (var i = 0; i < pattern.Length; i++)
            {
                // --- Calculate the bit pattern
                switch (pattern[i])
                {
                    case '-':
                    case '.':
                    case '_':
                        bitPattern <<= 1;
                        break;
                    default:
                        bitPattern = (bitPattern << 1) | 1;
                        break;
                }
                if ((i + 1) % 8 != 0) continue;

                // --- Emit a full byte
                if (emitAction != null)
                {
                    emitAction((byte)bitPattern);
                }
                else
                {
                    EmitByte((byte)bitPattern);
                }
                bitPattern = 0x00;
            }
        }

        /// <summary>
        /// Processes the ERROR pragma
        /// </summary>
        /// <param name="pragma">Assembly line of DEFG pragma</param>
        private void ProcessErrorPragma(ErrorPragma pragma)
        {
            var errorValue = EvalImmediate(pragma, pragma.Expression);
            if (!errorValue.IsValid) return;
            ReportError(Errors.Z0500, pragma, errorValue.AsString());
        }

        /// <summary>
        /// Processes the INCLUDEBIN pragma
        /// </summary>
        /// <param name="pragma">Assembly line of DEFG pragma</param>
        private void ProcessIncBinPragma(IncludeBinPragma pragma)
        {
            // --- Obtain the file name
            var fileNameValue = EvalImmediate(pragma, pragma.FileExpr);
            if (!fileNameValue.IsValid) return;

            if (fileNameValue.Type != ExpressionValueType.String)
            {
                ReportError(Errors.Z0306, pragma);
                return;
            }

            // --- Obtain optional offset
            var offset = 0;
            if (pragma.OffsetExpr != null)
            {
                var offsValue = EvalImmediate(pragma, pragma.OffsetExpr);
                if (offsValue.Type != ExpressionValueType.Integer)
                {
                    ReportError(Errors.Z0308, pragma);
                    return;
                }
                offset = (int)offsValue.AsLong();
                if (offset < 0)
                {
                    ReportError(Errors.Z0424, pragma);
                    return;
                }
            }

            // --- Obtain optional length
            int? length = null;
            if (pragma.LengthExpr != null)
            {
                var lengthValue = EvalImmediate(pragma, pragma.LengthExpr);
                if (lengthValue.Type != ExpressionValueType.Integer)
                {
                    ReportError(Errors.Z0308, pragma);
                    return;
                }
                length = (int)lengthValue.AsLong();
                if (length < 0)
                {
                    ReportError(Errors.Z0425, pragma);
                    return;
                }
            }

            // --- Read the binary file
            var currentSourceFile = Output.SourceFileList[pragma.FileIndex];
            var dirname = Path.GetDirectoryName(currentSourceFile.Filename) ?? string.Empty;
            var filename = Path.Combine(dirname, fileNameValue.AsString());

            byte[] contents;
            try
            {
                var fileLength = new FileInfo(filename).Length;
                using (var reader = new BinaryReader(File.OpenRead(filename)))
                {
                    contents = reader.ReadBytes((int)fileLength);
                }
            }
            catch (Exception e)
            {
                ReportError(Errors.Z0423, pragma, e.Message);
                return;
            }

            // --- Check content segment
            if (offset >= contents.Length)
            {
                ReportError(Errors.Z0424, pragma);
                return;
            }

            if (length == null)
            {
                length = contents.Length - offset;
            }

            // --- Check length
            if (offset + length > contents.Length)
            {
                ReportError(Errors.Z0425, pragma);
                return;
            }

            // --- Check for too long binary segment
            if (GetCurrentAssemblyAddress() + length >= 0x10000)
            {
                ReportError(Errors.Z0426, pragma);
                return;
            }

            // --- Everything is ok, emit the binary data
            for (var i = offset; i < offset + length; i++)
            {
                EmitByte(contents[i]);
            }
        }

        /// <summary>
        /// Processes the COMPAREBIN pragma
        /// </summary>
        /// <param name="pragma">Assembly line of DEFG pragma</param>
        private void ProcessCompareBinPragma(CompareBinPragma pragma)
        {
            // --- Obtain the file name
            var fileNameValue = EvalImmediate(pragma, pragma.FileExpr);
            if (!fileNameValue.IsValid) return;

            if (fileNameValue.Type != ExpressionValueType.String)
            {
                ReportError(Errors.Z0306, pragma);
                return;
            }

            // --- Store pragma information
            CompareBins.Add(new BinaryComparisonInfo(pragma, 
                CurrentSegment, 
                CurrentSegment.CurrentOffset));
        }

        #endregion

        #region Operations code emitting

        /// <summary>
        /// Emits code for the specified operation
        /// </summary>
        /// <param name="opLine">Operation to emit the code for</param>
        private void EmitAssemblyOperationCode(SourceLineBase opLine)
        {
            // --- This line might be a single label
            if (opLine is NoInstructionLine)
            {
                return;
            }

            // --- Handle the trivial operations (with simple mnemonics, like
            // --- nop, ldir, scf, etc.
            var trivOpLine = opLine as TrivialOperation;
            if (trivOpLine != null)
            {
                if (trivOpLine is TrivialNextOperation && Output.ModelType != SpectrumModelType.Next)
                {
                    ReportError(Errors.Z0102, opLine);
                    return;
                }
                EmitTrivialOperation(trivOpLine);
                return;
            }

            // --- Handle compound operations
            var compoundOpLine = opLine as CompoundOperation;
            if (compoundOpLine != null)
            {
                EmitCompoundOperation(compoundOpLine);
                return;
            }

            // --- Any other case means an internal error
            ReportError(Errors.Z0083, opLine, opLine.GetType().FullName);
        }

        /// <summary>
        /// Emits code for trivial operations
        /// </summary>
        /// <param name="opLine">
        /// Assembly line that denotes a trivial Z80 operation.
        /// </param>
        private void EmitTrivialOperation(OperationBase opLine)
        {
            EmitOperationWithLookup(s_TrivialOpBytes, opLine.Mnemonic, opLine);
        }

        /// <summary>
        /// Emits a compound operation
        /// </summary>
        /// <param name="compoundOpLine">
        /// Assembly line that denotes a compound Z80 operation.
        /// </param>
        private void EmitCompoundOperation(CompoundOperation compoundOpLine)
        {
            if (!_compoundOpTable.TryGetValue(compoundOpLine.Mnemonic, out var rules))
            {
                ReportError(Errors.Z0084, compoundOpLine, compoundOpLine.Mnemonic);
                return;
            }

            // --- Get the operand types
            var op1Type = compoundOpLine.Operand?.Type ?? OperandType.None;
            var op2Type = compoundOpLine.Operand2?.Type ?? OperandType.None;

            var isProcessable = true;

            // --- Check inclusive rules
            if (rules.Allow != null)
            {
                isProcessable = rules.Allow.Any(r => r.FirstOp == op1Type && r.SecondOp == op2Type);
            }

            // --- We applied operands according to rules
            if (isProcessable)
            {
                rules.ProcessAction(this, compoundOpLine);
                return;
            }

            // --- This operations is invalid. Report it with the proper message.
            ReportError(Errors.Z0001, compoundOpLine, compoundOpLine.Mnemonic);
        }

        /// <summary>
        /// LD operations
        /// </summary>
        private static void ProcessLd(Z80Assembler asm, CompoundOperation op)
        {
            // --- Destination is an 8-bit register
            if (op.Operand.Type == OperandType.Reg8)
            {
                var destReg = op.Operand.Register;
                var destRegIdx = s_Reg8Order.IndexOf(destReg);
                var sourceReg = op.Operand2.Register;

                if (op.Operand2.Type == OperandType.Reg8)
                {
                    // ld '8bitreg','8bitReg'
                    asm.EmitByte((byte) (0x40 + (destRegIdx << 3) + s_Reg8Order.IndexOf(sourceReg)));
                    return;
                }

                if (op.Operand2.Type == OperandType.RegIndirect)
                {
                    if (sourceReg == "(BC)")
                    {
                        if (destReg == "A")
                        {
                            // ld a,(bc)
                            asm.EmitByte(0x0A);
                            return;
                        }
                    }
                    else if (sourceReg == "(DE)")
                    {
                        if (destReg == "A")
                        {
                            // ld a,(de)
                            asm.EmitByte(0x1A);
                            return;
                        }
                    }
                    else if (sourceReg == "(HL)")
                    {
                        // ld '8bitreg',(hl)
                        asm.EmitByte((byte) (0x46 + (destRegIdx << 3)));
                        return;
                    }
                    asm.ReportInvalidLoadOp(op, destReg, sourceReg);
                    return;
                }

                if (op.Operand2.Type == OperandType.Reg8Spec)
                {
                    // ld a,i and ld a,r
                    if (op.Operand.Register != "A")
                    {
                        asm.ReportInvalidLoadOp(op, destReg, sourceReg);
                        return;
                    }
                    asm.EmitDoubleByte(sourceReg == "R" ? 0xED5F : 0xED57);
                    return;
                }

                if (op.Operand2.Type == OperandType.Reg8Idx)
                {
                    // ld reg,'xh|xl|yh|yl'
                    // --- Destination must be one of the indexed 8-bit registers
                    if (destRegIdx >= 4 && destRegIdx <= 6)
                    {
                        // --- Deny invalid destination: h, l, (hl)
                        asm.ReportInvalidLoadOp(op, destReg, sourceReg);
                        return;
                    }
                    var opCode = sourceReg.Contains("X") ? 0xDD44 : 0xFD44;
                    asm.EmitDoubleByte(opCode + (destRegIdx << 3) + (sourceReg.EndsWith("H") ? 0 : 1));
                    return;
                }

                if (op.Operand2.Type == OperandType.Expr)
                {
                    // ld reg,expr
                    asm.EmitByte((byte)(0x06 + (destRegIdx << 3)));
                    asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit8);
                    return;
                }

                if (op.Operand2.Type == OperandType.MemIndirect)
                {
                    // ld a,(expr)
                    if (destReg != "A")
                    {
                        asm.ReportInvalidLoadOp(op, destReg, sourceReg);
                        return;
                    }
                    asm.EmitByte(0x3A);
                    asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit16);
                    return;
                }

                if (op.Operand2.Type == OperandType.IndexedAddress)
                {
                    // --- ld '8-bit-reg', '(idxreg+disp)' operation
                    var opCode = (byte)(0x46 + (destRegIdx << 3));
                    asm.EmitIndexedOperation(op, op.Operand2, opCode);
                    return;
                }
            }

            // --- Destination is an 8-bit index register
            if (op.Operand.Type == OperandType.Reg8Idx)
            {
                var destReg = op.Operand.Register;
                var sourceReg = op.Operand2.Register;
                if (op.Operand2.Type == OperandType.Reg8)
                {
                    // ld 'xh|xl|yh|yl', reg
                    var sourceRegIdx = s_Reg8Order.IndexOf(sourceReg);

                    // --- Destination must be one of the indexed 8-bit registers
                    if (sourceRegIdx >= 4 && sourceRegIdx <= 6)
                    {
                        // --- Deny invalid destination: h, l, (hl)
                        asm.ReportInvalidLoadOp(op, destReg, sourceReg);
                        return;
                    }
                    var opBytes = destReg.Contains("X") ? 0xDD60 : 0xFD60;
                    asm.EmitDoubleByte(opBytes + (destReg.EndsWith("H") ? 0 : 8) + sourceRegIdx);
                    return;
                }

                if (op.Operand2.Type == OperandType.Reg8Idx)
                {
                    // ld 'xh|xl|yh|yl', 'xh|xl|yh|yl'
                    if (sourceReg[0] != destReg[0])
                    {
                        asm.ReportInvalidLoadOp(op, destReg, sourceReg);
                        return;
                    }

                    var xopBytes = destReg.Contains("X") ? 0xDD64 : 0xFD64;
                    asm.EmitDoubleByte(xopBytes + (destReg.EndsWith("H") ? 0 : 8)
                                       + (sourceReg.EndsWith("H") ? 0 : 1));
                    return;
                }

                // ld 'xh|xl|yh|yl',expr
                var opCode = destReg.Contains("X") ? 0xDD26 : 0xFD26;
                opCode += destReg.EndsWith("H") ? 0 : 8;
                asm.EmitDoubleByte(opCode);
                asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit8);
                return;
            }

            // --- Destination is I or A
            if (op.Operand.Type == OperandType.Reg8Spec)
            {
                // ld i,a and ld r,a
                if (op.Operand2.Register != "A")
                {
                    asm.ReportInvalidLoadOp(op, op.Operand.Register, op.Operand2.Register);
                    return;
                }
                asm.EmitDoubleByte(op.Operand.Register == "R" ? 0xED4F : 0xED47);
                return;
            }

            // --- Destination is memory through a 16-bit register
            if (op.Operand.Type == OperandType.RegIndirect)
            {
                var destReg = op.Operand.Register;
                if (op.Operand2.Type == OperandType.Reg8)
                {
                    var sourceReg = op.Operand2.Register;
                    if (destReg == "(BC)")
                    {
                        if (sourceReg == "A")
                        {
                            // ld (bc),a
                            asm.EmitByte(0x02);
                            return;
                        }
                    }
                    else if (destReg == "(DE)")
                    {
                        if (sourceReg == "A")
                        {
                            // ld (de),a
                            asm.EmitByte(0x12);
                            return;
                        }
                    }
                    else if (destReg == "(HL)")
                    {
                        // ld (hl),'8BitReg'
                        asm.EmitByte((byte)(0x70 + s_Reg8Order.IndexOf(sourceReg)));
                        return;
                    }
                    asm.ReportInvalidLoadOp(op, destReg, sourceReg);
                    return;
                }

                if (op.Operand2.Type == OperandType.Expr)
                {
                    if (op.Operand.Register != "(HL)")
                    {
                        asm.ReportInvalidLoadOp(op, destReg, "<expression>");
                        return;
                    }
                    // ld (hl),expr
                    asm.EmitByte(0x36);
                    asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit8);
                    return;
                }

                return;
            }

            // --- Destination is a memory address
            if (op.Operand.Type == OperandType.MemIndirect)
            {
                if (op.Operand2.Type == OperandType.Reg8)
                {
                    if (op.Operand2.Register != "A")
                    {
                        asm.ReportInvalidLoadOp(op, "(<expression>)", op.Operand2.Register);
                        return;
                    }
                    asm.EmitByte(0x32);
                }
                else if (op.Operand2.Type == OperandType.Reg16)
                {
                    // ld (expr),reg16
                    var sourceReg = op.Operand2.Register;
                    var opCode = 0x22;
                    if (sourceReg == "BC")
                    {
                        opCode = 0xED43;
                    }
                    else if (sourceReg == "DE")
                    {
                        opCode = 0xED53;
                    }
                    else if (sourceReg == "SP")
                    {
                        opCode = 0xED73;
                    }
                    asm.EmitDoubleByte(opCode);
                }
                else if (op.Operand2.Type == OperandType.Reg16Idx)
                {
                    asm.EmitDoubleByte(op.Operand2.Register == "IX" ? 0xDD22 : 0xFD22);
                }
                asm.EmitumNumericExpression(op, op.Operand.Expression, FixupType.Bit16);
                return;
            }

            // --- Destination is a 16-bit register
            if (op.Operand.Type == OperandType.Reg16)
            {
                var destReg = op.Operand.Register;
                if (op.Operand2.Type == OperandType.MemIndirect)
                {
                    // ld reg16,(expr)
                    var opCode = 0x2A;
                    if (destReg == "BC")
                    {
                        opCode = 0xED4B;
                    }
                    else if (destReg == "DE")
                    {
                        opCode = 0xED5B;
                    }
                    else if (destReg == "SP")
                    {
                        opCode = 0xED7B;
                    }
                    asm.EmitDoubleByte(opCode);
                    asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit16);
                    return;
                }

                if (op.Operand2.Type == OperandType.Expr)
                {
                    // ld reg16,expr
                    var sourceRegIdx = s_Reg16Order.IndexOf(op.Operand.Register);
                    asm.EmitByte((byte)(0x01 + (sourceRegIdx << 4)));
                    asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit16);
                    return;
                }

                // --- From now on, the destination can be only SP

                if (op.Operand.Register != "SP")
                {
                    asm.ReportInvalidLoadOp(op, op.Operand.Register, op.Operand2.Register);
                    return;
                }

                var spCode = 0xF9;
                if (op.Operand2.Register == "IX")
                {
                    spCode = 0xDDF9;
                }
                else if (op.Operand2.Register == "IY")
                {
                    spCode = 0xFDF9;
                }
                else if (op.Operand2.Register != "HL")
                {
                    asm.ReportInvalidLoadOp(op, op.Operand.Register, op.Operand2.Register);
                    return;
                }
                asm.EmitDoubleByte(spCode);
                return;
            }

            // --- Destination is a 16-bit index register
            if (op.Operand.Type == OperandType.Reg16Idx)
            {
                var sourceReg = op.Operand.Register;
                if (op.Operand2.Type == OperandType.MemIndirect)
                {
                    // ld 'ix|iy',(expr)
                    asm.EmitDoubleByte(sourceReg == "IX" ? 0xDD2A : 0xFD2A);
                    asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit16);
                    return;
                }

                if (op.Operand2.Type == OperandType.Expr)
                {
                    // ld 'ix|iy',expr
                    asm.EmitDoubleByte(op.Operand.Register == "IX" ? 0xDD21 : 0xFD21);
                    asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit16);
                    return;
                }
                return;
            }

            // --- Destination is an indexed memory address
            if (op.Operand.Type == OperandType.IndexedAddress)
            {

                if (op.Operand2.Type == OperandType.Reg8)
                {
                    // --- ld '(idxreg+disp)','8bitReg'
                    var opCode = (byte)(0x70 + s_Reg8Order.IndexOf(op.Operand2.Register));
                    asm.EmitIndexedOperation(op, op.Operand, opCode);
                    return;
                }

                if (op.Operand2.Type == OperandType.Expr)
                {
                    // --- ld '(idxreg+disp)','expr'
                    asm.EmitIndexedOperation(op, op.Operand, 0x36);
                    asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit8);
                }
            }
        }

        /// <summary>
        /// BIT, SET, RES operations
        /// </summary>
        private static void ProcessBit(Z80Assembler asm, CompoundOperation op)
        {
            byte opByte;
            switch (op.Mnemonic)
            {
                case "BIT":
                    opByte = 0x40;
                    break;
                case "RES":
                    opByte = 0x80;
                    break;
                default:
                    opByte = 0xC0;
                    break;
            }

            // --- Check the bit index
            var bitIndex = asm.EvalImmediate(op, op.Operand.Expression);
            if (!bitIndex.IsValid)
            {
                return;
            }
            if (bitIndex.AsLong() < 0 || bitIndex.AsLong() > 7)
            {
                asm.ReportError(Errors.Z0002, op, bitIndex);
                return;
            }

            if (op.Operand2.Type == OperandType.IndexedAddress)
            {
                if (op.Operand3 == null)
                {
                    opByte |= 0x06;
                }
                else if (op.Operand3.Type == OperandType.Reg8)
                {
                    opByte |= (byte)s_Reg8Order.IndexOf(op.Operand3.Register);
                }
                else
                {
                    asm.ReportError(Errors.Z0001, op, op.Mnemonic);
                }
                asm.EmitIndexedBitOperation(op, op.Operand2.Register, op.Operand2.Sign, op.Operand2.Expression, 
                    (byte)(opByte + (bitIndex.Value << 3)));
                return;
            }

            if (op.Operand2.Type == OperandType.Reg8)
            {
                opByte |= (byte)s_Reg8Order.IndexOf(op.Operand2.Register);
            }
            else if (op.Operand2.Type == OperandType.RegIndirect)
            {
                if (op.Operand2.Register != "(HL)")
                {
                    asm.ReportError(Errors.Z0004, op, op.Mnemonic, op.Operand2.Register);
                    return;
                }
                opByte |= 0x06;
            }
            asm.EmitBytes(0xCB, (byte)(opByte + (bitIndex.Value << 3)));
        }

        /// <summary>
        /// Shift and rotate operations
        /// </summary>
        private static void ProcessShiftRotate(Z80Assembler asm, CompoundOperation op)
        {
            var sOpByte = (byte)(8 * s_ShiftOpOrder.IndexOf(op.Mnemonic));
            if (op.Operand.Type == OperandType.IndexedAddress)
            {
                if (op.Operand2 == null)
                {
                    sOpByte |= 0x06;
                }
                else if (op.Operand2.Type == OperandType.Reg8)
                {
                    sOpByte |= (byte)s_Reg8Order.IndexOf(op.Operand2.Register);
                }
                asm.EmitIndexedBitOperation(op, op.Operand.Register, op.Operand.Sign, op.Operand.Expression, sOpByte);
                return;
            }

            if (op.Operand.Type == OperandType.Reg8)
            {
                sOpByte |= (byte) s_Reg8Order.IndexOf(op.Operand.Register);
            }
            else if (op.Operand.Type == OperandType.RegIndirect)
            {
                if (op.Operand.Register != "(HL)")
                {
                    asm.ReportError(Errors.Z0004, op, op.Mnemonic, op.Operand.Register);
                    return;
                }
                sOpByte |= 0x06;
            }
            asm.EmitBytes(0xCB, sOpByte);
        }

        /// <summary>
        /// OUT operations
        /// </summary>
        private static void ProcessOut(Z80Assembler asm, CompoundOperation op)
        {
            if (op.Operand.Type == OperandType.MemIndirect)
            {
                if (op.Operand2.Register != "A")
                {
                    asm.ReportError(Errors.Z0005, op);
                    return;
                }

                asm.EmitByte(0xD3);
                asm.EmitumNumericExpression(op, op.Operand.Expression, FixupType.Bit8);
                return;
            }

            if (op.Operand.Type == OperandType.CPort)
            {
                if (op.Operand2.Type == OperandType.Reg8)
                {
                    asm.EmitOperationWithLookup(s_OutOpBytes, op.Operand2.Register, op);
                    return;
                }

                if (op.Operand2.Type == OperandType.Expr)
                {
                    var value = asm.EvalImmediate(op, op.Operand2.Expression);
                    if (!value.IsValid || value.Value != 0)
                    {
                        asm.ReportError(Errors.Z0006, op);
                        return;
                    }

                    // --- out (c),0
                    asm.EmitDoubleByte(0xED71);
                }
            }
        }

        /// <summary>
        /// IN operations
        /// </summary>
        private static void ProcessIn(Z80Assembler asm, CompoundOperation op)
        {
            if (op.Operand.Type == OperandType.Reg8)
            {
                if (op.Operand2.Type == OperandType.MemIndirect)
                {
                    if (op.Operand.Register != "A")
                    {
                        asm.ReportError(Errors.Z0005, op);
                        return;
                    }

                    // --- in a,(port)
                    asm.EmitByte(0xDB);
                    asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit8);
                    return;
                }
            }

            if (op.Operand.Type == OperandType.CPort)
            {
                // --- in (c)
                asm.EmitDoubleByte(0xED70);
                return;
            }

            // --- in reg,(c)
            asm.EmitOperationWithLookup(s_InOpBytes, op.Operand.Register, op);
        }

        /// <summary>
        /// ALU operations: SUB, AND, XOR, OR, CP
        /// </summary>
        private static void ProcessAlu2(Z80Assembler asm, CompoundOperation op)
        {
            var operand = op.Operand;
            var opType = op.Operand.Type;
            var opReg = op.Operand.Register;

            // --- Check for alternative syntax (A register as the first operand)
            if (op.Operand2 != null)
            {
                if (opType != OperandType.Reg8 || opReg != "A")
                {
                    asm.ReportError(Errors.Z0023, op, op.Mnemonic);
                    return;
                }
                operand = op.Operand2;
                opType = op.Operand2.Type;
                opReg = op.Operand2.Register;
            }

            var aluIdx = (byte)s_AluOpOrder.IndexOf(op.Mnemonic);
            if (opType == OperandType.Reg8)
            {
                var regIdx = s_Reg8Order.IndexOf(opReg);
                asm.EmitByte((byte)(0x80 + (aluIdx << 3) + regIdx));
                return;
            }

            if (opType == OperandType.RegIndirect)
            {
                if (opReg != "(HL)")
                {
                    asm.ReportError(Errors.Z0004, op, op.Mnemonic, opReg);
                    return;
                }
                asm.EmitByte((byte)(0x86 + (aluIdx << 3)));
                return;
            }

            if (opType == OperandType.Reg8Idx)
            {
                asm.EmitByte((byte)(opReg.Contains("X") ? 0xDD : 0xFD));
                asm.EmitByte((byte)(0x80 + (aluIdx << 3) + (opReg.EndsWith("H") ? 4 : 5)));
                return;
            }

            if (opType == OperandType.Expr)
            {
                asm.EmitByte((byte)(0xC6 + (aluIdx << 3)));
                asm.EmitumNumericExpression(op, operand.Expression, FixupType.Bit8);
                return;
            }

            if (opType == OperandType.IndexedAddress)
            {
                var opByte = (byte)(0x86 + (aluIdx << 3));
                asm.EmitIndexedOperation(op, operand, opByte);
            }
        }

        /// <summary>
        /// ALU operations: ADD, ADC, SBC
        /// </summary>
        private static void ProcessAlu1(Z80Assembler asm, CompoundOperation op)
        {
            var aluIdx = (byte)s_AluOpOrder.IndexOf(op.Mnemonic);
            if (op.Operand.Type == OperandType.Reg8)
            {
                if (op.Operand.Register != "A")
                {
                    asm.ReportError(Errors.Z0007, op, op.Mnemonic);
                    return;
                }

                if (op.Operand2.Type == OperandType.Reg8)
                {
                    var regIdx = s_Reg8Order.IndexOf(op.Operand2.Register);
                    asm.EmitByte((byte) (0x80 + (aluIdx << 3) + regIdx));
                    return;
                }

                if (op.Operand2.Type == OperandType.RegIndirect)
                {
                    if (op.Operand2.Register != "(HL)")
                    {
                        asm.ReportError(Errors.Z0008, op, op.Mnemonic, op.Operand2.Register);
                        return;
                    }
                    asm.EmitByte((byte)(0x86 + (aluIdx << 3)));
                    return;
                }

                if (op.Operand2.Type == OperandType.Reg8Idx)
                {
                    asm.EmitByte((byte)(op.Operand2.Register.Contains("X") ? 0xDD : 0xFD));
                    asm.EmitByte((byte)(0x80 + (aluIdx << 3) + (op.Operand2.Register.EndsWith("H") ? 4 : 5)));
                    return;
                }

                if (op.Operand2.Type == OperandType.Expr)
                {
                    asm.EmitByte((byte)(0xC6 + (aluIdx << 3)));
                    asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit8);
                    return;
                }

                if (op.Operand2.Type == OperandType.IndexedAddress)
                {
                    var opByte = (byte)(0x86 + (aluIdx << 3));
                    asm.EmitIndexedOperation(op, op.Operand2, opByte);
                    return;
                }
            }

            if (op.Operand.Type == OperandType.Reg16)
            {
                if (op.Operand2.Type == OperandType.Reg16)
                {
                    if (op.Operand.Register != "HL")
                    {
                        asm.ReportError(Errors.Z0009, op, op.Mnemonic, op.Operand.Register);
                        return;
                    }

                    // --- 16-bit register ALU operations
                    int opCodeBase;
                    switch (op.Mnemonic)
                    {
                        case "ADD":
                            opCodeBase = 0x09;
                            break;
                        case "ADC":
                            opCodeBase = 0xED4A;
                            break;
                        default:
                            opCodeBase = 0xED42;
                            break;
                    }
                    asm.EmitDoubleByte(opCodeBase + (s_Reg16Order.IndexOf(op.Operand2.Register) << 4));
                    return;
                }

                // --- Spectrum Next extended opcodes
                if (op.Operand2.Type == OperandType.Reg8)
                {
                    if (asm.Output.ModelType != SpectrumModelType.Next)
                    {
                        asm.ReportError(Errors.Z0102, op);
                        return;
                    }

                    // --- ADD HL,A; ADD DE,A; ADD BC,A
                    if (op.Operand.Register == "SP")
                    {
                        asm.ReportError(Errors.Z0009, op, op.Mnemonic, op.Operand.Register);
                        return;
                    }
                    if (op.Operand2.Register != "A")
                    {
                        asm.ReportError(Errors.Z0010, op, op.Mnemonic, op.Operand.Register, op.Operand2.Register);
                        return;
                    }
                    int opCodeBase;
                    switch (op.Operand.Register)
                    {
                        case "HL":
                            opCodeBase = 0xED31;
                            break;
                        case "DE":
                            opCodeBase = 0xED32;
                            break;
                        default: // BC
                            opCodeBase = 0xED33;
                            break;
                    }
                    asm.EmitDoubleByte(opCodeBase);
                    return;
                }

                if (op.Operand2.Type == OperandType.Expr)
                {
                    if (asm.Output.ModelType != SpectrumModelType.Next)
                    {
                        asm.ReportError(Errors.Z0102, op);
                        return;
                    }

                    // --- ADD HL,NNNN; ADD DE,NNNN; ADD BC,NNNN
                    if (op.Operand.Register == "SP")
                    {
                        asm.ReportError(Errors.Z0009, op, op.Mnemonic, op.Operand.Register);
                        return;
                    }

                    int opCodeBase;
                    switch (op.Operand.Register)
                    {
                        case "HL":
                            opCodeBase = 0xED34;
                            break;
                        case "DE":
                            opCodeBase = 0xED35;
                            break;
                        default: // BC
                            opCodeBase = 0xED36;
                            break;
                    }
                    asm.EmitDoubleByte(opCodeBase);
                    asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit16);
                }
            }

            if (op.Operand.Type == OperandType.Reg16Idx)
            {
                if (op.Mnemonic != "ADD")
                {
                    asm.ReportError(Errors.Z0001, op, op.Mnemonic);
                    return;
                }

                var opCode = op.Operand.Register == "IX" ? 0xDD09 : 0xFD09;
                if (op.Operand2.Type == OperandType.Reg16)
                {
                    if (op.Operand2.Register == "HL")
                    {
                        asm.ReportError(Errors.Z0010, op, op.Mnemonic, 
                            op.Operand.Register, op.Operand2.Register);
                        return;
                    }
                    asm.EmitDoubleByte(opCode + (s_Reg16Order.IndexOf(op.Operand2.Register) << 4));
                    return;
                }

                if (op.Operand2.Type == OperandType.Reg16Idx)
                {
                    if (op.Operand.Register != op.Operand2.Register)
                    {
                        asm.ReportError(Errors.Z0010, op, op.Mnemonic,
                            op.Operand.Register, op.Operand2.Register);
                        return;
                    }
                    asm.EmitDoubleByte(opCode + 0x20);
                }
            }
        }

        /// <summary>
        /// INC/DEC operation
        /// </summary>
        private static void ProcessIncDec(Z80Assembler asm, CompoundOperation op)
        {
            if (op.Operand.Type == OperandType.RegIndirect && op.Operand.Register != "(HL)")
            {
                asm.ReportError(Errors.Z0011, op, op.Mnemonic, op.Operand.Register);
                return;
            }
            if (op.Operand.Type == OperandType.IndexedAddress)
            {
                var opByte = op.Mnemonic == "INC" ? (byte)0x34 : (byte)0x35;
                asm.EmitIndexedOperation(op, op.Operand, opByte);
            }
            else
            {
                asm.EmitOperationWithLookup(
                    op.Mnemonic == "INC" ? s_IncOpBytes : s_DecOpBytes,
                    op.Operand.Register, op);
            }
        }

        /// <summary>
        /// EX operation
        /// </summary>
        private static void ProcessEx(Z80Assembler asm, CompoundOperation op)
        {
            if (op.Operand.Register == "AF")
            {
                if (op.Operand2.Register != "AF'")
                {
                    asm.ReportError(Errors.Z0012, op);
                    return;
                }
                asm.EmitByte(0x08);

            }
            else if (op.Operand.Register == "DE")
            {
                if (op.Operand2.Register != "HL")
                {
                    asm.ReportError(Errors.Z0013, op);
                    return;
                }
                asm.EmitByte(0xEB);
            }
            else if (op.Operand.Register != "(SP)")
            {
                asm.ReportError(Errors.Z0014, op);
            }
            else
            {
                if (op.Operand2.Register == "HL")
                {
                    asm.EmitByte(0xE3);
                }
                else if (op.Operand2.Register == "IX")
                {
                    asm.EmitBytes(0xDD, 0xE3);
                }
                else if (op.Operand2.Register == "IY")
                {
                    asm.EmitBytes(0xFD, 0xE3); // ex (sp),iy
                }
                else
                {
                    asm.ReportError(Errors.Z0015, op);
                }
            }

        }

        /// <summary>
        /// RET operation
        /// </summary>
        private static void ProcessRet(Z80Assembler asm, CompoundOperation op)
        {
            if (op.Operand == null)
            {
                asm.EmitByte(0xC9);
                return;
            }

            if (op.Operand.Type == OperandType.Reg8)
            {
                if (op.Operand.Register == "C")
                {
                    asm.EmitByte(0xD8);
                    return;
                }
                asm.ReportError(Errors.Z0001, op, op.Mnemonic);
                return;
            }
            if (op.Operand.Type == OperandType.Condition)
            {
                var condIndex = s_ConditionOrder.IndexOf(op.Operand.Condition);
                    var opCode = 0xC0 + condIndex * 8;
                asm.EmitByte((byte)opCode);
            }
            else
            {
                asm.ReportError(Errors.Z0001, op, op.Mnemonic);
            }
        }

        /// <summary>
        /// CALL operation
        /// </summary>
        private static void ProcessCall(Z80Assembler asm, CompoundOperation op)
        {
            if (op.Operand.Type == OperandType.Reg8)
            {
                if (op.Operand.Register == "C")
                {
                    asm.EmitByte(0xDC);
                    asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit16);
                    return;
                }
                asm.ReportError(Errors.Z0001, op, op.Mnemonic);
                return;
            }

            if (op.Operand.Type == OperandType.Condition)
            {
                var condIndex = s_ConditionOrder.IndexOf(op.Operand.Condition);
                var opCode = 0xC4 + condIndex * 8;
                asm.EmitByte((byte) opCode);
                asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit16);
            }
            else
            {
                asm.EmitByte(0xCD);
                asm.EmitumNumericExpression(op, op.Operand.Expression, FixupType.Bit16);
            }
        }

        /// <summary>
        /// JP operation
        /// </summary>
        private static void ProcessJp(Z80Assembler asm, CompoundOperation op)
        {
            if (op.Operand.Type == OperandType.Reg8)
            {
                if (op.Operand.Register == "C")
                {
                    asm.EmitByte(0xDA);
                    asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit16);
                    return;
                }
                asm.ReportError(Errors.Z0001, op, op.Mnemonic);
                return;
            }

            if (op.Operand.Type == OperandType.Condition)
            {
                var condIndex = s_ConditionOrder.IndexOf(op.Operand.Condition);
                var opCode = 0xC2 + condIndex * 8;
                asm.EmitByte((byte)opCode);
                asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit16);
                return;
            }

            if (op.Operand.Type == OperandType.Expr)
            {
                // --- Jump to a direct address
                asm.EmitByte(0xC3);
                asm.EmitumNumericExpression(op, op.Operand.Expression, FixupType.Bit16);
                return;
            }

            if (op.Operand.Type == OperandType.RegIndirect && op.Operand.Register != "(HL)"
                || op.Operand.Type == OperandType.IndexedAddress && op.Operand.Sign != null)
            {
                asm.ReportError(Errors.Z0016, op);
                return;
            }

            // --- Jump to a register address
            if (op.Operand.Type == OperandType.Reg16)
            {
                if (op.Operand.Register != "HL")
                {
                    asm.ReportError(Errors.Z0016, op);
                    return;
                }
            }
            else if (op.Operand.Type == OperandType.IndexedAddress
                || op.Operand.Type == OperandType.Reg16Idx)
            {
                if (op.Operand.Register == "IX") asm.EmitByte(0xDD);
                else if (op.Operand.Register == "IY") asm.EmitByte(0xFD);
            }
            asm.EmitByte(0xE9);
        }

        /// <summary>
        /// JR operation
        /// </summary>
        private static void ProcessJr(Z80Assembler asm, CompoundOperation op)
        {
            if (op.Operand.Type == OperandType.Reg8)
            {
                if (op.Operand.Register == "C")
                {
                    asm.EmitJumpRelativeOp(op, op.Operand2.Expression, 0x38);
                    return;
                }
                asm.ReportError(Errors.Z0001, op, op.Mnemonic);
                return;
            }

            if (op.Operand.Type == OperandType.Condition)
            {
                var cond = op.Operand.Condition;
                if (cond == "PO" || cond == "PE" || cond == "P" || cond == "M")
                {
                    asm.ReportError(Errors.Z0095, op, cond);
                    return;
                }
                var condIndex = s_ConditionOrder.IndexOf(cond);
                var opCode = 0x20 + condIndex * 8;
                asm.EmitJumpRelativeOp(op, op.Operand2.Expression, opCode);
                return;
            }

            if (op.Operand.Type != OperandType.Expr) return;

            // --- Jump to a direct address
            asm.EmitJumpRelativeOp(op, op.Operand.Expression, 0x18);
        }

        /// <summary>
        /// DJNZ operation
        /// </summary>
        private static void ProcessDjnz(Z80Assembler asm, CompoundOperation op)
        {
            asm.EmitJumpRelativeOp(op, op.Operand.Expression, 0x10);
        }

        /// <summary>
        /// RST operation
        /// </summary>
        private static void ProcessRst(Z80Assembler asm, CompoundOperation op)
        {
            var value = asm.EvalImmediate(op, op.Operand.Expression);
            if (!value.IsValid) return;
            if (value.Value > 0x38 || value.Value % 8 != 0)
            {
                asm.ReportError(Errors.Z0018, op, $"{value:X}");
                return;
            }
            asm.EmitByte((byte)(0xC7 + value.Value));
        }

        /// <summary>
        /// Process PUSH and POP operations
        /// </summary>
        private static void ProcessStackOp(Z80Assembler asm, CompoundOperation op)
        {
            if (op.Operand.Type == OperandType.Expr)
            {
                // --- PUSH NNNN Spectrum Next operation
                if (op.Mnemonic == "POP")
                {
                    asm.ReportError(Errors.Z0024, op);
                    return;
                }
                if (asm.Output.ModelType != SpectrumModelType.Next)
                {
                    asm.ReportError(Errors.Z0102, op);
                    return;
                }
                asm.EmitDoubleByte(0xED8A);
                asm.EmitumNumericExpression(op, op.Operand.Expression, FixupType.Bit16);
                return;
            }

            if (op.Operand.Register == "AF'")
            {
                asm.ReportError(Errors.Z0019, op, op.Mnemonic);
                return;
            }
            asm.EmitOperationWithLookup(
                op.Mnemonic == "PUSH" ? s_PushOpBytes : s_PopOpBytes,
                op.Operand.Register, op);
        }

        /// <summary>
        /// Process the IM operation
        /// </summary>
        private static void ProcessImOp(Z80Assembler asm, CompoundOperation op)
        {
            var mode = asm.EvalImmediate(op, op.Operand.Expression);
            if (!mode.IsValid) return;

            if (mode.AsLong() < 0 || mode.AsLong() > 2)
            {
                asm.ReportError(Errors.Z0020, op, mode);
                return;
            }

            var opCodes = new[] { 0xED46, 0xED56, 0xED5E };
            asm.EmitDoubleByte(opCodes[mode.Value]);
        }

        /// <summary>
        /// Process the MIRROR operation
        /// </summary>
        private static void ProcessMirrorOp(Z80Assembler asm, CompoundOperation op)
        {
            if (asm.Output.ModelType != SpectrumModelType.Next)
            {
                asm.ReportError(Errors.Z0102, op);
                return;
            }
            if (op.Operand.Register != "A" && op.Operand.Register != "DE")
            {
                asm.ReportError(Errors.Z0009, op, op.Mnemonic, op.Operand.Register);
            }
            var opCode = op.Operand.Register == "A"
                ? 0xED24
                : 0xED26;
            asm.EmitDoubleByte(opCode);
        }

        /// <summary>
        /// Process the NEXTREG operation
        /// </summary>
        private static void ProcessNextRegOp(Z80Assembler asm, CompoundOperation op)
        {
            if (asm.Output.ModelType != SpectrumModelType.Next)
            {
                asm.ReportError(Errors.Z0102, op);
                return;
            }

            if (op.Operand2.Type == OperandType.Reg8)
            {
                if (op.Operand2.Register != "A")
                {
                    asm.ReportError(Errors.Z0010, op, op.Mnemonic, "<expr>", op.Operand2.Register);
                    return;
                }

                asm.EmitDoubleByte(0xED92);
                asm.EmitumNumericExpression(op, op.Operand.Expression, FixupType.Bit8);
                return;
            }

            asm.EmitDoubleByte(0xED91);
            asm.EmitumNumericExpression(op, op.Operand.Expression, FixupType.Bit8);
            asm.EmitumNumericExpression(op, op.Operand2.Expression, FixupType.Bit8);
        }

        /// <summary>
        /// Process the TEST operation
        /// </summary>
        private static void ProcessTestOp(Z80Assembler asm, CompoundOperation op)
        {
            if (asm.Output.ModelType != SpectrumModelType.Next)
            {
                asm.ReportError(Errors.Z0102, op);
                return;
            }

            asm.EmitDoubleByte(0xED27);
            asm.EmitumNumericExpression(op, op.Operand.Expression, FixupType.Bit8);
        }

        /// <summary>
        /// Reports that the specified source and destination means invalid LD operation
        /// </summary>
        /// <param name="opLine">Assembly line for the load operation</param>
        /// <param name="dest">Load destination</param>
        /// <param name="source">Load source</param>
        private void ReportInvalidLoadOp(SourceLineBase opLine, string dest, string source)
        {
            ReportError(Errors.Z0021, opLine, dest, source);
        }

        /// <summary>
        /// Emits a jump relative operation
        /// </summary>
        /// <param name="opLine">Control flow operation line</param>
        /// <param name="target">Target expression</param>
        /// <param name="opCode">Operation code</param>
        private void EmitJumpRelativeOp(SourceLineBase opLine, ExpressionNode target, int opCode)
        {
            var value = Eval(opLine, target);
            if (target.EvaluationError != null) return;
            var dist = 0;
            if (value.IsNonEvaluated)
            {
                RecordFixup(opLine, FixupType.Jr, target);
            }
            else
            {
                // --- Check for Relative address
                dist = (short)(ushort)(value.Value - (GetCurrentAssemblyAddress() + 2));
                if (dist < -128 || dist > 127)
                {
                    ReportError(Errors.Z0022, opLine, dist);
                    return;
                }
            }
            EmitBytes((byte)opCode, (byte)dist);
        }

        /// <summary>
        /// Emits an indexed operation with the specified operand and operation code
        /// </summary>
        /// <param name="opLine">Operation source line</param>
        /// <param name="operand">Operand with indexed address</param>
        /// <param name="opCode">Operation code</param>
        private void EmitIndexedOperation(SourceLineBase opLine, Operand operand, byte opCode)
        {
            byte idxByte, disp;
            var done = GetIndexBytes(opLine, operand, out idxByte, out disp);
            EmitBytes(idxByte, opCode);
            if (!done)
            {
                RecordFixup(opLine, FixupType.Bit8, operand.Expression);
            }
            EmitByte(disp);
        }

        /// <summary>
        /// Gets the index byte and displacement byte from an indexed address
        /// </summary>
        /// <param name="opLine">Control flow operation line</param>
        /// <param name="operand">Operand with indexed address type</param>
        /// <param name="idxByte">Index byte (0xDD for IX, 0xFD for IY)</param>
        /// <param name="disp">Displacement byte</param>
        /// <returns>
        /// True, if displacement has been resolved; 
        /// false if it can be resolved only during fixup phase
        /// </returns>
        private bool GetIndexBytes(SourceLineBase opLine, Operand operand, out byte idxByte, out byte disp)
        {
            idxByte = operand.Register == "IX" ? (byte)0xDD : (byte)0xFD;
            disp = 0x00;
            if (operand.Sign == null) return true;

            var dispValue = Eval(opLine, operand.Expression);
            if (!dispValue.IsValid) return false;
            disp = operand.Sign == "-" 
                ? (byte) -dispValue.Value 
                : dispValue.AsByte();
            return true;
        }

        /// <summary>
        /// Emits an indexed operation with the specified operand and operation code
        /// </summary>
        /// <param name="opLine">Operation source line</param>
        /// <param name="register">Index register</param>
        /// <param name="sign">Displacement sign</param>
        /// <param name="expr">Displacement expression</param>
        /// <param name="opCode">Operation code</param>
        private void EmitIndexedBitOperation(SourceLineBase opLine, string register, string sign, ExpressionNode expr, byte opCode)
        {
            byte idxByte, disp;
            var done = GetIndexBytes(opLine, register, sign, expr, out idxByte, out disp);
            EmitBytes(idxByte, 0xCB);
            if (!done)
            {
                RecordFixup(opLine, FixupType.Bit8, expr);
            }
            EmitByte(disp);
            EmitByte(opCode);
        }

        /// <summary>
        /// Gets the index byte and displacement byte from an indexxed address
        /// </summary>
        /// <param name="opLine">Control flow operation line</param>
        /// <param name="register">Index register</param>
        /// <param name="sign">Displacement sign</param>
        /// <param name="expr">Displacement expression</param>
        /// <param name="idxByte">Index byte (0xDD for IX, 0xFD for IY)</param>
        /// <param name="disp">Displacement byte</param>
        /// <returns>
        /// True, if displacement has been resolved; 
        /// false if it can be resolved only during fixup phase
        /// </returns>
        private bool GetIndexBytes(SourceLineBase opLine, string register, string sign, ExpressionNode expr, out byte idxByte, out byte disp)
        {
            idxByte = register == "IX" ? (byte)0xDD : (byte)0xFD;
            disp = 0x00;
            if (sign == null) return true;

            var dispValue = Eval(opLine, expr);
            if (!dispValue.IsValid) return false;
            disp = sign == "-"
                ? (byte)-dispValue.Value
                : dispValue.AsByte();
            return true;
        }

        /// <summary>
        /// Evaluates the expression and emits bytes accordingly. If the expression
        /// cannot be resolved, creates a fixup.
        /// </summary>
        /// <param name="opLine">Assembly line</param>
        /// <param name="expr">Expression to evaluate</param>
        /// <param name="type">Expression/Fixup type</param>
        /// <returns></returns>
        private void EmitumNumericExpression(SourceLineBase opLine, ExpressionNode expr, FixupType type)
        {
            var value = Eval(opLine, expr);
            if (value.IsNonEvaluated)
            {
                RecordFixup(opLine, type, expr);
            }
            if (value.IsValid && value.Type == ExpressionValueType.String)
            {
                ReportError(Errors.Z0305, opLine);
            }
            var fixupValue = value.Value;
            EmitByte((byte)fixupValue);
            if (type == FixupType.Bit16)
            {
                EmitByte((byte)(fixupValue >> 8));
            }
        }

        #endregion

        #region Emit helper methods

        /// <summary>
        /// Emits a new byte to the current code segment
        /// </summary>
        /// <param name="data">Data byte to emit</param>
        /// <returns>Current code offset</returns>
        public void EmitByte(byte data)
        {
            EnsureCodeSegment();
            var overflow = CurrentSegment.EmitByte(data);
            if (overflow != null)
            {
                ReportError(overflow, CurrentSourceLine);
            }
        }

        /// <summary>
        /// Emits a new word to the current code segment
        /// </summary>
        /// <param name="data">Data byte to emit</param>
        /// <returns>Current code offset</returns>
        public void EmitWord(ushort data)
        {
            EmitByte((byte)data);
            EmitByte((byte)(data >> 8));
        }

        /// <summary>
        /// Emits an operation using a lookup table
        /// </summary>
        /// <param name="table">Lookup table</param>
        /// <param name="key">Operation key</param>
        /// <param name="operation">Assembly line that represents the operation</param>
        private void EmitOperationWithLookup(IReadOnlyDictionary<string, int> table, string key,
            OperationBase operation)
        {
            if (table.TryGetValue(key, out var code))
            {
                EmitDoubleByte(code);
                return;
            }
            ReportError(Errors.Z0085, operation, key, operation.Mnemonic);
        }

        /// <summary>
        /// Ensures that there's a code segment by the time the code is emitted
        /// </summary>
        private void EnsureCodeSegment(ushort? defaultAddress = null, ushort maxLength = 0xffff )
        {
            if (CurrentSegment == null)
            {
                CurrentSegment = new BinarySegment
                {
                    StartAddress = defaultAddress ?? (_options?.DefaultStartAddress ?? 0x8000),
                    CurrentInstructionOffset = 0,
                    MaxCodeLength = maxLength
                };
                Output.Segments.Add(CurrentSegment);
            }
        }

        /// <summary>
        /// Emits a double byte passed as an integer
        /// </summary>
        private void EmitDoubleByte(int doubleByte)
        {
            var low = (byte) (doubleByte & 0xFF);
            var high = (byte) ((doubleByte >> 8) & 0xFF);
            if (high != 0)
            {
                EmitByte(high);
            }
            EmitByte(low);
        }

        /// <summary>
        /// Emits a series of bytes
        /// </summary>
        private void EmitBytes(params byte[] bytes)
        {
            foreach (var data in bytes) EmitByte(data);
        }

        /// <summary>
        /// Converts a ZX Spectrum string into a byte lisy
        /// </summary>
        /// <param name="input">Input string</param>
        /// <returns>Bytes representing the string</returns>
        public static List<byte> SpectrumStringToBytes(string input)
        {
            var bytes = new List<byte>(input.Length);
            var state = StrParseState.Normal;
            var collect = 0;
            foreach (var ch in input)
            {
                switch (state)
                {
                    case StrParseState.Normal:
                        if (ch == '\\')
                        {
                            state = StrParseState.Backslash;
                        }
                        else
                        {
                            bytes.Add((byte)ch);
                        }
                        break;

                    case StrParseState.Backslash:
                        state = StrParseState.Normal;
                        switch (ch)
                        {
                            case 'i': // INK
                                bytes.Add(0x10);
                                break;
                            case 'p': // PAPER
                                bytes.Add(0x11);
                                break;
                            case 'f': // FLASH
                                bytes.Add(0x12);
                                break;
                            case 'b': // BRIGHT
                                bytes.Add(0x13);
                                break;
                            case 'I': // INVERSE
                                bytes.Add(0x14);
                                break;
                            case 'o': // OVER
                                bytes.Add(0x15);
                                break;
                            case 'a': // AT
                                bytes.Add(0x16);
                                break;
                            case 't': // TAB
                                bytes.Add(0x17);
                                break;
                            case 'P': // Pound sign
                                bytes.Add(0x60);
                                break;
                            case 'C': // Copyright sign
                                bytes.Add(0x7F);
                                break;
                            case '"':
                                bytes.Add((byte)'"');
                                break;
                            case '\'':
                                bytes.Add((byte)'\'');
                                break;
                            case '\\':
                                bytes.Add((byte)'\\');
                                break;
                            case '0':
                                bytes.Add(0);
                                break;
                            case 'x':
                                state = StrParseState.X;
                                break;
                            default:
                                bytes.Add((byte)ch);
                                break;
                        }
                        break;

                    case StrParseState.X:
                        if (ch >= '0' && ch <= '9'
                            || ch >= 'a' && ch <= 'f'
                            || ch >= 'A' && ch <= 'F')
                        {
                            collect = int.Parse(new string(ch, 1), NumberStyles.HexNumber);
                            state = StrParseState.Xh;
                        }
                        else
                        {
                            bytes.Add((byte)'x');
                            state = StrParseState.Normal;
                        }
                        break;

                    case StrParseState.Xh:
                        if (ch >= '0' && ch <= '9'
                            || ch >= 'a' && ch <= 'f'
                            || ch >= 'A' && ch <= 'F')
                        {
                            collect = collect * 0x10 + int.Parse(new string(ch, 1), NumberStyles.HexNumber);
                            bytes.Add((byte)collect);
                            state = StrParseState.Normal;
                        }
                        else
                        {
                            bytes.Add((byte)collect);
                            bytes.Add((byte)ch);
                            state = StrParseState.Normal;
                        }
                        break;
                }
            }

            // --- Handle the final machine state
            switch (state)
            {
                case StrParseState.Backslash:
                    bytes.Add((byte)'\\');
                    break;
                case StrParseState.X:
                    bytes.Add((byte)'x');
                    break;
                case StrParseState.Xh:
                    bytes.Add((byte)collect);
                    break;
            }
            return bytes;
        }

        /// <summary>
        /// We use this enumeration to represent the state
        /// of the machine parsing Spectrum string
        /// </summary>
        private enum StrParseState
        {
            Normal,
            Backslash,
            X,
            Xh
        }

        #endregion

        #region Operation rules

        /// <summary>
        /// Represents the rules for the LD operations
        /// </summary>
        private static readonly List<OperandRule> s_LoadRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Reg8, OperandType.Reg8),
                new OperandRule(OperandType.Reg8, OperandType.RegIndirect),
                new OperandRule(OperandType.Reg8, OperandType.Reg8Spec),
                new OperandRule(OperandType.Reg8, OperandType.Reg8Idx),
                new OperandRule(OperandType.Reg8, OperandType.Expr),
                new OperandRule(OperandType.Reg8, OperandType.MemIndirect),
                new OperandRule(OperandType.Reg8, OperandType.IndexedAddress),
                new OperandRule(OperandType.Reg8Idx, OperandType.Reg8),
                new OperandRule(OperandType.Reg8Idx, OperandType.Reg8Idx),
                new OperandRule(OperandType.Reg8Idx, OperandType.Expr),
                new OperandRule(OperandType.Reg8Spec, OperandType.Reg8),
                new OperandRule(OperandType.RegIndirect, OperandType.Reg8),
                new OperandRule(OperandType.RegIndirect, OperandType.Expr),
                new OperandRule(OperandType.MemIndirect, OperandType.Reg8),
                new OperandRule(OperandType.MemIndirect, OperandType.Reg16),
                new OperandRule(OperandType.MemIndirect, OperandType.Reg16Idx),
                new OperandRule(OperandType.Reg16, OperandType.Expr),
                new OperandRule(OperandType.Reg16, OperandType.MemIndirect),
                new OperandRule(OperandType.Reg16, OperandType.Reg16),
                new OperandRule(OperandType.Reg16, OperandType.Reg16Idx),
                new OperandRule(OperandType.Reg16Idx, OperandType.Expr),
                new OperandRule(OperandType.Reg16Idx, OperandType.MemIndirect),
                new OperandRule(OperandType.IndexedAddress, OperandType.Reg8),
                new OperandRule(OperandType.IndexedAddress, OperandType.Expr)
            };

        /// <summary>
        /// Represents a single expression rule
        /// </summary>
        private static readonly List<OperandRule> s_SingleExprRule =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Expr)
            };

        /// <summary>
        /// Represents a single expression rule
        /// </summary>
        private static readonly List<OperandRule> s_JumpRule =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Reg8, OperandType.Expr),
                new OperandRule(OperandType.Condition, OperandType.Expr),
                new OperandRule(OperandType.Expr)
            };

        /// <summary>
        /// Stack operation rule set
        /// </summary>
        private static readonly List<OperandRule> s_StackOpRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Reg16),
                new OperandRule(OperandType.Reg16Idx),
                new OperandRule(OperandType.Reg16Spec),
                new OperandRule(OperandType.Expr),
            };

        /// <summary>
        /// Represents a rule set for increment and decrement operations
        /// </summary>
        private static readonly List<OperandRule> s_IncDecOpRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Reg8),
                new OperandRule(OperandType.Reg8Idx),
                new OperandRule(OperandType.Reg16),
                new OperandRule(OperandType.Reg16Idx),
                new OperandRule(OperandType.RegIndirect),
                new OperandRule(OperandType.IndexedAddress)
            };

        /// <summary>
        /// Alu operation rule set (ADD, ADC, SBC)
        /// </summary>
        private static readonly List<OperandRule> s_RsDoubleArgAluRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Reg8, OperandType.Reg8),
                new OperandRule(OperandType.Reg8, OperandType.Reg8Idx),
                new OperandRule(OperandType.Reg8, OperandType.RegIndirect),
                new OperandRule(OperandType.Reg8, OperandType.IndexedAddress),
                new OperandRule(OperandType.Reg8, OperandType.Expr),
                new OperandRule(OperandType.Reg16, OperandType.Reg16),
                new OperandRule(OperandType.Reg16Idx, OperandType.Reg16),
                new OperandRule(OperandType.Reg16Idx, OperandType.Reg16Idx),
            };

        /// <summary>
        /// ADD operation rule set (created because of Next opcodes)
        /// </summary>
        private static readonly List<OperandRule> s_ExtAddRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Reg8, OperandType.Reg8),
                new OperandRule(OperandType.Reg8, OperandType.Reg8Idx),
                new OperandRule(OperandType.Reg8, OperandType.RegIndirect),
                new OperandRule(OperandType.Reg8, OperandType.IndexedAddress),
                new OperandRule(OperandType.Reg8, OperandType.Expr),
                new OperandRule(OperandType.Reg16, OperandType.Reg16),
                new OperandRule(OperandType.Reg16, OperandType.Reg8),
                new OperandRule(OperandType.Reg16, OperandType.Expr),
                new OperandRule(OperandType.Reg16Idx, OperandType.Reg16),
                new OperandRule(OperandType.Reg16Idx, OperandType.Reg16Idx),
            };

        /// <summary>
        /// Alu operation rule set (SUB, AND, XOR, OR, CP)
        /// </summary>
        private static readonly List<OperandRule> s_SingleArgAluRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Reg8),
                new OperandRule(OperandType.Reg8Idx),
                new OperandRule(OperandType.RegIndirect),
                new OperandRule(OperandType.IndexedAddress),
                new OperandRule(OperandType.Expr),
                new OperandRule(OperandType.Reg8, OperandType.Reg8),
                new OperandRule(OperandType.Reg8, OperandType.Reg8Idx),
                new OperandRule(OperandType.Reg8, OperandType.RegIndirect),
                new OperandRule(OperandType.Reg8, OperandType.IndexedAddress),
                new OperandRule(OperandType.Reg8, OperandType.Expr),
            };

        /// <summary>
        /// Shift and rotate operations rule set
        /// </summary>
        private static readonly List<OperandRule> s_ShiftRotateRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Reg8),
                new OperandRule(OperandType.RegIndirect),
                new OperandRule(OperandType.IndexedAddress),
                new OperandRule(OperandType.IndexedAddress, OperandType.Reg8)
            };

        /// <summary>
        /// BIT, SET, RES rules
        /// </summary>
        private static readonly List<OperandRule> s_BitManipRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Expr, OperandType.Reg8),
                new OperandRule(OperandType.Expr, OperandType.RegIndirect),
                new OperandRule(OperandType.Expr, OperandType.IndexedAddress),
            };

        /// <summary>
        /// JP operation rule set
        /// </summary>
        private static readonly List<OperandRule> s_JpOpRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Reg8, OperandType.Expr),
                new OperandRule(OperandType.Condition, OperandType.Expr),
                new OperandRule(OperandType.Expr),
                new OperandRule(OperandType.Reg16),
                new OperandRule(OperandType.Reg16Idx),
                new OperandRule(OperandType.RegIndirect),
                new OperandRule(OperandType.IndexedAddress),
            };

        /// <summary>
        /// RET operation rule set
        /// </summary>
        private static readonly List<OperandRule> s_RetOpRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Reg8),
                new OperandRule(OperandType.Condition),
                new OperandRule(OperandType.None)
            };

        /// <summary>
        /// EX operation rule set
        /// </summary>
        private static readonly List<OperandRule> s_ExOpRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Reg16Spec, OperandType.Reg16Spec),
                new OperandRule(OperandType.Reg16, OperandType.Reg16),
                new OperandRule(OperandType.RegIndirect, OperandType.Reg16),
                new OperandRule(OperandType.RegIndirect, OperandType.Reg16Idx)
            };

        /// <summary>
        /// IN operation rule set
        /// </summary>
        private static readonly List<OperandRule> s_InOpRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Reg8, OperandType.MemIndirect),
                new OperandRule(OperandType.Reg8, OperandType.CPort),
                new OperandRule(OperandType.CPort)
            };

        /// <summary>
        /// OUT operation rule set
        /// </summary>
        private static readonly List<OperandRule> s_OutOpRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.MemIndirect, OperandType.Reg8),
                new OperandRule(OperandType.CPort, OperandType.Reg8),
                new OperandRule(OperandType.CPort, OperandType.Expr)
            };

        /// <summary>
        /// MIRROR operation rule set
        /// </summary>
        private static readonly List<OperandRule> s_MirrorOpRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Reg8),
                new OperandRule(OperandType.Reg16)
            };

        /// <summary>
        /// NEXTREG operation rule set
        /// </summary>
        private static readonly List<OperandRule> s_NextRegOpRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Expr, OperandType.Expr),
                new OperandRule(OperandType.Expr, OperandType.Reg8)
            };

        /// <summary>
        /// TEST operation rule set
        /// </summary>
        private static readonly List<OperandRule> s_TestOpRules =
            new List<OperandRule>
            {
                new OperandRule(OperandType.Expr)
            };

        /// <summary>
        /// The table that contains the first level processing rules
        /// </summary>
        private readonly Dictionary<string, CompoundOperationDescriptor> _compoundOpTable =
            new Dictionary<string, CompoundOperationDescriptor>(StringComparer.OrdinalIgnoreCase)
            {
                { "ADC", new CompoundOperationDescriptor(s_RsDoubleArgAluRules, ProcessAlu1) },
                { "ADD", new CompoundOperationDescriptor(s_ExtAddRules, ProcessAlu1) },
                { "AND", new CompoundOperationDescriptor(s_SingleArgAluRules, ProcessAlu2) },
                { "BIT", new CompoundOperationDescriptor(s_BitManipRules, ProcessBit) },
                { "CALL", new CompoundOperationDescriptor(s_JumpRule, ProcessCall) },
                { "CP", new CompoundOperationDescriptor(s_SingleArgAluRules, ProcessAlu2) },
                { "DEC", new CompoundOperationDescriptor(s_IncDecOpRules, ProcessIncDec) },
                { "DJNZ", new CompoundOperationDescriptor(s_SingleExprRule, ProcessDjnz) },
                { "EX", new CompoundOperationDescriptor(s_ExOpRules, ProcessEx) },
                { "IM", new CompoundOperationDescriptor(s_SingleExprRule, ProcessImOp) },
                { "IN", new CompoundOperationDescriptor(s_InOpRules, ProcessIn) },
                { "INC", new CompoundOperationDescriptor(s_IncDecOpRules, ProcessIncDec) },
                { "JP", new CompoundOperationDescriptor(s_JpOpRules, ProcessJp) },
                { "JR", new CompoundOperationDescriptor(s_JumpRule, ProcessJr) },
                { "LD", new CompoundOperationDescriptor(s_LoadRules, ProcessLd) },
                { "MIRROR", new CompoundOperationDescriptor(s_MirrorOpRules, ProcessMirrorOp) },
                { "NEXTREG", new CompoundOperationDescriptor(s_NextRegOpRules, ProcessNextRegOp) },
                { "OR", new CompoundOperationDescriptor(s_SingleArgAluRules, ProcessAlu2) },
                { "OUT", new CompoundOperationDescriptor(s_OutOpRules, ProcessOut) },
                { "POP", new CompoundOperationDescriptor(s_StackOpRules, ProcessStackOp) },
                { "PUSH", new CompoundOperationDescriptor(s_StackOpRules, ProcessStackOp) },
                { "RES", new CompoundOperationDescriptor(s_BitManipRules, ProcessBit) },
                { "RET", new CompoundOperationDescriptor(s_RetOpRules, ProcessRet) },
                { "RL", new CompoundOperationDescriptor(s_ShiftRotateRules, ProcessShiftRotate) },
                { "RLC", new CompoundOperationDescriptor(s_ShiftRotateRules, ProcessShiftRotate) },
                { "RR", new CompoundOperationDescriptor(s_ShiftRotateRules, ProcessShiftRotate) },
                { "RRC", new CompoundOperationDescriptor(s_ShiftRotateRules, ProcessShiftRotate) },
                { "RST", new CompoundOperationDescriptor(s_SingleExprRule, ProcessRst) },
                { "SBC", new CompoundOperationDescriptor(s_RsDoubleArgAluRules, ProcessAlu1) },
                { "SET", new CompoundOperationDescriptor(s_BitManipRules, ProcessBit) },
                { "SLA", new CompoundOperationDescriptor(s_ShiftRotateRules, ProcessShiftRotate) },
                { "SLL", new CompoundOperationDescriptor(s_ShiftRotateRules, ProcessShiftRotate) },
                { "SRA", new CompoundOperationDescriptor(s_ShiftRotateRules, ProcessShiftRotate) },
                { "SRL", new CompoundOperationDescriptor(s_ShiftRotateRules, ProcessShiftRotate) },
                { "SUB", new CompoundOperationDescriptor(s_SingleArgAluRules, ProcessAlu2) },
                { "TEST", new CompoundOperationDescriptor(s_TestOpRules, ProcessTestOp) },
                { "XOR", new CompoundOperationDescriptor(s_SingleArgAluRules, ProcessAlu2) },
            };

        #endregion

        #region Operation lookup tables

        /// <summary>
        /// The order of Z80 shift and rotation operations
        /// </summary>
        private static readonly List<string> s_ShiftOpOrder = new List<string>
        {
            "RLC",
            "RRC",
            "RL",
            "RR",
            "SLA",
            "SRA",
            "SLL",
            "SRL"
        };

        /// <summary>
        /// The order of Z80 ALU operations
        /// </summary>
        private static readonly List<string> s_AluOpOrder = new List<string>
        {
            "ADD",
            "ADC",
            "SUB",
            "SBC",
            "AND",
            "XOR",
            "OR",
            "CP"
        };

        /// <summary>
        /// The index order of 8-bit registers in Z80 operations
        /// </summary>
        private static readonly List<string> s_Reg8Order = new List<string>
        {
            "B",
            "C",
            "D",
            "E",
            "H",
            "L",
            "(HL)",
            "A"
        };

        /// <summary>
        /// The index order of 16-bit registers in Z80 operations
        /// </summary>
        private static readonly List<string> s_Reg16Order = new List<string>
        {
            "BC",
            "DE",
            "HL",
            "SP"
        };

        /// <summary>
        /// The order of Z80 conditions operations
        /// </summary>
        private static readonly List<string> s_ConditionOrder = new List<string>
        {
            "NZ",
            "Z",
            "NC",
            "C",
            "PO",
            "PE",
            "P",
            "M"
        };

        /// <summary>
        /// Z80 binary operation codes for trivial operations
        /// </summary>
        private static readonly Dictionary<string, int> s_TrivialOpBytes =
            new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
            {
                {"NOP", 0x00},
                {"RLCA", 0x07},
                {"RRCA", 0x0F},
                {"RLA", 0x17},
                {"RRA", 0x1F},
                {"DAA", 0x27},
                {"CPL", 0x2F},
                {"SCF", 0x37},
                {"CCF", 0x3F},
                {"HALT", 0x76},
                {"EXX", 0xD9},
                {"DI", 0xF3},
                {"EI", 0xFB},
                {"NEG", 0xED44},
                {"RETN", 0xED45},
                {"RETI", 0xED4D},
                {"RRD", 0xED67},
                {"RLD", 0xED6F},
                {"LDI", 0xEDA0},
                {"CPI", 0xEDA1},
                {"INI", 0xEDA2},
                {"OUTI", 0xEDA3},
                {"LDD", 0xEDA8},
                {"CPD", 0xEDA9},
                {"IND", 0xEDAA},
                {"OUTD", 0xEDAB},
                {"LDIR", 0xEDB0},
                {"CPIR", 0xEDB1},
                {"INIR", 0xEDB2},
                {"OTIR", 0xEDB3},
                {"LDDR", 0xEDB8},
                {"CPDR", 0xEDB9},
                {"INDR", 0xEDBA},
                {"OTDR", 0xEDBB},
                {"SWAPNIB", 0xED23},
                {"MUL", 0xED30},
                {"OUTINB", 0xED90},
                {"LDIX", 0xEDA4},
                {"LDIRX", 0xEDB4},
                {"LDDX", 0xEDAC},
                {"LDDRX", 0xEDBC},
                {"PIXELDN", 0xED93},
                {"PIXELAD", 0xED94},
                {"SETAE", 0xED95},
                {"LDPIRX", 0xEDB7},
                {"LDIRSCALE", 0xEDB6},
            };

        /// <summary>
        /// Z80 PUSH operation binary codes
        /// </summary>
        private static readonly Dictionary<string, int> s_PushOpBytes =
            new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
            {
                {"AF", 0xF5},
                {"BC", 0xC5},
                {"DE", 0xD5},
                {"HL", 0xE5},
                {"IX", 0xDDE5},
                {"IY", 0xFDE5}
            };

        /// <summary>
        /// Z80 POP operation binary codes
        /// </summary>
        private static readonly Dictionary<string, int> s_PopOpBytes =
            new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
            {
                {"AF", 0xF1},
                {"BC", 0xC1},
                {"DE", 0xD1},
                {"HL", 0xE1},
                {"IX", 0xDDE1},
                {"IY", 0xFDE1}
            };

        /// <summary>
        /// Z80 INC operation binary codes
        /// </summary>
        private static readonly Dictionary<string, int> s_IncOpBytes =
            new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
            {
                {"A", 0x3C},
                {"B", 0x04},
                {"C", 0x0C},
                {"D", 0x14},
                {"E", 0x1C},
                {"H", 0x24},
                {"L", 0x2C},
                {"(HL)", 0x34},
                {"XL", 0xDD2C},
                {"XH", 0xDD24},
                {"YL", 0xFD2C},
                {"YH", 0xFD24},
                {"IXL", 0xDD2C},
                {"IXH", 0xDD24},
                {"IYL", 0xFD2C},
                {"IYH", 0xFD24},
                {"BC", 0x03},
                {"DE", 0x13},
                {"HL", 0x23},
                {"SP", 0x33},
                {"IX", 0xDD23},
                {"IY", 0xFD23},
            };

        /// <summary>
        /// Z80 DEC operation binary codes
        /// </summary>
        private static readonly Dictionary<string, int> s_DecOpBytes =
            new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
            {
                {"A", 0x3D},
                {"B", 0x05},
                {"C", 0x0D},
                {"D", 0x15},
                {"E", 0x1D},
                {"H", 0x25},
                {"L", 0x2D},
                {"(HL)", 0x35},
                {"XL", 0xDD2D},
                {"XH", 0xDD25},
                {"YL", 0xFD2D},
                {"YH", 0xFD25},
                {"IXL", 0xDD2D},
                {"IXH", 0xDD25},
                {"IYL", 0xFD2D},
                {"IYH", 0xFD25},
                {"BC", 0x0B},
                {"DE", 0x1B},
                {"HL", 0x2B},
                {"SP", 0x3B},
                {"IX", 0xDD2B},
                {"IY", 0xFD2B},
            };

        /// <summary>
        /// Z80 IN operation binary codes
        /// </summary>
        private static readonly Dictionary<string, int> s_InOpBytes =
            new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
            {
                {"A", 0xED78},
                {"B", 0xED40},
                {"C", 0xED48},
                {"D", 0xED50},
                {"E", 0xED58},
                {"H", 0xED60},
                {"L", 0xED68},
            };

        /// <summary>
        /// Z80 OUT operation binary codes
        /// </summary>
        private static readonly Dictionary<string, int> s_OutOpBytes =
            new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
            {
                {"A", 0xED79},
                {"B", 0xED41},
                {"C", 0xED49},
                {"D", 0xED51},
                {"E", 0xED59},
                {"H", 0xED61},
                {"L", 0xED69},
            };

        #endregion
    }
}


<|start_filename|>v2/Assembler/Spect.Net.Assembler/SyntaxTree/Pragmas/BankPragma.cs<|end_filename|>
using Antlr4.Runtime.Tree;
using Spect.Net.Assembler.SyntaxTree.Expressions;

namespace Spect.Net.Assembler.SyntaxTree.Pragmas
{
    /// <summary>
    /// This class represents the BANK pragma
    /// </summary>
    public sealed class BankPragma : ExpressionPragmaBase
    {
        /// <summary>
        /// Start offset of the bank
        /// </summary>
        public ExpressionNode StartOffset { get; set; }

        public BankPragma(IZ80AsmVisitorContext visitorContext, IParseTree context)
            : base(visitorContext, context)
        {
            if (context.ChildCount > 3)
            {
                StartOffset = visitorContext.GetExpression(context.GetChild(3));
            }
        }
    }
}

<|start_filename|>v2/Tests/Spect.Net.Assembler.Test/Assembler/LabelEmissionTests.cs<|end_filename|>
﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Spect.Net.Assembler.Assembler;

namespace Spect.Net.Assembler.Test.Assembler
{
    [TestClass]
    public class LabelEmissionTests : AssemblerTestBed
    {
        [TestMethod]
        public void LabelOnlyCodeEmissionWorks()
        {
            CodeEmitWorks(@"
                .org #6000
                LabelOnly:
                    ld a,b
                    ld bc,LabelOnly", 
                0x78, 0x01, 0x00, 0x60);
        }

        [TestMethod]
        public void LabelOnlyCodeEmissionWorksCs1()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = false },
                @"
                .org #6000
                labelonly:
                    ld a,b
                    ld bc,LabelOnly",
                0x78, 0x01, 0x00, 0x60);
        }

        [TestMethod]
        public void LabelOnlyCodeEmissionWorksCs2()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = true },
                @"
                .org #6000
                LabelOnly:
                    ld a,b
                    ld bc,LabelOnly",
                0x78, 0x01, 0x00, 0x60);
        }

        [TestMethod]
        public void LabelOnlyCodeEmissionWorksCs3()
        {
            CodeRaisesError(
                @"
                .org #6000
                labelOnly:
                    ld a,b
                    ld bc,LabelOnly",
                Errors.Z0201, new AssemblerOptions { UseCaseSensitiveSymbols = true });
        }

        [TestMethod]
        public void LabelOnlyCodeEmissionWorksWithDottedName()
        {
            CodeEmitWorks(@"
                .org #6000
                Label.Only:
                    ld a,b
                    ld bc,Label.Only",
                0x78, 0x01, 0x00, 0x60);
        }

        [TestMethod]
        public void LabelOnlyCodeEmissionWorksWithDottedNameCs1()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = false }, 
                @"
                .org #6000
                label.only:
                    ld a,b
                    ld bc,Label.Only",
                0x78, 0x01, 0x00, 0x60);
        }

        [TestMethod]
        public void LabelOnlyCodeEmissionWorksWithDottedNameCs2()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = true },
                @"
                .org #6000
                Label.Only:
                    ld a,b
                    ld bc,Label.Only",
                0x78, 0x01, 0x00, 0x60);
        }

        [TestMethod]
        public void LabelOnlyCodeEmissionWorksWithDottedNameCs3()
        {
            CodeRaisesError(
                @"
                .org #6000
                label.only:
                    ld a,b
                    ld bc,Label.Only",
                Errors.Z0201,
                new AssemblerOptions { UseCaseSensitiveSymbols = true });
        }

        [TestMethod]
        public void LabelOnlyWithCommentCodeEmissionWorks()
        {
            CodeEmitWorks(@"
                .org #6000
                LabelOnly: ; Empty label
                    ld a,b
                    ld bc,LabelOnly",
                0x78, 0x01, 0x00, 0x60);
        }

        [TestMethod]
        public void LabelOnlyWithCommentCodeEmissionWorksCs1()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = false }, 
                @"
                .org #6000
                labelonly: ; Empty label
                    ld a,b
                    ld bc,LabelOnly",
                0x78, 0x01, 0x00, 0x60);
        }

        [TestMethod]
        public void LabelOnlyWithCommentCodeEmissionWorksCs2()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = true },
                @"
                .org #6000
                LabelOnly: ; Empty label
                    ld a,b
                    ld bc,LabelOnly",
                0x78, 0x01, 0x00, 0x60);
        }

        [TestMethod]
        public void LabelOnlyWithCommentCodeEmissionWorksCs3()
        {
            CodeRaisesError(
                @"
                .org #6000
                labelOnly: ; Empty label
                    ld a,b
                    ld bc,LabelOnly",
                Errors.Z0201,
                new AssemblerOptions { UseCaseSensitiveSymbols = true });
        }

        [TestMethod]
        public void MultiLabelOnlyCodeEmissionWorks()
        {
            CodeEmitWorks(@"
                .org #6000
                LabelOnly1:
                LabelOnly2:
                LabelOnly3:
                LabelOnly4:
                LabelOnly5:
                    ld a,b
                    ld bc,LabelOnly3",
                0x78, 0x01, 0x00, 0x60);
        }

        [TestMethod]
        public void OrgWithHangingLabelWorks()
        {
            CodeEmitWorks(@"
                LabelOnly:
                    .org #6000
                    ld a,b
                    ld bc,LabelOnly",
                0x78, 0x01, 0x00, 0x60);
        }

        [TestMethod]
        public void EquWithHangingLabelWorks()
        {
            CodeEmitWorks(@"
                LabelOnly:
                    .org #6000
                LabelOnly2:
                    .equ #4567
                    ld a,b
                    ld bc,LabelOnly2",
                0x78, 0x01, 0x67, 0x45);
        }

        [TestMethod]
        public void VarWithHangingLabelWorks()
        {
            CodeEmitWorks(@"
                LabelOnly:
                    .org #6000
                LabelOnly2:
                    .var #4567
                    ld a,b
                    ld bc,LabelOnly2",
                0x78, 0x01, 0x67, 0x45);
        }

        [TestMethod]
        public void OrphanHangingLabelWorks()
        {
            CodeEmitWorks(@"
                    .org #6000
                    ld a,b
                    ld bc,LabelOnly
                LabelOnly:",
                0x78, 0x01, 0x04, 0x60);
        }

        [TestMethod]
        public void SingleTempLabelWithBackReferenceWorks()
        {
            CodeEmitWorks(@"
                Start:
                    .org #6000
                    ld a,b
                `t1:
                    ld bc,`t1",
                0x78, 0x01, 0x01, 0x60);
        }

        [TestMethod]
        public void SingleTempLabelWithBackReferenceWorksCs1()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = false }, 
                @"
                Start:
                    .org #6000
                    ld a,b
                `T1:
                    ld bc,`t1",
                0x78, 0x01, 0x01, 0x60);
        }

        [TestMethod]
        public void SingleTempLabelWithBackReferenceWorksCs2()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = true },
                @"
                Start:
                    .org #6000
                    ld a,b
                `t1:
                    ld bc,`t1",
                0x78, 0x01, 0x01, 0x60);
        }

        [TestMethod]
        public void SingleTempLabelWithBackReferenceWorksCs3()
        {
            CodeRaisesError(
                @"
                Start:
                    .org #6000
                    ld a,b
                `T1:
                    ld bc,`t1",
                Errors.Z0201,
                new AssemblerOptions { UseCaseSensitiveSymbols = true });
        }

        [TestMethod]
        public void SingleTempLabelWithForwardReferenceWorks()
        {
            CodeEmitWorks(@"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,`t1
                `t1:
                    ld a,b",
                0x78, 0x01, 0x04, 0x60, 0x78);
        }

        [TestMethod]
        public void SingleTempLabelWithForwardReferenceWorksCs1()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = false},
                @"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,`t1
                `T1:
                    ld a,b",
                0x78, 0x01, 0x04, 0x60, 0x78);
        }

        [TestMethod]
        public void SingleTempLabelWithForwardReferenceWorksCs2()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = true },
                @"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,`t1
                `t1:
                    ld a,b",
                0x78, 0x01, 0x04, 0x60, 0x78);
        }

        [TestMethod]
        public void SingleTempLabelWithForwardReferenceWorksCs3()
        {
            CodeRaisesError(
                @"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,`t1
                `T1:
                    ld a,b",
                Errors.Z0201,
                new AssemblerOptions { UseCaseSensitiveSymbols = true });
        }

        [TestMethod]
        public void StartAndEndLabelWithForwardReferenceWorks()
        {
            CodeEmitWorks(@"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,End
                End:
                    ld a,b",
                0x78, 0x01, 0x04, 0x60, 0x78);
        }

        [TestMethod]
        public void StartAndEndLabelWithForwardReferenceWorksCs1()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = false }, 
                @"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,END
                End:
                    ld a,b",
                0x78, 0x01, 0x04, 0x60, 0x78);
        }

        [TestMethod]
        public void StartAndEndLabelWithForwardReferenceWorksCs2()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = true },
                @"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,End
                End:
                    ld a,b",
                0x78, 0x01, 0x04, 0x60, 0x78);
        }

        [TestMethod]
        public void StartAndEndLabelWithForwardReferenceWorksCs3()
        {
            CodeRaisesError(
                @"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,END
                End:
                    ld a,b",
                Errors.Z0201,
                new AssemblerOptions { UseCaseSensitiveSymbols = true });
        }

        [TestMethod]
        public void TempLabelInDifferentScopesWork()
        {
            CodeEmitWorks(@"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,`t1
                `t1:
                    ld a,b
                Next: 
                    ld a,b
                    ld bc,`t1
                `t1:
                    ld a,b",
                0x78, 0x01, 0x04, 0x60, 0x78, 0x78, 0x01, 0x09, 0x60, 0x78);
        }

        [TestMethod]
        public void TempLabelInDifferentScopesWorkCs1()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = false},
                @"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,`t1
                `T1:
                    ld a,b
                Next: 
                    ld a,b
                    ld bc,`T1
                `t1:
                    ld a,b",
                0x78, 0x01, 0x04, 0x60, 0x78, 0x78, 0x01, 0x09, 0x60, 0x78);
        }

        [TestMethod]
        public void TempLabelInDifferentScopesWorkCs2()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = true },
                @"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,`t1
                `t1:
                    ld a,b
                Next: 
                    ld a,b
                    ld bc,`t1
                `t1:
                    ld a,b",
                0x78, 0x01, 0x04, 0x60, 0x78, 0x78, 0x01, 0x09, 0x60, 0x78);
        }

        [TestMethod]
        public void TempLabelInDifferentScopesWorkCs3()
        {
            CodeRaisesMultipleErrors(
                @"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,`t1
                `T1:
                    ld a,b
                Next: 
                    ld a,b
                    ld bc,`T1
                `t1:
                    ld a,b",
                new AssemblerOptions { UseCaseSensitiveSymbols = true },
                Errors.Z0201);
        }


        [TestMethod]
        public void TempLabelWithLoopWork()
        {
            CodeEmitWorks(@"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,`t1
                    .loop 3
                    nop
                    .endl
                `t1:
                    ld a,b
                ",
                0x78, 0x01, 0x07, 0x60, 0x00, 0x00, 0x00, 0x78);
        }

        [TestMethod]
        public void TempLabelWithLoopWorkCs1()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = false},
                @"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,`t1
                    .loop 3
                    nop
                    .endl
                `T1:
                    ld a,b
                ",
                0x78, 0x01, 0x07, 0x60, 0x00, 0x00, 0x00, 0x78);
        }

        [TestMethod]
        public void TempLabelWithLoopWorkCs2()
        {
            CodeEmitWorksWithOptions(
                new AssemblerOptions { UseCaseSensitiveSymbols = true },
                @"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,`t1
                    .loop 3
                    nop
                    .endl
                `t1:
                    ld a,b
                ",
                0x78, 0x01, 0x07, 0x60, 0x00, 0x00, 0x00, 0x78);
        }

        [TestMethod]
        public void TempLabelWithLoopWorkCs3()
        {
            CodeRaisesError(
                @"
                Start:
                    .org #6000
                    ld a,b
                    ld bc,`t1
                    .loop 3
                    nop
                    .endl
                `T1:
                    ld a,b
                ",
                Errors.Z0201,
                new AssemblerOptions { UseCaseSensitiveSymbols = true });
        }
    }
}


<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/Debugging/VsIntegratedSpectrumDebugInfoProvider.cs<|end_filename|>
﻿using System;
using System.Linq;
using System.Threading.Tasks;
using Antlr4.Runtime;
using EnvDTE;
using Spect.Net.Assembler.Assembler;
using Spect.Net.EvalParser;
using Spect.Net.EvalParser.Generated;
using Spect.Net.EvalParser.SyntaxTree;
using Spect.Net.SpectrumEmu.Abstraction.Machine;
using Spect.Net.SpectrumEmu.Abstraction.Providers;
using Spect.Net.SpectrumEmu.Machine;
using Spect.Net.VsPackage.LanguageServices.Z80Asm;
using Spect.Net.VsPackage.ToolWindows.SpectrumEmulator;

namespace Spect.Net.VsPackage.Debugging
{
    public class VsIntegratedSpectrumDebugInfoProvider: VmComponentProviderBase,
        ISpectrumDebugInfoProvider,
        IDisposable
    {
        /// <summary>
        /// Contains the compiled output, provided the compilation was successful
        /// </summary>
        public AssemblerOutput CompiledOutput { get; set; }

        /// <summary>
        /// The name of the file with the current breakpoint
        /// </summary>
        public string CurrentBreakpointFile { get; private set; }

        /// <summary>
        /// The line number within the current breakpoint file
        /// </summary>
        public int CurrentBreakpointLine { get; private set; }

        /// <summary>
        /// The currently defined breakpoints
        /// </summary>
        public BreakpointCollection Breakpoints { get; set; }

        /// <summary>
        /// Gets or sets an imminent breakpoint
        /// </summary>
        public ushort? ImminentBreakpoint { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Object" /> class.
        /// </summary>
        public VsIntegratedSpectrumDebugInfoProvider()
        {
            Breakpoints = new BreakpointCollection();
        }

        /// <summary>
        /// Prepares this object for debugging
        /// </summary>
        public void Prepare()
        {
            SpectNetPackage.Default.EmulatorViewModel.VmStateChanged += OnVmStateChanged;
        }

        /// <summary>
        /// Us this method to prepare the breakpoints when running the
        /// virtual machine in debug mode
        /// </summary>
        public void PrepareBreakpoints()
        {
            // --- No compiled code, no VS breakpoints to merge
            if (CompiledOutput == null)
            {
                return;
            }

            // --- Start assembling the new breakpoint collection
            var newBreakpointCollection = new BreakpointCollection();

            // --- Keep CPU breakpoints set through the Disassembler tool
            foreach (var pair in Breakpoints.Where(bp => bp.Value.IsCpuBreakpoint))
            {
                newBreakpointCollection[pair.Key] = pair.Value;
            }

            // --- Create new breakpoints
            foreach (Breakpoint newBp in SpectNetPackage.Default.ApplicationObject.Debugger.Breakpoints)
            {
                // --- Check for the file
                var fileIndex = -1;
                for (var i = 0; i < CompiledOutput.SourceFileList.Count; i++)
                {
                    if (string.Compare(newBp.File, CompiledOutput.SourceFileList[i].Filename,
                            StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        fileIndex = i;
                        break;
                    }
                }
                if (fileIndex < 0) continue;

                var newVsBreakpoint = new BreakpointInfo
                {
                    File = CompiledOutput.SourceFileList[fileIndex].Filename,
                    FileLine = newBp.FileLine,
                    HitType = BreakpointHitType.None
                };

                // --- Set hit condition
                if (newBp.HitCountType != dbgHitCountType.dbgHitCountTypeNone)
                {
                    if (newBp.HitCountType == dbgHitCountType.dbgHitCountTypeEqual)
                    {
                        newVsBreakpoint.HitType = BreakpointHitType.Equal;
                    }
                    else if (newBp.HitCountType == dbgHitCountType.dbgHitCountTypeGreaterOrEqual)
                    {
                        newVsBreakpoint.HitType = BreakpointHitType.GreaterOrEqual;
                    }
                    else if (newBp.HitCountType == dbgHitCountType.dbgHitCountTypeMultiple)
                    {
                        newVsBreakpoint.HitType = BreakpointHitType.Multiple;
                    }
                    newVsBreakpoint.HitConditionValue = (ushort)(newBp.HitCountTarget >= 0 ? newBp.HitCountTarget : 0);
                }

                // --- Set filter condition
                if (!string.IsNullOrWhiteSpace(newBp.Condition))
                {
                    var inputStream = new AntlrInputStream(newBp.Condition);
                    var lexer = new Z80EvalLexer(inputStream);
                    var tokenStream = new CommonTokenStream(lexer);
                    var evalParser = new Z80EvalParser(tokenStream);
                    var context = evalParser.compileUnit();
                    var visitor = new Z80EvalVisitor();
                    var z80Expr = (Z80ExpressionNode)visitor.Visit(context);
                    if (evalParser.SyntaxErrors.Count == 0)
                    {
                        newVsBreakpoint.FilterExpression = z80Expr.Expression;
                    }
                }

                // --- Check the breakpoint address
                if (CompiledOutput.AddressMap.TryGetValue((fileIndex, newBp.FileLine), out var addresses))
                {
                    foreach (var addr in addresses)
                    {
                        // --- Set up breakpoints

                        newBreakpointCollection.Add(addr, newVsBreakpoint);
                    }
                }

            }

            // --- Set the new collection of breakpoints
            Breakpoints = newBreakpointCollection;
        }


        /// <summary>
        /// Resets the current hit count of breakpoints
        /// </summary>
        public void ResetHitCounts()
        {
            foreach (var bp in Breakpoints.Values)
            {
                bp.CurrentHitCount = 0;
            }
        }
        
        /// <summary>
        /// Checks if the virtual machine should stop at the specified address
        /// </summary>
        /// <param name="address">Address to check</param>
        /// <returns>
        /// True, if the address means a breakpoint to stop; otherwise, false
        /// </returns>
        public bool ShouldBreakAtAddress(ushort address)
            => Breakpoints.ContainsKey(address);

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or
        /// resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            SpectNetPackage.Default.EmulatorViewModel.VmStateChanged -= OnVmStateChanged;
        }

        private async void OnVmStateChanged(object sender, VmStateChangedEventArgs args)
        {
            if (args.NewState == VmState.Running || args.NewState == VmState.Stopped)
            {
                // --- Remove current breakpoint information
                var oldFile = CurrentBreakpointFile;
                var oldLine = CurrentBreakpointLine;

                CurrentBreakpointFile = null;
                CurrentBreakpointLine = -1;

                if (oldFile != null)
                {
                    Z80AsmViewTaggerProvider.UpdateBreakpointVisuals(oldFile, oldLine);
                }
            }

            var package = SpectNetPackage.Default;
            if (args.NewState == VmState.Paused
                && package.EmulatorViewModel.Machine.RunsInDebugMode
                && !package.Options.DisableSourceNavigation)
            {
                // --- Set up breakpoint information
                var address = package.EmulatorViewModel.Machine.SpectrumVm.Cpu.Registers.PC;
                if (CompiledOutput?.SourceMap != null
                    && CompiledOutput.SourceMap.TryGetValue(address, out var fileInfo))
                {
                    // --- Add highlight to the current source code line
                    CurrentBreakpointFile = CompiledOutput
                        .SourceFileList[fileInfo.FileIndex].Filename;
                    CurrentBreakpointLine = fileInfo.Line;
                    if (package.Options.ForceShowSourceCode)
                    {
                        package.ShowToolWindow<SpectrumEmulatorToolWindow>();
                        var document = package.ApplicationObject.Documents.Open(CurrentBreakpointFile);
                        document.Activate();
                    }
                    else
                    {
                        package.ApplicationObject.Documents.Open(CurrentBreakpointFile);
                        package.ShowToolWindow<SpectrumEmulatorToolWindow>();
                    }
                    await Task.Delay(10);
                    Z80AsmViewTaggerProvider.UpdateBreakpointVisuals(CurrentBreakpointFile, CurrentBreakpointLine);
                }
            }
        }
    }
}

<|start_filename|>v2/Assembler/Spect.Net.Assembler/SyntaxTree/Operations/MacroOrStructInvocation.cs<|end_filename|>
﻿using System.Collections.Generic;
using System.Linq;
using Spect.Net.Assembler.Generated;

namespace Spect.Net.Assembler.SyntaxTree.Operations
{
    /// <summary>
    /// This class represents a macro or struct invocation statement
    /// </summary>
    public class MacroOrStructInvocation : StatementBase
    {
        /// <summary>
        /// Name of the macro to invoke
        /// </summary>
        public string Name { get; }

        /// <summary>
        /// Actual parameters of the macro invocation
        /// </summary>
        public List<Operand> Parameters { get; }

        public MacroOrStructInvocation(IZ80AsmVisitorContext visitorContext, Z80AsmParser.MacroOrStructInvocationContext context)
        {
            Parameters = new List<Operand>();
            if (context.macroArgument().Length > 1
                || context.macroArgument().Length > 0 && context.macroArgument()[0].operand() != null)
            {
                Parameters.AddRange(context.macroArgument()
                    .Select(arg => arg.operand() != null
                        ? visitorContext.GetOperand(arg.operand())
                        : new Operand()));
            }

            KeywordSpan = new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1);
            Name = context.IDENTIFIER().GetText();
        }
    }
}

<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/SolutionItems/SpectrumProjectItemBase.cs<|end_filename|>
﻿using System.Linq;
using EnvDTE;

#pragma warning disable VSTHRD010 // Invoke single-threaded types on Main thread

namespace Spect.Net.VsPackage.SolutionItems
{
    /// <summary>
    /// This class is intended to be the base class of all project items within a
    /// ZX Spectrum Code Discovery project
    /// </summary>
    public abstract class SpectrumProjectItemBase
    {
        /// <summary>
        /// The DTE project item associated with this item.
        /// </summary>
        public ProjectItem DteProjectItem { get; }

        /// <summary>
        /// Project item identity.
        /// </summary>
        public string Identity { get; }

        /// <summary>
        /// The project item's file name.
        /// </summary>
        public string Filename { get; }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Object" /> class.
        /// </summary>
        protected SpectrumProjectItemBase(ProjectItem dteProjectItem)
        {
            DteProjectItem = dteProjectItem;
            Filename = dteProjectItem.FileNames[0];
            Identity = dteProjectItem.Properties.Item("Identity").Value.ToString();
        }

        /// <summary>
        /// Checks if this project item has a child item with the specified name.
        /// </summary>
        /// <param name="filename">File name to check</param>
        /// <returns>True, if the item has the specified child item</returns>
        public bool HasChild(string filename)
        {
            foreach (ProjectItem item in DteProjectItem.ProjectItems)
            {
                var itemPath = item.Properties.Item("FullPath").Value;
                if (itemPath.Equals(filename))
                {
                    return true;
                }
            }

            return false;
        }

    }
}

#pragma warning restore VSTHRD010 // Invoke single-threaded types on Main thread


<|start_filename|>v2/Tests/Spect.Net.Assembler.Test/Assembler/MacroEmitTests.cs<|end_filename|>
﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shouldly;
using Spect.Net.Assembler.Assembler;
// ReSharper disable StringLiteralTypo
// ReSharper disable IdentifierTypo

namespace Spect.Net.Assembler.Test.Assembler
{
    [TestClass]
    public class MacroEmitTests : AssemblerTestBed
    {
        [TestMethod]
        public void MacroWithNoLabelFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                .macro()
                .endm
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0400);
        }

        [TestMethod]
        public void MacroWithLocalLabelFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                `local .macro()
                .endm
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0427);
        }

        [TestMethod]
        public void MacroWithLabelWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro()
                    .endm
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Macros.ContainsKey("MyMacro").ShouldBeTrue();
            var def = output.Macros["MyMacro"];
            def.ShouldNotBeNull();
            def.Section.FirstLine.ShouldBe(0);
            def.Section.LastLine.ShouldBe(1);
            def.MacroName.ShouldBe("MyMacro");
        }

        [TestMethod]
        public void MacroWithExistingLabelFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: nop
                MyMacro: .macro()
                    .endm
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0402);
        }

        [TestMethod]
        public void MacroWithHangingLabelWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: 
                    .macro()
                    .endm
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Macros.ContainsKey("MyMacro").ShouldBeTrue();
            var def = output.Macros["MyMacro"];
            def.ShouldNotBeNull();
            def.Section.FirstLine.ShouldBe(1);
            def.Section.LastLine.ShouldBe(2);
            def.MacroName.ShouldBe("MyMacro");
        }

        [TestMethod]
        public void MacroWithArgumentsWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first, second)
                    .endm
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Macros.ContainsKey("MyMacro").ShouldBeTrue();
            var def = output.Macros["MyMacro"];
            def.ShouldNotBeNull();
            def.Section.FirstLine.ShouldBe(0);
            def.Section.LastLine.ShouldBe(1);
            def.MacroName.ShouldBe("MyMacro");
        }

        [TestMethod]
        public void MacroDefWithinMacroDefIsNotAllowed()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first, second)
                Nested:  .macro()
                    .endm
                    .endm
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0404);
        }

        [TestMethod]
        public void MacroDefWithValidParameterNamesWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first, second)
                    {{first}}
                    ld a,{{second}}
                    .endm
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
        }

        [TestMethod]
        public void MacroDefWithInvalidParameterNamesFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first, second)
                    {{first}}
                    ld b,{{unknown}}
                    ld {{other}},{{second}}
                    {{what}}
                    .endm
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(3);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0403);
            output.Errors[1].ErrorCode.ShouldBe(Errors.Z0403);
            output.Errors[2].ErrorCode.ShouldBe(Errors.Z0403);
        }

        [TestMethod]
        public void MacroWithNoEndFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first, second)
                    ld a,b
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0401);
        }

        [TestMethod]
        [DataRow(".endm")]
        [DataRow("endm")]
        [DataRow(".ENDM")]
        [DataRow("ENDM")]
        [DataRow(".mend")]
        [DataRow("mend")]
        [DataRow(".MEND")]
        [DataRow("MEND")]
        public void EndMacroWithoutOpenTagFails(string source)
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(source);

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0405);
        }

        [TestMethod]
        public void MacroDefWithDuplicatedArgumentFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first, second, first)
                    .endm
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0417);
        }

        [TestMethod]
        public void MacroInvocationWithUnknownNameFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro()
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0418);
        }

        [TestMethod]
        public void MacroInvocationWithKnownNameWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro()
                    nop
                .endm
                MyMacro()
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
        }

        [TestMethod]
        public void MacroInvocationWithKnownNameAndArgumentsWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first, second)
                    nop
                .endm
                MyMacro(1, 2)
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
        }

        [TestMethod]
        public void MacroInvocationWithLessArgumentWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first)
                    nop
                .endm
                MyMacro()
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
        }

        [TestMethod]
        public void MacroInvocationWithMoreArgumentsFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first)
                    nop
                .endm
                MyMacro(12, 13)
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0419);
        }

        [TestMethod]
        public void MacroArgEvaluationWithSingleArgumentWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first)
                    nop
                .endm
                value .equ 123
                MyMacro(value)
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
        }

        [TestMethod]
        public void MacroArgEvaluationWithSingleArgumentFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first)
                    nop
                .endm
                MyMacro(value)
                value .equ 123
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
        }

        [TestMethod]
        public void MacroArgEvaluationWithDivByZeroFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first)
                    nop
                .endm
                value .equ 0
                MyMacro(1/value)
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0200);
        }

        [TestMethod]
        public void MacroArgEvaluationWithMultipleArgumentWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first, second)
                    nop
                .endm
                value .equ 123
                MyMacro(value, value + 2)
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
        }

        [TestMethod]
        public void MacroArgEvaluationWithMultipleArgumentFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyMacro: .macro(first, second)
                    nop
                .endm
                MyMacro(value, value + 2)
                value .equ 123
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
        }

        [TestMethod]
        public void SimpleMacroEmitWorks()
        {
            const string SOURCE = @"
                Simple: .macro()
                    nop
                    ld a,b
                    nop
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x00, 0x78, 0x00);
        }

        [TestMethod]
        public void MacroWithInternalLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    ThisLabel: ld bc,ThisLabel
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x00, 0x80);
        }

        [TestMethod]
        public void MacroWithInternalLabelInvokedMultipleTimesWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    ThisLabel: ld bc,ThisLabel
                .endm
                Simple()
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x00, 0x80, 0x01, 0x03, 0x80);
        }

        [TestMethod]
        public void MacroWithInternalFixupLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    ld bc,ThisLabel
                    ThisLabel: nop
                .endm
                Simple()
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x03, 0x80, 0x00, 0x01, 0x07, 0x80, 0x00);
        }

        [TestMethod]
        public void LoopWithStartLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    ld bc,Simple
                    nop
                .endm
                Simple()
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x00, 0x80, 0x00, 0x01, 0x04, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroWithEndLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    ld bc,EndLabel
                    nop
                EndLabel: .endm
                Simple()
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x04, 0x80, 0x00, 0x01, 0x08, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroWithExternalFixupLabelWorks1()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    ld bc,OuterLabel
                    nop
                .endm
                Simple()
                Simple()
                OuterLabel: nop";

            CodeEmitWorks(SOURCE, 0x01, 0x08, 0x80, 0x00, 0x01, 0x08, 0x80, 0x00, 0x00);
        }

        [TestMethod]
        public void MacroWithExternalFixupLabelWorks2()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    ld bc,OuterLabel
                    nop
                .endm
                OuterLabel: nop
                Simple()
                Simple()";

            CodeEmitWorks(SOURCE, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroNestedLoopEmitWithSingleLineAndNoInternalLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    ld bc,#1234
                    .loop 3
                        inc a
                    .endl
                .endm
                Simple()
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x34, 0x12, 0x3C, 0x3C, 0x3C, 0x01, 0x34, 0x12, 0x3C, 0x3C, 0x3C);
        }

        [TestMethod]
        public void MacroNestedLoopWithLabelsWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    inc a
                    .loop 2
                        ld hl,EndLabel
                        ld bc,NopLabel
                    EndLabel: .endl
                    NopLabel: nop
                .endm
                Simple()";

            CodeEmitWorks(SOURCE,
                0x3C, 0x21, 0x07, 0x80, 0x01, 0x0D, 0x80, 0x21, 0x0D, 0x80, 0x01, 0x0D, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroNestedLoopWithLabelsWorks2()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    inc a
                    .loop 2
                        ld hl,EndLabel
                        ld bc,NopLabel
                    EndLabel: 
                        nop
                    .endl
                    NopLabel: nop
                .endm
                Simple()";

            CodeEmitWorks(SOURCE,
                0x3C, 0x21, 0x07, 0x80, 0x01, 0x0F, 0x80, 0x00, 0x21, 0x0E, 0x80, 0x01, 0x0F, 0x80, 0x00, 0x00);
        }

        [TestMethod]
        public void MacroLoopWithVarWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    index = 1;
                    .loop 2
                        ld a,index
                        index = index + 1
                        nop
                    .endl
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x3E, 0x01, 0x00, 0x3E, 0x02, 0x00);
        }

        [TestMethod]
        public void MacroLoopWithNestedVarWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    index = 1;
                    .loop 2
                        index = 5
                        ld a,index
                        index := index + 1
                        nop
                    EndLabel: .endl
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x3E, 0x05, 0x00, 0x3E, 0x05, 0x00);
        }

        [TestMethod]
        public void LoopCounterWorksInMacro()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    .loop 3
                        .db $cnt
                    .endl
                .endm
                Simple()
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03);
        }

        [TestMethod]
        public void MacroRepeatEmitWithSingleLineAndNoInternalLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .repeat
                        ld bc,#1234
                        counter = counter + 1
                    .until counter == 2
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x34, 0x12, 0x01, 0x34, 0x12);
        }

        [TestMethod]
        public void MacroRepeatEmitWithMultipleLineAndNoInternalLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .repeat
                        inc b
                        inc c
                        inc d
                        counter = counter + 1
                    .until counter == 2
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x04, 0x0C, 0x14, 0x04, 0x0C, 0x14);
        }

        [TestMethod]
        public void MacroRepeatEmitWithMultipleLineAndNoInternalLabelWorks2()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 3
                    .repeat
                        inc b
                        inc c
                        inc d
                        counter = counter + 1
                    .until counter == 5
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x04, 0x0C, 0x14, 0x04, 0x0C, 0x14);
        }

        [TestMethod]
        public void MacroRepeatWithInternalLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .repeat
                        ThisLabel: ld bc,ThisLabel
                        counter = counter + 1
                    .until counter == 2
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x00, 0x80, 0x01, 0x03, 0x80);
        }

        [TestMethod]
        public void MacroRepeatWithInternalFixupLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .repeat
                        ld bc,ThisLabel
                        ThisLabel: nop
                        counter = counter + 1
                    .until counter == 2
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x03, 0x80, 0x00, 0x01, 0x07, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroRepeatWithStartLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    StartLabel: .repeat
                        ld bc,StartLabel
                        nop
                        counter = counter + 1
                    .until counter == 2
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroRepeatWithEndLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .repeat
                        ld bc,EndLabel
                        nop
                        counter = counter + 1
                    EndLabel .until counter == 2
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x04, 0x80, 0x00, 0x01, 0x08, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroRepeatWithExternalFixupLabelWorks1()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .repeat
                        ld bc,OuterLabel
                        nop
                        counter = counter + 1
                    .until counter == 2
                .endm
                OuterLabel: nop
                Simple()";

            CodeEmitWorks(SOURCE, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroRepeatWithExternalFixupLabelWorks2()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .repeat
                        ld bc,OuterLabel
                        nop
                        counter = counter + 1
                    .until counter == 2
                .endm
                Simple()
                OuterLabel: nop";

            CodeEmitWorks(SOURCE, 0x01, 0x08, 0x80, 0x00, 0x01, 0x08, 0x80, 0x00, 0x00);
        }

        [TestMethod]
        public void MacroRepeatNestedLoopEmitWithSingleLineAndNoInternalLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .repeat
                        ld bc,#1234
                        .loop 3
                            inc a
                        .endl
                        counter = counter + 1
                    .until counter == 2
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x34, 0x12, 0x3C, 0x3C, 0x3C, 0x01, 0x34, 0x12, 0x3C, 0x3C, 0x3C);
        }

        [TestMethod]
        public void MacroWithRepeatCounterWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .repeat
                        .db $cnt
                        counter = counter + 1
                    .until counter == 3
                .endm
                Simple()
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03);
        }

        [TestMethod]
        public void MacroWhileEmitWithSingleLineAndNoInternalLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .while counter < 2
                        ld bc,#1234
                        counter = counter + 1
                    .wend
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x34, 0x12, 0x01, 0x34, 0x12);
        }

        [TestMethod]
        public void MacroWhileEmitWithMultipleLineAndNoInternalLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .while counter < 2
                        inc b
                        inc c
                        inc d
                        counter = counter + 1
                    .wend
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x04, 0x0C, 0x14, 0x04, 0x0C, 0x14);
        }

        [TestMethod]
        public void MacroWhileWithInternalLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .while counter < 2
                        ThisLabel: ld bc,ThisLabel
                        counter = counter + 1
                    .wend
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x00, 0x80, 0x01, 0x03, 0x80);
        }

        [TestMethod]
        public void MacroWhileWithInternalFixupLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .while counter < 2
                        ld bc,ThisLabel
                        ThisLabel: nop
                        counter = counter + 1
                    .wend
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x03, 0x80, 0x00, 0x01, 0x07, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroWhileWithStartLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    StartLabel: .while counter < 2
                        ld bc,StartLabel
                        nop
                        counter = counter + 1
                    .wend
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroWhileWithEndLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .while counter < 2
                        ld bc,EndLabel
                        nop
                        counter = counter + 1
                    EndLabel .wend
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x04, 0x80, 0x00, 0x01, 0x08, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroWhileWithExternalFixupLabelWorks1()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .while counter < 2
                        ld bc,OuterLabel
                        nop
                        counter = counter + 1
                    .wend
                .endm
                Simple()
                OuterLabel: nop";

            CodeEmitWorks(SOURCE, 0x01, 0x08, 0x80, 0x00, 0x01, 0x08, 0x80, 0x00, 0x00);
        }

        [TestMethod]
        public void MacroWhileWithExternalFixupLabelWorks2()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0
                    .while counter < 2
                        ld bc,OuterLabel
                        nop
                        counter = counter + 1
                    .wend
                .endm
                OuterLabel: nop
                Simple()";

            CodeEmitWorks(SOURCE, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroWhileCounterWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    counter = 0;
                    .while counter < 3
                        .db $cnt
                        counter = counter + 1                    
                    .endw
                .endm
                Simple()
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03);
        }

        [TestMethod]
        public void MacroForLoopEmitWithSingleLineAndNoInternalLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    .for _i = 1 .to 2
                        ld bc,#1234
                    .next
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x34, 0x12, 0x01, 0x34, 0x12);
        }

        [TestMethod]
        public void MacroForLoopEmitWithMultipleLineAndNoInternalLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    .for _i = 1 .to 2
                        inc b
                        inc c
                        inc d
                    .next
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x04, 0x0C, 0x14, 0x04, 0x0C, 0x14);
        }

        [TestMethod]
        public void MacroBackwardForLoopEmitWithMultipleLineAndNoInternalLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    .for _i = 2 .to 1 step -1
                        inc b
                        inc c
                        inc d
                    .next
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x04, 0x0C, 0x14, 0x04, 0x0C, 0x14);
        }

        [TestMethod]
        public void MacroForLoopWithInternalLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    .for _i = 1 .to 2
                        ThisLabel: ld bc,ThisLabel
                    .next
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x00, 0x80, 0x01, 0x03, 0x80);
        }

        [TestMethod]
        public void MacroForLoopWithInternalFixupLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    .for _i = 2 .to 1 step -1
                        ld bc,ThisLabel
                        ThisLabel: nop
                    .next
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x03, 0x80, 0x00, 0x01, 0x07, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroForLoopWithStartLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    StartLabel: .for _i = 1 to 2
                        ld bc,StartLabel
                        nop
                    .next
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroForLoopWithEndLabelWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    .for _i = 1 .to 2
                        ld bc,EndLabel
                        nop
                    EndLabel: .next
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x04, 0x80, 0x00, 0x01, 0x08, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroForLoopWithExternalFixupLabelWorks1()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    .for _i = 2 to 1 step -1
                        ld bc,OuterLabel
                        nop
                    .next
                .endm
                Simple()
                OuterLabel: nop";

            CodeEmitWorks(SOURCE, 0x01, 0x08, 0x80, 0x00, 0x01, 0x08, 0x80, 0x00, 0x00);
        }

        [TestMethod]
        public void MacroForLoopWithExternalFixupLabelWorks2()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    .for _i = 2 to 1 step -1
                        ld bc,OuterLabel
                        nop
                    .next
                .endm
                OuterLabel: nop
                Simple()";

            CodeEmitWorks(SOURCE, 0x00, 0x01, 0x00, 0x80, 0x00, 0x01, 0x00, 0x80, 0x00);
        }

        [TestMethod]
        public void MacroForLoopCounterWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    .for _i = 6 to 8
                        .db $cnt
                    .next
                .endm
                Simple()
                Simple()";

            CodeEmitWorks(SOURCE, 0x01, 0x02, 0x03, 0x01, 0x02, 0x03);
        }

        [TestMethod]
        public void MacroWithLoopVariableWorks()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    .for _i = 6 to 8
                        .db _i
                    .next
                .endm
                Simple()
                Simple()";

            CodeEmitWorks(SOURCE, 0x06, 0x07, 0x08, 0x06, 0x07, 0x08);
        }

        [TestMethod]
        public void MultipleMacrosWork()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple1: .macro()
                    .db #01
                .endm
                Simple2: .macro()
                    .db #02
                .endm
                Simple3: .macro()
                    .db #03
                .endm
                Simple2()
                Simple1()
                Simple3()
                Simple1()
                Simple2()";

            CodeEmitWorks(SOURCE, 0x02, 0x01, 0x03, 0x01, 0x02);
        }

        [TestMethod]
        public void MacroIfEmitsNothingWithFalseCondition()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    cond = false;
                    .if cond
                        nop
                    .endif
                .endm
                Simple()";

            CodeEmitWorks(SOURCE);
        }

        [TestMethod]
        public void MacroIfEmitsCodeWithTrueCondition()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    cond = true;
                    .if cond
                        nop
                    .endif
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x00);
        }

        [TestMethod]
        public void MacroIfEmitsCodeWithTrueConditionAndElse()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    cond = true;
                    .if cond
                        nop
                    .else
                        inc c
                    .endif
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x00);
        }

        [TestMethod]
        public void MacroIfEmitsCodeWithFalseConditionAndElse()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    cond = false;
                    .if cond
                        nop
                    .else
                        inc b
                    .endif
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x04);
        }

        [TestMethod]
        public void MacroIfEmitsNothingWithMultipleFalseCondition()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    cond = false;
                    .if cond
                        nop
                    .elif cond
                        nop
                    .elif cond
                        nop
                    .endif
                .endm
                Simple()";

            CodeEmitWorks(SOURCE);
        }

        [TestMethod]
        [DataRow("0", 0x00)]
        [DataRow("1", 0x04)]
        [DataRow("2", 0x0C)]
        [DataRow("123", 0x14)]
        public void MacroIfEmitsBranchWithTrueCondition(string value, int emitted)
        {
            // --- Arrange
            var source = @"
                Simple: .macro()
                    cond = " + value + @"
                    .if cond == 0
                        nop
                    .elif cond == 1
                        inc b
                    .elif cond == 2
                        inc c
                    .else
                        inc d
                    .endif
                .endm
                Simple()";

            CodeEmitWorks(source, (byte)emitted);
        }

        [TestMethod]
        [DataRow("0", 0x03)]
        [DataRow("1", 0x04)]
        [DataRow("2", 0x05)]
        [DataRow("123", 0x6)]
        public void MacroIfHandlesEquProperly(string value, int emitted)
        {
            // --- Arrange
            var source = @"
                Simple: .macro()
                    cond = " + value + @"
                    .if cond == 0
                        value .equ 3
                    .elif cond == 1
                        value .equ 4
                    .elif cond == 2
                        value .equ 5
                    .else
                        value .equ 6
                    .endif
                    .db value
                .endm
                Simple()";

            CodeEmitWorks(source, (byte)emitted);
        }

        [TestMethod]
        [DataRow("0", 0x03)]
        [DataRow("1", 0x04)]
        [DataRow("2", 0x05)]
        [DataRow("123", 0x6)]
        public void MacroIfHandlesVarProperly(string value, int emitted)
        {
            // --- Arrange
            var source = @"
                Simple: .macro()
                    cond = " + value + @"
                    value = 0
                    .if cond == 0
                        value = 3
                    .elif cond == 1
                        value = 4
                    .elif cond == 2
                        value = 5
                    .else
                        value = 6
                    .endif
                    .db value
                .endm
                Simple()";

            CodeEmitWorks(source, (byte)emitted);
        }

        [TestMethod]
        [DataRow("0", 0x3C)]
        [DataRow("1", 0x04)]
        [DataRow("2", 0x0C)]
        [DataRow("123", 0x14)]
        public void MacroIfHandlesBranchStartLabels(string value, int emitted)
        {
            // --- Arrange
            var source = @"
                Simple: .macro()
                    cond = " + value + @"
                    .if cond == 0
                        Label: nop
                        inc a
                        ld bc,Label
                    .elif cond == 1
                        Label: nop
                        inc b
                        ld bc,Label
                    .elif cond == 2
                        Label: nop
                        inc c
                        ld bc,Label
                    .else
                        Label: nop
                        inc d
                        ld bc,Label
                    .endif
                .endm
                Simple()";

            CodeEmitWorks(source, 0x00, (byte)emitted, 0x01, 0x00, 0x80);
        }

        [TestMethod]
        [DataRow("0", 0x3C)]
        [DataRow("1", 0x04)]
        [DataRow("2", 0x0C)]
        [DataRow("123", 0x14)]
        public void MacroIfHandlesBranchStartHangingLabels(string value, int emitted)
        {
            // --- Arrange
            var source = @"
                Simple: .macro()
                    cond = " + value + @"
                    .if cond == 0
                      Label: 
                        nop
                        inc a
                        ld bc,Label
                    .elif cond == 1
                      Label: 
                        nop
                        inc b
                        ld bc,Label
                    .elif cond == 2
                      Label: 
                        nop
                        inc c
                        ld bc,Label
                    .else
                      Label: 
                        nop
                        inc d
                        ld bc,Label
                    .endif
                .endm
                Simple()";

            CodeEmitWorks(source, 0x00, (byte)emitted, 0x01, 0x00, 0x80);
        }

        [TestMethod]
        [DataRow("0", 0x3C)]
        [DataRow("1", 0x04)]
        [DataRow("2", 0x0C)]
        [DataRow("123", 0x14)]
        public void MacroIfHandlesBranchMiddleLabels(string value, int emitted)
        {
            // --- Arrange
            var source = @"
                Simple: .macro()
                    cond = " + value + @"
                    .if cond == 0
                        nop
                        Label: inc a
                        ld bc,Label
                    .elif cond == 1
                        nop
                        Label: inc b
                        ld bc,Label
                    .elif cond == 2
                        nop
                        Label: inc c
                        ld bc,Label
                    .else
                        nop
                        Label: inc d
                        ld bc,Label
                    .endif
                .endm
                Simple()";

            CodeEmitWorks(source, 0x00, (byte)emitted, 0x01, 0x01, 0x80);
        }

        [TestMethod]
        [DataRow("0", 0x3C)]
        [DataRow("1", 0x04)]
        [DataRow("2", 0x0C)]
        [DataRow("123", 0x14)]
        public void MacroIfHandlesBranchMiddleHangingLabels(string value, int emitted)
        {
            // --- Arrange
            var source = @"
                Simple: .macro()
                    cond = " + value + @"
                    .if cond == 0
                        nop
                      Label: 
                        inc a
                        ld bc,Label
                    .elif cond == 1
                        nop
                      Label: 
                        inc b
                        ld bc,Label
                    .elif cond == 2
                        nop
                      Label: 
                        inc c
                        ld bc,Label
                    .else
                        nop
                      Label: 
                        inc d
                        ld bc,Label
                    .endif
                .endm
                Simple()";

            CodeEmitWorks(source, 0x00, (byte)emitted, 0x01, 0x01, 0x80);
        }

        [TestMethod]
        [DataRow("0", 0x3C)]
        [DataRow("1", 0x04)]
        [DataRow("2", 0x0C)]
        [DataRow("123", 0x14)]
        public void MacroIfHandlesBranchEndLabels(string value, int emitted)
        {
            // --- Arrange
            var source = @"
                Simple: .macro()
                    cond = " + value + @"
                    .if cond == 0
                        nop
                        inc a
                        Label: ld bc,Label
                    .elif cond == 1
                        nop
                        inc b
                        Label: ld bc,Label
                    .elif cond == 2
                        nop
                        inc c
                        Label: ld bc,Label
                    .else
                        nop
                        inc d
                        Label: ld bc,Label
                    .endif
                .endm
                Simple()";

            CodeEmitWorks(source, 0x00, (byte)emitted, 0x01, 0x02, 0x80);
        }

        [TestMethod]
        [DataRow("0", 0x3C)]
        [DataRow("1", 0x04)]
        [DataRow("2", 0x0C)]
        [DataRow("123", 0x14)]
        public void MacroIfHandlesBranchEndHangingLabels(string value, int emitted)
        {
            // --- Arrange
            var source = @"
                Simple: .macro()
                    cond = " + value + @"
                    .if cond == 0
                        nop
                        inc a
                      Label: 
                        ld bc,Label
                    .elif cond == 1
                        nop
                        inc b
                      Label: 
                        ld bc,Label
                    .elif cond == 2
                        nop
                        inc c
                      Label: 
                        ld bc,Label
                    .else
                        nop
                        inc d
                      Label: 
                        ld bc,Label
                    .endif
                .endm
                Simple()";

            CodeEmitWorks(source, 0x00, (byte)emitted, 0x01, 0x02, 0x80);
        }

        [TestMethod]
        public void MacroIfRecognizesLabel()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    .if true
                        value = 100
                    .else
                    .endif
                    ld hl,value
                .endm
                Simple()";

            CodeEmitWorks(SOURCE, 0x21, 0x64, 0x00);
        }

        [TestMethod]
        public void MacroIfRecognizesMissingLabel()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro()
                    .if false
                        value = 100
                    .else
                    .endif
                    ld hl,value
                .endm
                Simple()";

            CodeRaisesError(SOURCE, Errors.Z0201);
        }

        [TestMethod]
        [DataRow("0", "0", 0x00)]
        [DataRow("0", "1", 0x01)]
        [DataRow("0", "5", 0x02)]
        [DataRow("1", "0", 0x03)]
        [DataRow("1", "1", 0x04)]
        [DataRow("1", "100", 0x05)]
        [DataRow("2", "0", 0x06)]
        [DataRow("2", "1", 0x07)]
        [DataRow("2", "123", 0x08)]
        [DataRow("123", "0", 0x09)]
        [DataRow("123", "1", 0x0A)]
        [DataRow("123", "123", 0x0B)]
        public void MacroNestedIfWorks(string row, string column, int emitted)
        {
            // --- Arrange
            var source = @"
                Simple: .macro()
                    row = " + row + @"
                    col = " + column + @"
                    .if row == 0
                        .if col == 0
                            .db #00
                        .elif col == 1
                            .db #01
                        .else
                            .db #02
                        .endif
                    .elif row == 1
                        .if col == 0
                            .db #03
                        .elif col == 1
                            .db #04
                        .else
                            .db #05
                        .endif
                    .elif row == 2
                        .if col == 0
                            .db #06
                        .elif col == 1
                            .db #07
                        .else
                            .db #08
                        .endif
                    .else
                        .if col == 0
                            .db #09
                        .elif col == 1
                            .db #0A
                        .else
                            .db #0B
                        .endif
                    .endif
                .endm
                Simple()";

            CodeEmitWorks(source, (byte)emitted);
        }

        [TestMethod]
        public void UnpassedMacroArgumentsGetEmptyString()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro(arg1, arg2)
                    .if def({{arg1}})
                        ld a,b
                    .endif
                    .if def({{arg2}})
                        ld b,a
                    .endif
                .endm
                Simple()
                Simple(12)
                Simple(12, 13)
                Simple("""", 13)";

            CodeEmitWorks(SOURCE, 0x78, 0x78, 0x047, 0x47);
        }

        [TestMethod]
        public void UnpassedMacroArgumentsGetEmptyString2()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro(arg1, arg2)
                    .if def({{arg1}})
                        ld a,b
                    .endif
                    .if def({{arg2}})
                        ld b,a
                    .endif
                .endm
                Simple(, 13)
                Simple(12)";

            CodeEmitWorks(SOURCE, 0x47, 0x78);
        }

        [TestMethod]
        public void DefAcceptOnlyMacroParameter()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro(arg1, arg2)
                    .if def(arg1) ; This is en error
                        ld a,b
                    .endif
                    .if def({{arg2}})
                        ld b,a
                    .endif
                .endm";

            CodeRaisesError(SOURCE, Errors.Z0421);
        }

        [TestMethod]
        public void MacroArgCannotAcceptOtherArgument()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: 
                    .macro(arg1, arg2)
                        {{arg2}}
                    .endm
                Simple(c, ""ld a,{{arg1}}"")";

            CodeRaisesError(SOURCE, Errors.Z0422);
        }

        [TestMethod]
        public void UnpassedMacroArgumentsGetEmptyString3()
        {
            // --- Arrange
            const string SOURCE = @"
                LdBcDeHl:
                    .macro(bcVal, deVal, hlVal)
                        .if def({{bcVal}})
                            ld bc,{{bcVal}}
                        .endif
                        .if def({{deVal}})
                            ld de,{{deVal}}
                        .endif
                        .if def({{hlVal}})
                            ld hl,{{hlVal}}
                        .endif
                .endm
                LdBcDeHl(,#1000, #2000)";

            CodeEmitWorks(SOURCE, 0x11, 0x00, 0x10, 0x21, 0x00, 0x20);
        }

        [TestMethod]
        public void UnpassedMacroArgumentsGetEmptyString4()
        {
            // --- Arrange
            const string SOURCE = @"
                Simple: .macro(arg1, arg2)
                    .if def({{arg1}})
                        ld a,hreg({{arg1}})
                    .endif
                    .if def({{arg2}})
                        ld b,lreg({{arg2}})
                    .endif
                .endm
                Simple(, bc)
                Simple(bc)";

            CodeEmitWorks(SOURCE, 0x41, 0x78);
        }



        [TestMethod]
        public void MacroInMacroWorks1()
        {
            // --- Arrange
            const string SOURCE = @"
                LdHl:
                    .macro(value)
                        ld hl,{{value}}    
                    .endm

                LdHl2:
                    .macro(value1, value2)
                        LdHl({{value1}})
                        LdHl({{value2}})
                    .endm

                LdHl2(2,3)";

            CodeEmitWorks(SOURCE, 0x21, 0x02, 0x00, 0x21, 0x03, 0x00);
        }

        [TestMethod]
        public void DefFailsOutOfMacro()
        {
            // --- Arrange
            var source = @"
                ld a,def(a)";

            CodeRaisesError(source, Errors.Z0421);
        }



        [TestMethod]
        [DataRow("b", 0x78)]
        [DataRow("c", 0x79)]
        [DataRow("d", 0x7A)]
        [DataRow("e", 0x7B)]
        [DataRow("h", 0x7C)]
        [DataRow("l", 0x7D)]
        [DataRow("a", 0x7F)]
        [DataRow("bc", 0x00)]
        public void IsReg8WorksAsExpected(string param, int expected)
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isreg8({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(" + param + ")";

            CodeEmitWorks(source, (byte)expected);
        }

        [TestMethod]
        [DataRow("i", 0x57)]
        [DataRow("r", 0x5F)]
        [DataRow("bc", 0x00)]
        public void IsReg8WithSpecRegistersWorksAsExpected(string param, int expected)
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isreg8({{mpar}})
                            ld a,{{mpar}}
                        .else
                            .defb 0xED, 0x00
                        .endif
                .endm
                MyMacro(" + param + ")";

            CodeEmitWorks(source, 0xED, (byte)expected);
        }

        [TestMethod]
        [DataRow("xh", 0xDD, 0x7C)]
        [DataRow("ixh", 0xDD, 0x7C)]
        [DataRow("xl", 0xDD, 0x7D)]
        [DataRow("ixl", 0xDD, 0x7D)]
        [DataRow("yh", 0xFD, 0x7C)]
        [DataRow("iyh", 0xFD, 0x7C)]
        [DataRow("yl", 0xFD, 0x7D)]
        [DataRow("iyl", 0xFD, 0x7D)]
        [DataRow("bc", 0x00, 0x00)]
        public void IsReg8WithIndexRegistersWorksAsExpected(string param, int exp1, int exp2)
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isreg8({{mpar}})
                            ld a,{{mpar}}
                        .else
                            .defb 0x00, 0x00
                        .endif
                .endm
                MyMacro(" + param + ")";

            CodeEmitWorks(source, (byte)exp1, (byte)exp2);
        }

        [TestMethod]
        public void IsReg8FailsOutOfMacro()
        {
            // --- Arrange
            var source = @"
                ld a,isreg8(a)";

            CodeRaisesError(source, Errors.Z0421);
        }

        [TestMethod]
        [DataRow("i", 0x57)]
        [DataRow("r", 0x5F)]
        [DataRow("bc", 0x00)]
        public void IsReg8SpecWorksAsExpected(string param, int expected)
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isreg8spec({{mpar}})
                            ld a,{{mpar}}
                        .else
                            .defb 0xED, 0x00
                        .endif
                .endm
                MyMacro(" + param + ")";

            CodeEmitWorks(source, 0xED, (byte)expected);
        }

        [TestMethod]
        public void IsReg8SpecFailsOutOfMacro()
        {
            // --- Arrange
            var source = @"
                ld a,isreg8spec(a)";

            CodeRaisesError(source, Errors.Z0421);
        }

        [TestMethod]
        [DataRow("xh", 0xDD, 0x7C)]
        [DataRow("ixh", 0xDD, 0x7C)]
        [DataRow("xl", 0xDD, 0x7D)]
        [DataRow("ixl", 0xDD, 0x7D)]
        [DataRow("yh", 0xFD, 0x7C)]
        [DataRow("iyh", 0xFD, 0x7C)]
        [DataRow("yl", 0xFD, 0x7D)]
        [DataRow("iyl", 0xFD, 0x7D)]
        [DataRow("bc", 0x00, 0x00)]
        public void IsReg8IdxWorksAsExpected(string param, int exp1, int exp2)
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isreg8idx({{mpar}})
                            ld a,{{mpar}}
                        .else
                            .defb 0x00, 0x00
                        .endif
                .endm
                MyMacro(" + param + ")";

            CodeEmitWorks(source, (byte)exp1, (byte)exp2);
        }

        [TestMethod]
        public void IsReg8IdxFailsOutOfMacro()
        {
            // --- Arrange
            var source = @"
                ld a,isreg8idx(a)";

            CodeRaisesError(source, Errors.Z0421);
        }

        [TestMethod]
        [DataRow("bc", 0x01)]
        [DataRow("de", 0x11)]
        [DataRow("hl", 0x21)]
        [DataRow("sp", 0x31)]
        public void IsReg16WorksAsExpected(string param, int expected)
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isreg16({{mpar}})
                            ld {{mpar}},0x1234
                        .else
                            .defb 0xED, 0x00
                        .endif
                .endm
                MyMacro(" + param + ")";

            CodeEmitWorks(source, (byte)expected, 0x34, 0x12);
        }

        [TestMethod]
        [DataRow("ix", 0xDD, 0x21)]
        [DataRow("iy", 0xFD, 0x21)]
        [DataRow("a", 0x00, 0x00)]
        public void IsReg16WithIndexRegistersWorksAsExpected(string param, int exp1, int exp2)
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isreg16({{mpar}})
                            ld {{mpar}},0x1234
                        .else
                            .defb 0x00, 0x00, 0x34, 0x12
                        .endif
                .endm
                MyMacro(" + param + ")";

            CodeEmitWorks(source, (byte)exp1, (byte)exp2, 0x34, 0x12);
        }

        [TestMethod]
        public void IsReg16FailsOutOfMacro()
        {
            // --- Arrange
            var source = @"
                ld a,isreg16(a)";

            CodeRaisesError(source, Errors.Z0421);
        }

        [TestMethod]
        [DataRow("ix", 0xDD, 0x21)]
        [DataRow("iy", 0xFD, 0x21)]
        [DataRow("a", 0x00, 0x00)]
        public void IsReg16IdxWorksAsExpected(string param, int exp1, int exp2)
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isreg16idx({{mpar}})
                            ld {{mpar}},0x1234
                        .else
                            .defb 0x00, 0x00, 0x34, 0x12
                        .endif
                .endm
                MyMacro(" + param + ")";

            CodeEmitWorks(source, (byte)exp1, (byte)exp2, 0x34, 0x12);
        }

        [TestMethod]
        public void IsReg16IdxFailsOutOfMacro()
        {
            // --- Arrange
            var source = @"
                ld a,isreg16idx(a)";

            CodeRaisesError(source, Errors.Z0421);
        }

        [TestMethod]
        [DataRow("(bc)", 0x02)]
        [DataRow("(de)", 0x12)]
        [DataRow("(hl)", 0x77)]
        [DataRow("IX", 0x00)]
        public void IsRegIndirectWorksAsExpected(string param, int expected)
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregindirect({{mpar}})
                            ld {{mpar}},a
                        .else
                            .defb 0x00
                        .endif
                .endm
                MyMacro(" + param + ")";

            CodeEmitWorks(source, (byte)expected);
        }

        [TestMethod]
        public void IsRegIndirectFailsOutOfMacro()
        {
            // --- Arrange
            var source = @"
                ld a,isregindirect(a)";

            CodeRaisesError(source, Errors.Z0421);
        }

        [TestMethod]
        [DataRow("(c)", 0x78)]
        [DataRow("c", 0x00)]
        [DataRow("a", 0x00)]
        public void IsCPortWorksAsExpected(string param, int expected)
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if iscport({{mpar}})
                            in a,{{mpar}}
                        .else
                            .defb 0xED, 0x00
                        .endif
                .endm
                MyMacro(" + param + ")";

            CodeEmitWorks(source, 0xED, (byte)expected);
        }

        [TestMethod]
        public void IsCPortFailsOutOfMacro()
        {
            // --- Arrange
            var source = @"
                ld a,iscport(a)";

            CodeRaisesError(source, Errors.Z0421);
        }

        [TestMethod]
        [DataRow("(ix)", 0xDD, 0x77, 0x00)]
        [DataRow("(ix+2)", 0xDD, 0x77, 0x02)]
        [DataRow("(ix-2)", 0xDD, 0x77, 0xFE)]
        [DataRow("(iy)", 0xFD, 0x77, 0x00)]
        [DataRow("(iy+2)", 0xFD, 0x77, 0x02)]
        [DataRow("(iy-2)", 0xFD, 0x77, 0xFE)]
        [DataRow("a", 0x00, 0x00, 0x00)]
        public void IsIndexedAddrWorksAsExpected(string param, int exp1, int exp2, int exp3)
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isindexedaddr({{mpar}})
                            ld {{mpar}},a
                        .else
                            .defb 0x00, 0x00, 0x00
                        .endif
                .endm
                MyMacro(" + param + ")";

            CodeEmitWorks(source, (byte)exp1, (byte)exp2, (byte)exp3);
        }

        [TestMethod]
        public void IsIndexedAddrFailsOutOfMacro()
        {
            // --- Arrange
            var source = @"
                ld a,isindexedaddr(a)";

            CodeRaisesError(source, Errors.Z0421);
        }

        [TestMethod]
        [DataRow("nz", 0xC2)]
        [DataRow("z", 0xCA)]
        [DataRow("nc", 0xD2)]
        [DataRow("c", 0xDA)]
        [DataRow("po", 0xE2)]
        [DataRow("pe", 0xEA)]
        [DataRow("p", 0xF2)]
        [DataRow("m", 0xFA)]
        [DataRow("a", 0x00)]
        public void IsConditionWorksAsExpected(string param, int expexted)
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if iscondition({{mpar}})
                            jp {{mpar}},#1234
                        .else
                            .defb 0x00, 0x34, 0x12
                        .endif
                .endm
                MyMacro(" + param + ")";

            CodeEmitWorks(source, (byte)expexted, 0x34, 0x12);
        }

        [TestMethod]
        public void IsConditionFailsOutOfMacro()
        {
            // --- Arrange
            var source = @"
                ld a,iscondition(a)";

            CodeRaisesError(source, Errors.Z0421);
        }

        [TestMethod]
        [DataRow("1 * 3", 0x03)]
        [DataRow("1 << 2", 0x04)]
        [DataRow("#10", 0x10)]
        [DataRow("a", 0x00)]
        public void IsExprWorksAsExpected(string param, int expexted)
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isexpr({{mpar}})
                            ld a,{{mpar}}
                        .else
                            .defb 0x3E, 0x00
                        .endif
                .endm
                MyMacro(" + param + ")";

            CodeEmitWorks(source, 0x3E, (byte)expexted);
        }

        [TestMethod]
        public void IsExprFailsOutOfMacro()
        {
            // --- Arrange
            var source = @"
                ld a,isexpr(a)";

            CodeRaisesError(source, Errors.Z0421);
        }

        [TestMethod]
        public void IsRegAWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isrega({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(a)";

            CodeEmitWorks(source, (byte)0x7F);
        }

        [TestMethod]
        public void IsRegAFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isrega({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegBWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregb({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(b)";

            CodeEmitWorks(source, (byte)0x78);
        }

        [TestMethod]
        public void IsRegBFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregb({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegCWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregc({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(c)";

            CodeEmitWorks(source, (byte)0x79);
        }

        [TestMethod]
        public void IsRegCFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregc({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegDWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregd({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(d)";

            CodeEmitWorks(source, (byte)0x7a);
        }

        [TestMethod]
        public void IsRegDFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregd({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegEWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isrege({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(e)";

            CodeEmitWorks(source, (byte)0x7b);
        }

        [TestMethod]
        public void IsRegEFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isrege({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegHWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregh({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(h)";

            CodeEmitWorks(source, (byte)0x7c);
        }

        [TestMethod]
        public void IsRegHFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregh({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegLWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregl({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(l)";

            CodeEmitWorks(source, (byte)0x7d);
        }

        [TestMethod]
        public void IsRegLFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregl({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegIWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregi({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(i)";

            CodeEmitWorks(source, (byte)0xed, (byte)0x57);
        }

        [TestMethod]
        public void IsRegIFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregi({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegRWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregr({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(r)";

            CodeEmitWorks(source, (byte)0xed, (byte)0x5f);
        }

        [TestMethod]
        public void IsRegRFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregr({{mpar}})
                            ld a,{{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegBCWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregbc({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(bc)";

            CodeEmitWorks(source, (byte)0x03);
        }

        [TestMethod]
        public void IsRegBCFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregbc({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegDEWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregde({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(de)";

            CodeEmitWorks(source, (byte)0x13);
        }

        [TestMethod]
        public void IsRegDEFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregde({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegHLWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isreghl({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(hl)";

            CodeEmitWorks(source, (byte)0x23);
        }

        [TestMethod]
        public void IsRegHLFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isreghl({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegXHWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregxh({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(xh)";

            CodeEmitWorks(source, (byte)0xdd, (byte)0x24);
        }

        [TestMethod]
        public void IsRegXHFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregxh({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegXLWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregxl({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(xl)";

            CodeEmitWorks(source, (byte)0xdd, (byte)0x2c);
        }

        [TestMethod]
        public void IsRegXLFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregxl({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegYHWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregyh({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(yh)";

            CodeEmitWorks(source, (byte)0xfd, (byte)0x24);
        }

        [TestMethod]
        public void IsRegYHFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregyh({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegYLWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregyl({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(yl)";

            CodeEmitWorks(source, (byte)0xfd, (byte)0x2c);
        }

        [TestMethod]
        public void IsRegYLFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregyl({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegIXHWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregxh({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(ixh)";

            CodeEmitWorks(source, (byte)0xdd, (byte)0x24);
        }

        [TestMethod]
        public void IsRegIXLWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregxl({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(ixl)";

            CodeEmitWorks(source, (byte)0xdd, (byte)0x2c);
        }

        [TestMethod]
        public void IsRegIYHWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregyh({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(iyh)";

            CodeEmitWorks(source, (byte)0xfd, (byte)0x24);
        }

        [TestMethod]
        public void IsRegIYLWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregyl({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(yl)";

            CodeEmitWorks(source, (byte)0xfd, (byte)0x2c);
        }

        [TestMethod]
        public void IsRegIXWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregix({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(ix)";

            CodeEmitWorks(source, (byte)0xdd, (byte)0x23);
        }

        [TestMethod]
        public void IsRegIXFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregix({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegIYWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregiy({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(iy)";

            CodeEmitWorks(source, (byte)0xfd, (byte)0x23);
        }

        [TestMethod]
        public void IsRegIYFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregiy({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegSPWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregsp({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x33);
        }

        [TestMethod]
        public void IsRegSPFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregsp({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(af)";

            CodeEmitWorks(source, (byte)0x00);
        }

        [TestMethod]
        public void IsRegAFWorksAsExpected()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregaf({{mpar}})
                            push {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(af)";

            CodeEmitWorks(source, (byte)0xf5);
        }

        [TestMethod]
        public void IsRegAFFails()
        {
            // --- Arrange
            var source = @"
                MyMacro:
                    .macro(mpar)
                        .if isregaf({{mpar}})
                            inc {{mpar}}
                        .else
                            nop
                        .endif
                .endm
                MyMacro(sp)";

            CodeEmitWorks(source, (byte)0x00);
        }

    }
}


<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/ToolWindows/SpectrumEmulator/SpectrumDisplayControl.xaml.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Spect.Net.SpectrumEmu.Abstraction.Devices.Screen;
using Spect.Net.SpectrumEmu.Abstraction.Devices.Tape;
using Spect.Net.SpectrumEmu.Devices.Screen;
using Spect.Net.SpectrumEmu.Machine;
using Spect.Net.VsPackage.SolutionItems;

#pragma warning disable VSTHRD010

namespace Spect.Net.VsPackage.ToolWindows.SpectrumEmulator
{
    /// <summary>
    /// This control is responsible to display the bitmap that represents the
    /// ZX Spectrum screen. It also responds to the virtual machine state changes 
    /// and other VM-related events.
    /// </summary>
    /// <remarks>
    /// Most of the logic is implemented within the MachineViewModel held by
    /// a control instance. In order to display and run the VM, you should set up 
    /// the properties of MachineViewModel before instantiating this control.
    /// </remarks>
    public partial class SpectrumDisplayControl
    {
        private const string FILE_EXISTS_MESSAGE = "The exported tape file exists in the project. " +
                                                   "Would you like to override it?";

        private const string INVALID_FOLDER_MESSAGE = "The tape folder specified in the Options dialog " +
                                                      "contains invalid characters or an absolute path. Go to the Options dialog and " +
                                                      "fix the issue so that you can add the tape file to the project.";

        private ScreenConfiguration _displayPars;
        private WriteableBitmap _bitmap;
        private bool _isReloaded;
        private byte[] _lastBuffer;
        private byte[] _savedBuffer;
        private int _cpuFrameCount;
        private uint[] _colors;
        private CancellationTokenSource _cancellationSource;
        private Task _shadowRenderingTask;
        private bool _justPaused = false;

        /// <summary>
        /// The ZX Spectrum virtual machine view model utilized by this user control
        /// </summary>
        public EmulatorViewModel Vm { get; set; }

        /// <summary>
        /// Provides keyboard input for the ZX Spectrum virtual machine
        /// </summary>
        public KeyboardScanner KeyboardScanner { get; }

        /// <summary>
        /// Initialize the control and sign that the next Loaded event will be the first one.
        /// </summary>
        public SpectrumDisplayControl()
        {
            InitializeComponent();
            KeyboardScanner = new KeyboardScanner();
            _isReloaded = false;
            _lastBuffer = null;
        }


        /// <summary>
        /// Resizes the Spectrum screen according to the specified parent area size
        /// </summary>
        public void ResizeFor(double width, double height)
        {
            if (Vm == null) return;

            var widthFactor = (int)(width / _displayPars.ScreenWidth);
            var heightFactor = (int)height / _displayPars.ScreenLines;
            var scale = Math.Min(widthFactor, heightFactor);
            if (scale < 1) scale = 1;

            Display.Width = _displayPars.ScreenWidth * scale;
            Display.Height = _displayPars.ScreenLines * scale;
        }

        /// <summary>
        /// Forces the refresh of the ZX Spectrum screen
        /// </summary>
        public void ForceRefresh()
        {
            Dispatcher.Invoke(async () =>
            {
                await Task.Delay(50);
                MachineOnRenderFrameCompleted(this,
                    new RenderFrameEventArgs(Vm.Machine.SpectrumVm.ScreenDevice.GetPixelBuffer()));
            });
        }

        /// <summary>
        /// Initialize the Spectrum virtual machine dependencies when the user control is loaded
        /// </summary>
        private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
        {
            Vm = DataContext as EmulatorViewModel;
            if (Vm == null) return;

            // --- Prepare the screen
            _colors = Spectrum48ScreenDevice.SpectrumColors.ToArray();
            _displayPars = Vm.Machine.ScreenConfiguration;
            _bitmap = new WriteableBitmap(
                _displayPars.ScreenWidth,
                _displayPars.ScreenLines,
                96,
                96,
                PixelFormats.Bgr32,
                null);
            Display.Source = _bitmap;
            Display.Width = _displayPars.ScreenWidth;
            Display.Height = _displayPars.ScreenLines;
            Display.Stretch = Stretch.Fill;

            // --- When the control is reloaded, resume playing the sound
            if (_isReloaded && Vm.MachineState == VmState.Running)
            {
                Vm.Machine.BeeperProvider?.PlaySound();
                Vm.Machine.SoundProvider?.PlaySound();
            }

            // --- Keyboard event handling
            KeyboardScanner.BindShiftChange();

            // --- Register messages this control listens to
            Vm.VmStateChanged += OnVmStateChanged;
            Vm.KeyScanning += MachineOnKeyScanning;
            Vm.CpuFrameCompleted += MachineOnCpuFrameCompleted;
            Vm.RenderFrameCompleted += MachineOnRenderFrameCompleted;
            Vm.LeftSaveMode += MachineOnLeftSaveMode;
            Vm.ShadowScreenModeChanged += OnShadowScreenModeChanged;
            Vm.UlaIndicationModeChanged += OnUlaIndicationModeChanged;
            Vm.MachineInstanceChanged += OnMachineInstanceChanged;
        }

        /// <summary>
        /// Cleanup when the user control is unloaded
        /// </summary>
        private void OnUnloaded(object sender, RoutedEventArgs e)
        {
            // --- Keyboard event handling
            KeyboardScanner.ReleaseShiftChange();

            // --- Un-register messages this control listens to
            if (Vm != null)
            {
                Vm.Machine.BeeperProvider?.KillSound();
                Vm.Machine.SoundProvider?.KillSound();
                Vm.Machine.VmStateChanged -= OnVmStateChanged;
                Vm.KeyScanning -= MachineOnKeyScanning;
                Vm.CpuFrameCompleted -= MachineOnCpuFrameCompleted;
                Vm.RenderFrameCompleted -= MachineOnRenderFrameCompleted;
                Vm.LeftSaveMode -= MachineOnLeftSaveMode;
                Vm.ShadowScreenModeChanged -= OnShadowScreenModeChanged;
                Vm.UlaIndicationModeChanged += OnUlaIndicationModeChanged;
                Vm.MachineInstanceChanged -= OnMachineInstanceChanged;
            }

            // --- Sign that the next time we load the control, it is a reload
            _isReloaded = true;
        }

        /// <summary>
        /// Respond to the state changes of the Spectrum virtual machine
        /// </summary>
        private void OnVmStateChanged(object sender, VmStateChangedEventArgs args)
        {
            Dispatcher.Invoke(() =>
                {
                    switch (args.NewState)
                    {
                        case VmState.Stopped:
                            Vm.Machine.BeeperProvider?.KillSound();
                            Vm.Machine.SoundProvider?.KillSound();
                            Vm.FastLoadCompleted -= OnFastLoadCompleted;
                            ShowUlaRaster();
                            break;
                        case VmState.Running:
                            Vm.FastLoadCompleted += OnFastLoadCompleted;
                            ShowUlaRaster();
                            StopShadowScreenRendering();
                            break;
                        case VmState.Paused:
                            Vm.Machine.BeeperProvider?.KillSound();
                            Vm.Machine.SoundProvider?.KillSound();
                            _justPaused = true;
                            MachineOnRenderFrameCompleted(this,
                                new RenderFrameEventArgs(Vm.Machine.SpectrumVm.ScreenDevice.GetPixelBuffer()));
                            StartShadowScreenRendering();
                            ShowUlaRaster();
                            break;
                    }
                },
                DispatcherPriority.Send);
        }

        /// <summary>
        /// Scans the keyboard at every 25th CPU frame cycle
        /// </summary>
        private void MachineOnKeyScanning(object sender, KeyStatusEventArgs e)
        {
            if (_cpuFrameCount++ % 25 == 0)
            {
                e.KeyStatusList.AddRange(KeyboardScanner.Scan());
            }
        }

        private void MachineOnCpuFrameCompleted(object sender, CancelEventArgs e)
        {
            // ReSharper disable once ExplicitCallerInfoArgument
            Vm.RaisePropertyChanged("Machine");
        }

        /// <summary>
        /// Takes care of refreshing the screen
        /// </summary>
        private void MachineOnRenderFrameCompleted(object sender, RenderFrameEventArgs e)
        {
            // --- Refresh the screen
            Dispatcher.Invoke(() =>
                {
                    _lastBuffer = e.ScreenPixels;
                    RefreshSpectrumScreen(_lastBuffer);
                    if (!_justPaused)
                    {
                        Vm.Machine.BeeperProvider?.PlaySound();
                        Vm.Machine.SoundProvider?.PlaySound();
                    }
                    _justPaused = false;
                },
                DispatcherPriority.Send
            );
        }

        /// <summary>
        /// It is time to restart playing the sound
        /// </summary>
        private void OnFastLoadCompleted(object sender, EventArgs e)
        {
            Dispatcher.Invoke(() =>
            {
                Vm.Machine.BeeperProvider?.PlaySound();
                Vm.Machine.SoundProvider?.PlaySound();
            });
        }

        /// <summary>
        /// The virtual machine has just saved a file.
        /// </summary>
        private void MachineOnLeftSaveMode(object sender, SaveModeEventArgs e)
        {
            Dispatcher.Invoke(() =>
                {
                    SpectrumProject.AddFileToProject(
                        SpectNetPackage.Default.Options.TapeFolder,
                        e.FileName,
                        INVALID_FOLDER_MESSAGE,
                        FILE_EXISTS_MESSAGE);
                });
        }

        /// <summary>
        /// Respond to the change of shadow screen mode
        /// </summary>
        private void OnShadowScreenModeChanged(object sender, EventArgs e)
        {
            if (Vm.MachineState != VmState.Paused) return;
            if (Vm.ShadowScreenEnabled)
            {
                StartShadowScreenRendering();
            }
            else
            {
                StopShadowScreenRendering();
            }
        }

        /// <summary>
        /// Responds to the change of ULA indication mode
        /// </summary>
        private void OnUlaIndicationModeChanged(object sender, EventArgs e)
        {
            ShowUlaRaster();
        }

        /// <summary>
        /// Responds to the event when machine instance changes.
        /// </summary>
        private void OnMachineInstanceChanged(object sender, MachineInstanceChangedEventArgs e)
        {
            Dispatcher.Invoke(() =>
                {
                    _lastBuffer = e.NewMachine.ScreenBitmap.GetPixelBuffer();
                    RefreshSpectrumScreen(_lastBuffer);
                },
                DispatcherPriority.Send
            );
        }


        /// <summary>
        /// Refreshes the spectrum screen
        /// </summary>
        private void RefreshSpectrumScreen(IReadOnlyList<byte> currentBuffer)
        {
            var width = _displayPars.ScreenWidth;
            var height = _displayPars.ScreenLines;

            _bitmap.Lock();
            try
            {
                unsafe
                {
                    var stride = _bitmap.BackBufferStride;
                    // Get a pointer to the back buffer.
                    var pBackBuffer = (int) _bitmap.BackBuffer;

                    for (var x = 0; x < width; x++)
                    {
                        for (var y = 0; y < height; y++)
                        {
                            var addr = pBackBuffer + y * stride + x * 4;
                            var pixelData = currentBuffer[y * width + x];
                            *(uint*) addr = _colors[pixelData & 0x0F];
                        }
                    }
                }

                _bitmap.AddDirtyRect(new Int32Rect(0, 0, width, height));
            }
            finally
            {
                _bitmap.Unlock();
            }
        }

        private void OnSizeChanged(object sender, SizeChangedEventArgs e)
        {
            if (Vm == null) return;
            ResizeFor(e.NewSize.Width, e.NewSize.Height);
            ShowUlaRaster();
        }

        private void OnLayoutUpdated(object sender, EventArgs e)
        {
            if (Vm == null) return;
            ResizeFor(ActualWidth, ActualHeight);
            ShowUlaRaster();
        }

        /// <summary>
        /// Starts rendering the shadow screen, provided it is turned on
        /// </summary>
        private async void StartShadowScreenRendering()
        {
            if (!Vm.ShadowScreenEnabled || _shadowRenderingTask != null || _cancellationSource != null) return;
            _savedBuffer = _lastBuffer.ToArray();
            _cancellationSource = new CancellationTokenSource();
            _shadowRenderingTask = Vm.Machine.RenderShadowScreen(_cancellationSource.Token);
            try
            {
                await _shadowRenderingTask;
            }
            catch
            {
                // --- This exception is intentionally ignored
            }
            _shadowRenderingTask = null;
        }

        /// <summary>
        /// Stops rendering the shadow screen
        /// </summary>
        private async void StopShadowScreenRendering()
        {
            if (_cancellationSource == null) return;
            _cancellationSource.Cancel();
            _cancellationSource = null;
            var tmpTask = _shadowRenderingTask;
            _shadowRenderingTask = null;
            try
            {
                await tmpTask;
            }
            catch
            {
                // --- This exception is intentionally ignored
            }
            Dispatcher.Invoke(() =>
                {
                    _lastBuffer = _savedBuffer.ToArray();
                    RefreshSpectrumScreen(_lastBuffer);
                },
                DispatcherPriority.Send
            );
        }

        private void ShowUlaRaster()
        {
            if (Vm.MachineState != VmState.Paused || !Vm.UlaIndicationEnabled)
            {
                // --- Hide ULA raster information
                RasterLine.Visibility = Visibility.Collapsed;
                PixelLine.Visibility = Visibility.Collapsed;
                SyncRectangle.Visibility = Visibility.Collapsed;
                NonVisibleRectangle.Visibility = Visibility.Collapsed;
                DisplayRectangle.Visibility = Visibility.Collapsed;
                BeamRectangle.Visibility = Visibility.Collapsed;
                return;
            }

            // --- Display ULA raster information
            var sc = Vm.Machine.ScreenConfiguration;
            var screenLines = sc.ScreenLines;
            var scale = Display.ActualHeight / screenLines;
            var ulaTacts = sc.ScreenRenderingFrameTactCount;
            var tact = Vm.Machine.CurrentFrameTact % ulaTacts;
            var line = tact / sc.ScreenLineTime;
            var pixel = tact % sc.ScreenLineTime * 2;
            var screenWidth = sc.ScreenLineTime * 2;

            RasterLine.X1 = (ActualWidth - Display.ActualWidth) / 2;
            RasterLine.X2 = RasterLine.X1 + screenWidth * scale;
            RasterLine.Y1 = RasterLine.Y2 = (ActualHeight - Display.ActualHeight) / 2 
            + (line - sc.NonVisibleBorderTopLines) * scale;
            RasterLine.StrokeThickness = scale;

            PixelLine.X1 = PixelLine.X2 = (ActualWidth - Display.ActualWidth) / 2 + pixel * scale;
            PixelLine.Y1 = RasterLine.Y1 - 4 * scale;
            PixelLine.Y2 = RasterLine.Y1 + 4 * scale;
            PixelLine.StrokeThickness = 2 * scale;

            BeamRectangle.Margin = new Thickness(
                (ActualWidth - Display.ActualWidth) / 2 + (pixel - 3) * scale,
                (ActualHeight - Display.ActualHeight) / 2 + (line - sc.NonVisibleBorderTopLines - 3) * scale,
                0,0);
            BeamRectangle.Width = BeamRectangle.Height = 6 * scale;
            BeamPosition.Text = $"({line}, {pixel / 2})";

            SyncRectangle.Margin = new Thickness(
                (ActualWidth - Display.ActualWidth) / 2,
                (ActualHeight - Display.ActualHeight) / 2
                - sc.NonVisibleBorderTopLines * scale, 4, 4);
            SyncRectangle.Width = screenWidth * scale;
            SyncRectangle.Height = sc.RasterLines * scale;

            NonVisibleRectangle.Margin = SyncRectangle.Margin;
            NonVisibleRectangle.Width = SyncRectangle.Width - sc.NonVisibleBorderRightTime * 2 * scale;
            NonVisibleRectangle.Height = SyncRectangle.Height - sc.NonVisibleBorderBottomLines * scale;

            DisplayRectangle.Margin = new Thickness(
                (ActualWidth - Display.ActualWidth) / 2 + sc.BorderLeftPixels * scale,
                (ActualHeight - Display.ActualHeight) / 2 + sc.BorderTopLines * scale, 0, 0);
            DisplayRectangle.Width = sc.DisplayWidth * scale;
            DisplayRectangle.Height = sc.DisplayLines * scale;

            RasterLine.Visibility = Visibility.Visible;
            PixelLine.Visibility = Visibility.Visible;
            SyncRectangle.Visibility = Visibility.Visible;
            NonVisibleRectangle.Visibility = Visibility.Visible;
            DisplayRectangle.Visibility = Visibility.Visible;
            BeamRectangle.Visibility = Visibility.Visible;
        }
    }
}


<|start_filename|>v2/Assembler/Spect.Net.Assembler/Z80AsmVisitor.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using Antlr4.Runtime;
using Antlr4.Runtime.Misc;
using Antlr4.Runtime.Tree;
using Spect.Net.Assembler.Assembler;
using Spect.Net.Assembler.Generated;
using Spect.Net.Assembler.SyntaxTree;
using Spect.Net.Assembler.SyntaxTree.Expressions;
using Spect.Net.Assembler.SyntaxTree.Operations;
using Spect.Net.Assembler.SyntaxTree.Pragmas;
using Spect.Net.Assembler.SyntaxTree.Statements;
// ReSharper disable StringLiteralTypo

namespace Spect.Net.Assembler
{
    /// <summary>
    /// This visitor class processes the elements of the AST parsed by ANTLR
    /// </summary>
    public class Z80AsmVisitor : Z80AsmBaseVisitor<object>, IZ80AsmVisitorContext
    {
        /// <summary>
        /// Visits the source code
        /// </summary>
        /// <param name="source">Source code string</param>
        /// <returns>Source code visitor object</returns>
        public static Z80AsmVisitor VisitSource(string source)
        {
            var inputStream = new AntlrInputStream(source);
            var lexer = new Z80AsmLexer(inputStream);
            var tokenStream = new CommonTokenStream(lexer);
            var parser = new Z80AsmParser(tokenStream);
            var context = parser.compileUnit();
            var visitor = new Z80AsmVisitor(inputStream);
            visitor.Visit(context);
            return visitor;
        }

        /// <summary>
        /// Gets the index of the compilation line index from the compilation
        /// </summary>
        /// <param name="lines">Compilation lines</param>
        /// <param name="lineNo">The source code's line number</param>
        /// <returns>Compilation line index</returns>
        public static int? GetAsmLineIndex(List<SourceLineBase> lines, int lineNo)
        {
            var lower = 0;
            var upper = lines.Count - 1;
            while (lower <= upper)
            {
                var idx = (lower + upper) / 2;
                var sourceLineNo = lines[idx].SourceLine;
                if (sourceLineNo == lineNo)
                {
                    return idx;
                }
                if (sourceLineNo > lineNo)
                {
                    upper = idx - 1;
                }
                else
                {
                    lower = idx + 1;
                }
            }
            return null;
        }

        /// <summary>
        /// Instantiates a visitor object
        /// </summary>
        /// <param name="inputStream">Input stream to parse</param>
        public Z80AsmVisitor(AntlrInputStream inputStream)
        {
            InputStream = inputStream;
        }

        #region IZ80AsmVisitorState implementation

        /// <summary>
        /// The input stream used by the parser
        /// </summary>
        public AntlrInputStream InputStream { get; }

        /// <summary>
        /// Source code text of the line being processed
        /// </summary>
        public string CurrentSourceText { get; set; }

        /// <summary>
        /// Source line number
        /// </summary>
        public int CurrentSourceLine { get; set; }

        /// <summary>
        /// Source index of the first column
        /// </summary>
        public int FirstColumn { get; set; }

        /// <summary>
        /// Last position of the processed instruction
        /// </summary>
        public int LastInstructionPos { get; set; }

        /// <summary>
        /// Source index of the beginning of the current line
        /// </summary>
        public int FirstPosition { get; set; }

        /// <summary>
        /// Source index of the beginning of the current line
        /// </summary>
        public int LastPosition { get; set; }

        /// <summary>
        /// The current label
        /// </summary>
        public string CurrentLabel { get; set; }

        /// <summary>
        /// Indicates if the current label has a colon
        /// </summary>
        public bool CurrentLabelColon { get; set; }

        /// <summary>
        /// The current comment
        /// </summary>
        public string CurrentComment { get; set; }

        /// <summary>
        /// The issue to emit when the line has been visited
        /// </summary>
        public string IssueToEmit { get; set; }

        /// <summary>
        /// Indicates if the current pragma is in a field assignment
        /// </summary>
        public bool IsFieldAssignment { get; set; }

        /// <summary>
        /// The macro parameter names within the current line
        /// </summary>
        public List<string> MacroParamNames { get; set; }

        /// <summary>
        /// The text span of the current label
        /// </summary>
        public TextSpan LabelSpan { get; set; }

        /// <summary>
        /// The text span of the current keyword
        /// </summary>
        public TextSpan KeywordSpan { get; set; }

        /// <summary>
        /// The text span of the current comment
        /// </summary>
        public TextSpan CommentSpan { get; set; }

        /// <summary>
        /// Number text spans in the current line
        /// </summary>
        public List<TextSpan> NumberSpans { get; set; }

        /// <summary>
        /// Identifier text spans in the current line
        /// </summary>
        public List<TextSpan> IdentifierSpans { get; set; }

        /// <summary>
        /// String text spans in the current line
        /// </summary>
        public List<TextSpan> StringSpans { get; set; }

        /// <summary>
        /// Semi variable text spans in the current line
        /// </summary>
        public List<TextSpan> SemiVarSpans { get; set; }

        /// <summary>
        /// Function text spans in the current line
        /// </summary>
        public List<TextSpan> FunctionSpans { get; set; }

        /// <summary>
        /// Macro parameter text spans in the current line
        /// </summary>
        public List<TextSpan> MacroParamSpans { get; set; }

        /// <summary>
        /// Statement text spans in the current line
        /// </summary>
        public List<TextSpan> StatementSpans { get; set; }

        /// <summary>
        /// Operand text spans in the current line
        /// </summary>
        public List<TextSpan> OperandSpans { get; set; }

        /// <summary>
        /// Mnemonic text spans in the current line
        /// </summary>
        public List<TextSpan> MnemonicSpans { get; set; }

        /// <summary>
        /// Adds a new number text span
        /// </summary>
        public void AddNumber(ParserRuleContext context)
        {
            if (NumberSpans == null) NumberSpans = new List<TextSpan>();
            NumberSpans.Add(new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1));
        }

        /// <summary>
        /// Adds a new string text span
        /// </summary>
        public void AddString(ParserRuleContext context)
        {
            if (StringSpans == null) StringSpans = new List<TextSpan>();
            StringSpans.Add(new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1));
        }

        /// <summary>
        /// Adds a new string text span
        /// </summary>
        public void AddString(ITerminalNode node)
        {
            if (StringSpans == null) StringSpans = new List<TextSpan>();
            StringSpans.Add(new TextSpan(node.Symbol.StartIndex, node.Symbol.StopIndex + 1));
        }

        /// <summary>
        /// Adds a new identifier text span
        /// </summary>
        public void AddIdentifier(ParserRuleContext context)
        {
            if (IdentifierSpans == null) IdentifierSpans = new List<TextSpan>();
            IdentifierSpans.Add(new TextSpan(context.Start.StartIndex, context.Stop.StopIndex + 1));
        }

        /// <summary>
        /// Adds a new identifier text span
        /// </summary>
        public void AddIdentifier(ITerminalNode node)
        {
            if (IdentifierSpans == null) IdentifierSpans = new List<TextSpan>();
            IdentifierSpans.Add(new TextSpan(node.Symbol.StartIndex, node.Symbol.StopIndex + 1));
        }

        /// <summary>
        /// Adds a new statement text span
        /// </summary>
        public void AddStatement(ITerminalNode node)
        {
            if (StatementSpans == null) StatementSpans = new List<TextSpan>();
            StatementSpans.Add(new TextSpan(node.Symbol.StartIndex, node.Symbol.StopIndex + 1));
        }

        /// <summary>
        /// Adds a new function text span
        /// </summary>
        public void AddFunction(ParserRuleContext context)
        {
            if (FunctionSpans == null) FunctionSpans = new List<TextSpan>();
            FunctionSpans.Add(new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1));
        }

        /// <summary>
        /// Adds a new semi-variable text span
        /// </summary>
        public void AddSemiVar(ParserRuleContext context)
        {
            if (SemiVarSpans == null) SemiVarSpans = new List<TextSpan>();
            SemiVarSpans.Add(new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1));
        }

        /// <summary>
        /// Adds a new semi-variable text span
        /// </summary>
        public void AddMacroParam(ParserRuleContext context)
        {
            if (MacroParamSpans == null) MacroParamSpans = new List<TextSpan>();
            MacroParamSpans.Add(new TextSpan(context.Start.StartIndex, context.Stop.StopIndex + 1));
        }

        /// <summary>
        /// Adds a new semi-variable text span
        /// </summary>
        public void AddMacroParamName(string name)
        {
            if (MacroParamNames == null) MacroParamNames = new List<string>();
            MacroParamNames.Add(name);
        }

        /// <summary>
        /// Adds a new operand text span
        /// </summary>
        public void AddOperand(ParserRuleContext context)
        {
            if (OperandSpans == null) OperandSpans = new List<TextSpan>();
            OperandSpans.Add(new TextSpan(context.Start.StartIndex, context.Stop.StopIndex + 1));
        }

        /// <summary>
        /// Adds a new operand text span
        /// </summary>
        public void AddOperand(ITerminalNode node)
        {
            if (OperandSpans == null) OperandSpans = new List<TextSpan>();
            OperandSpans.Add(new TextSpan(node.Symbol.StartIndex, node.Symbol.StopIndex + 1));
        }

        /// <summary>
        /// Adds a new operand text span
        /// </summary>
        public void AddMnemonics(ParserRuleContext context)
        {
            if (MnemonicSpans == null) MnemonicSpans = new List<TextSpan>();
            MnemonicSpans.Add(new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1));
        }

        /// <summary>
        /// Gets an expression from the specified context
        /// </summary>
        /// <param name="context">Context to get the expression from</param>
        /// <returns>Node that represents the expression</returns>
        public ExpressionNode GetExpression(IParseTree context)
        {
            return (ExpressionNode) VisitExpr(context as Z80AsmParser.ExprContext);
        }

        /// <summary>
        /// Gets an operand from the specified context
        /// </summary>
        /// <param name="context">Context to get the operand from</param>
        /// <returns>Node that represents the operand</returns>
        public Operand GetOperand(Z80AsmParser.OperandContext context)
        {
            return (Operand) VisitOperand(context);
        }

        #endregion

        /// <summary>
        /// Access the compilation results through this object
        /// </summary>
        public CompilationUnit Compilation { get; } = new CompilationUnit();

        /// <summary>
        /// The last assembly line parsed
        /// </summary>
        public object LastAsmLine { get; private set; }

        /// <summary>
        /// This flag indicates that the parses now works on parsing a macro
        /// </summary>
        public bool MacroParsingPhase { get; set; }

        #region Z80 Assembly line

        public override object VisitAsmline(Z80AsmParser.AsmlineContext context)
        {
            CurrentLabel = null;
            CurrentLabelColon = false;
            CurrentComment = null;
            LabelSpan = null;
            KeywordSpan = null;
            CommentSpan = null;
            IssueToEmit = null;
            IsFieldAssignment = false;
            NumberSpans = null;
            IdentifierSpans = null;
            StringSpans = null;
            FunctionSpans = null;
            SemiVarSpans = null;
            MacroParamSpans = null;
            MacroParamNames = null;
            SemiVarSpans = null;
            StatementSpans = null;
            OperandSpans = null;
            MnemonicSpans = null;

            if (context?.Start == null || context.Stop == null)
            {
                return null;
            }

            var startIndex = context.start.StartIndex;
            var stopIndex = context.stop.StopIndex;
            CurrentSourceText = InputStream.GetText(new Interval(startIndex, stopIndex));

            CurrentSourceLine = context.Start.Line;
            FirstColumn = context.Start.Column;
            FirstPosition = context.Start.StartIndex;
            LastPosition = context.Stop.StopIndex;

            object mainInstructionPart = null;

            // --- Obtain label
            var labelCtx = context.label();
            if (labelCtx != null)
            {
                CurrentLabel = labelCtx.GetChild(0).GetText();
                CurrentLabelColon = labelCtx.COLON() != null;
                LabelSpan = new TextSpan(labelCtx.Start.StartIndex, labelCtx.Start.StopIndex + 1);
            }

            // --- Obtain line body/directive
            var lineBodyCtx = context.lineBody();
            if (lineBodyCtx != null)
            {
                // --- Special case, when a macro parameters is used as the main line
                LastInstructionPos = lineBodyCtx.Stop.StopIndex;
                var macroParamCtx = lineBodyCtx.macroParam();
                if (macroParamCtx != null)
                {
                    VisitMacroParam(macroParamCtx);
                    mainInstructionPart = new MacroParamLine(macroParamCtx.IDENTIFIER()?.GetText());
                }
                else
                {
                    mainInstructionPart = VisitLineBody(context.lineBody());
                }
            }
            else if (context.directive() != null)
            {
                mainInstructionPart = VisitDirective(context.directive());
            }

            // --- Obtain comment
            if (context.comment() != null)
            {
                var commentCtx = context.comment(); 
                CurrentComment = commentCtx.GetText();
                CommentSpan = new TextSpan(commentCtx.Start.StartIndex, commentCtx.Stop.StopIndex + 1);
            }

            // --- Now, we have every part of the line, and create some special main instruction part
            if (context.exception != null)
            {
                mainInstructionPart = new ParserErrorLine();
            }
            else if (mainInstructionPart == null && (CurrentLabel != null || CurrentComment != null))
            {
                mainInstructionPart = new NoInstructionLine();
                if (CurrentLabel != null && !CurrentLabelColon)
                {
                    var statementFound = true;
                    switch (CurrentLabel.ToLower())
                    {
                        case "continue":
                            mainInstructionPart = new ContinueStatement();
                            break;
                        case "break":
                            mainInstructionPart = new BreakStatement();
                            break;
                        case "endm":
                        case "mend":
                            mainInstructionPart = new MacroEndStatement();
                            break;
                        case "endl":
                        case "lend":
                            mainInstructionPart = new LoopEndStatement();
                            break;
                        case "proc":
                            mainInstructionPart = new ProcStatement();
                            break;
                        case "endp":
                        case "pend":
                            mainInstructionPart = new ProcEndStatement();
                            break;
                        case "repeat":
                            mainInstructionPart = new RepeatStatement();
                            break;
                        case "endw":
                        case "wend":
                            mainInstructionPart = new WhileEndStatement();
                            break;
                        case "ends":
                            mainInstructionPart = new StructEndStatement();
                            break;
                        case "else":
                            mainInstructionPart = new ElseStatement();
                            break;
                        case "endif":
                            mainInstructionPart = new IfEndStatement();
                            break;

                        default:
                            statementFound = false;
                            break;
                    }

                    if (statementFound)
                    {
                        KeywordSpan = new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1);
                        CurrentLabel = null;
                    }
                }
            }

            return mainInstructionPart is SourceLineBase sourceLine
                ? AddLine(sourceLine, context)
                : mainInstructionPart;
        }

        #endregion

        #region Preprocessor directives

        public override object VisitDirective(Z80AsmParser.DirectiveContext context)
        {
            KeywordSpan = new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1);
            var mnemonic = context.GetChild(0).NormalizeToken();
            if (context.STRING() != null)
            {
                AddString(context.STRING());
            }
            if (mnemonic == "#INCLUDE")
            {
                return new IncludeDirective(this, context);
            } else if (mnemonic == "#LINE")
            {
                return new LineDirective(this, context);
            }
            return new Directive(this, context);
        }

        #endregion

        #region Pragma handling

        public override object VisitPragma(Z80AsmParser.PragmaContext context)
        {
            KeywordSpan = new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1);
            return base.VisitPragma(context);
        }

        public override object VisitByteEmPragma(Z80AsmParser.ByteEmPragmaContext context)
        {
            KeywordSpan = new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1);
            return base.VisitByteEmPragma(context);
        }

        public override object VisitOrgPragma(Z80AsmParser.OrgPragmaContext context) 
            => new OrgPragma(this, context);

        public override object VisitBankPragma(Z80AsmParser.BankPragmaContext context)
            => new BankPragma(this, context);

        public override object VisitXorgPragma(Z80AsmParser.XorgPragmaContext context)
            => new XorgPragma(this, context);

        public override object VisitEntPragma(Z80AsmParser.EntPragmaContext context) 
            => new EntPragma(this, context);

        public override object VisitXentPragma(Z80AsmParser.XentPragmaContext context) 
            => new XentPragma(this, context);

        public override object VisitDispPragma(Z80AsmParser.DispPragmaContext context)
            => new DispPragma(this, context);

        public override object VisitEquPragma(Z80AsmParser.EquPragmaContext context)
            => new EquPragma(this, context);

        public override object VisitVarPragma(Z80AsmParser.VarPragmaContext context) 
            => new VarPragma(this, context);

        public override object VisitSkipPragma(Z80AsmParser.SkipPragmaContext context) 
            => new SkipPragma(this, context);

        public override object VisitDefbPragma(Z80AsmParser.DefbPragmaContext context) 
            => new DefbPragma(this, context);

        public override object VisitDefwPragma(Z80AsmParser.DefwPragmaContext context) 
            => new DefwPragma(this, context);

        public override object VisitDefmPragma(Z80AsmParser.DefmPragmaContext context) 
            => new DefmnPragma(this, context, false, false);

        public override object VisitDefnPragma(Z80AsmParser.DefnPragmaContext context)
            => new DefmnPragma(this, context, true, false);

        public override object VisitDefcPragma(Z80AsmParser.DefcPragmaContext context)
            => new DefmnPragma(this, context, false, true);

        public override object VisitDefhPragma(Z80AsmParser.DefhPragmaContext context) 
            => new DefhPragma(this, context);

        public override object VisitExternPragma(Z80AsmParser.ExternPragmaContext context) 
            => new ExternPragma();

        public override object VisitDefsPragma(Z80AsmParser.DefsPragmaContext context) 
            => new DefsPragma(this, context);

        public override object VisitFillbPragma(Z80AsmParser.FillbPragmaContext context) 
            => new FillbPragma(this, context);

        public override object VisitFillwPragma(Z80AsmParser.FillwPragmaContext context) 
            => new FillwPragma(this, context);

        public override object VisitModelPragma(Z80AsmParser.ModelPragmaContext context) 
            => new ModelPragma(context);

        public override object VisitAlignPragma(Z80AsmParser.AlignPragmaContext context) 
            => new AlignPragma(this, context);

        public override object VisitTracePragma(Z80AsmParser.TracePragmaContext context) 
            => new TracePragma(this, context);

        public override object VisitRndSeedPragma(Z80AsmParser.RndSeedPragmaContext context) 
            => new RndSeedPragma(this, context);

        public override object VisitDefgPragma(Z80AsmParser.DefgPragmaContext context) 
            => new DefgPragma(context);

        public override object VisitDefgxPragma(Z80AsmParser.DefgxPragmaContext context) 
            => new DefgxPragma(this, context);

        public override object VisitErrorPragma(Z80AsmParser.ErrorPragmaContext context) 
            => new ErrorPragma(this, context);

        public override object VisitIncBinPragma(Z80AsmParser.IncBinPragmaContext context) 
            => new IncludeBinPragma(this, context);

        public override object VisitCompareBinPragma(Z80AsmParser.CompareBinPragmaContext context)
            => new CompareBinPragma(this, context);

        public override object VisitZxBasicPragma(Z80AsmParser.ZxBasicPragmaContext context)
            => new ZxBasicPragma();

        public override object VisitInjectOptPragma(Z80AsmParser.InjectOptPragmaContext context)
            => new InjectOptionPragma(context);

        #endregion

        #region Field assignment

        /// <summary>
        /// Visit a parse tree produced by <see cref="Z80AsmParser.fieldAssignment"/>.
        /// <para>
        /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
        /// on <paramref name="context"/>.
        /// </para>
        /// </summary>
        /// <param name="context">The parse tree.</param>
        /// <return>The visitor result.</return>
        public override object VisitFieldAssignment(Z80AsmParser.FieldAssignmentContext context)
        {
            IsFieldAssignment = true;
            return base.VisitFieldAssignment(context);
        }

        #endregion

        #region Operations

        public override object VisitOperation(Z80AsmParser.OperationContext context)
        {
            KeywordSpan = new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1);
            return base.VisitOperation(context);
        }

        public override object VisitTrivialOperation(Z80AsmParser.TrivialOperationContext context) 
            => new TrivialOperation(context);

        public override object VisitTrivialNextOperation(Z80AsmParser.TrivialNextOperationContext context)
            => new TrivialNextOperation(context);

        public override object VisitCompoundOperation(Z80AsmParser.CompoundOperationContext context)
            => new CompoundOperation(this, context);

        public override object VisitOperand(Z80AsmParser.OperandContext context) 
            => new Operand(this, context);

        #endregion

        #region Statement handling

        /// <summary>
        /// Visit a parse tree produced by <see cref="Z80AsmParser.iterationTest"/>.
        /// <para>
        /// The default implementation returns the result of calling <see cref="AbstractParseTreeVisitor{Result}.VisitChildren(IRuleNode)"/>
        /// on <paramref name="context"/>.
        /// </para>
        /// </summary>
        /// <param name="context">The parse tree.</param>
        /// <return>The visitor result.</return>
        public override object VisitIterationTest(Z80AsmParser.IterationTestContext context)
        {
            IToken token = null;
            StatementBase stmt = null;
            if (context.LOOP() != null || context.IDENTIFIER()?.GetText().ToLower() == "loop")
            {
                token = context.LOOP()?.Symbol;
                stmt = new LoopStatement(this, context.expr());
            }
            else if (context.WHILE() != null || context.IDENTIFIER()?.GetText().ToLower() == "while")
            {
                token = context.WHILE()?.Symbol;
                stmt = new WhileStatement(this, context.expr());
            }
            else if (context.UNTIL() != null || context.IDENTIFIER()?.GetText().ToLower() == "until")
            {
                token = context.UNTIL()?.Symbol;
                stmt = new UntilStatement(this, context.expr());
            }
            else if (context.ELIF() != null || context.IDENTIFIER()?.GetText().ToLower() == "elif")
            {
                token = context.ELIF()?.Symbol;
                stmt = new ElifStatement(this, context.expr());
            }
            else
            {
                return null;
            }

            if (token == null)
            {
                token = context.IDENTIFIER().Symbol;
            }
            KeywordSpan = new TextSpan(token.StartIndex, token.StopIndex + 1);
            return stmt;
        }

        public override object VisitStatement(Z80AsmParser.StatementContext context)
        {
            KeywordSpan = new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1);
            return base.VisitStatement(context);
        }

        public override object VisitMacroParam(Z80AsmParser.MacroParamContext context)
        {
            AddMacroParam(context);
            if (context.IDENTIFIER() != null)
            {
                AddMacroParamName(context.IDENTIFIER().GetText());
            }
            return null;
        }

        public override object VisitMacroOrStructInvocation(Z80AsmParser.MacroOrStructInvocationContext context) 
            => new MacroOrStructInvocation(this, context);

        public override object VisitMacroStatement(Z80AsmParser.MacroStatementContext context) 
            => new MacroStatement(this, context);

        public override object VisitMacroEndMarker(Z80AsmParser.MacroEndMarkerContext context) 
            => new MacroEndStatement();

        public override object VisitStructStatement(Z80AsmParser.StructStatementContext context) 
            => new StructStatement();

        public override object VisitStructEndMarker(Z80AsmParser.StructEndMarkerContext context)
            => new StructEndStatement();

        public override object VisitModuleStatement(Z80AsmParser.ModuleStatementContext context) 
            => new ModuleStatement(this, context);

        public override object VisitModuleEndMarker(Z80AsmParser.ModuleEndMarkerContext context) 
            => new ModuleEndStatement();

        public override object VisitLoopEndMarker(Z80AsmParser.LoopEndMarkerContext context) 
            => new LoopEndStatement();

        public override object VisitProcStatement(Z80AsmParser.ProcStatementContext context) 
            => new ProcStatement();

        public override object VisitProcEndMarker(Z80AsmParser.ProcEndMarkerContext context) 
            => new ProcEndStatement();

        public override object VisitRepeatStatement(Z80AsmParser.RepeatStatementContext context) 
            => new RepeatStatement();

        public override object VisitWhileEndMarker(Z80AsmParser.WhileEndMarkerContext context) 
            => new WhileEndStatement();

        public override object VisitIfStatement(Z80AsmParser.IfStatementContext context) 
            => new IfStatement(this, context);

        public override object VisitElseStatement(Z80AsmParser.ElseStatementContext context) 
            => new ElseStatement();

        public override object VisitEndifStatement(Z80AsmParser.EndifStatementContext context) 
            => new IfEndStatement();

        public override object VisitForStatement(Z80AsmParser.ForStatementContext context) 
            => new ForStatement(this, context);

        public override object VisitNextStatement(Z80AsmParser.NextStatementContext context) 
            => new NextStatement();

        public override object VisitBreakStatement(Z80AsmParser.BreakStatementContext context)
            => new BreakStatement();

        public override object VisitContinueStatement(Z80AsmParser.ContinueStatementContext context) 
            => new ContinueStatement();

        public override object VisitLocalStatement(Z80AsmParser.LocalStatementContext context)
            => new LocalStatement(this, context);

        #endregion

        #region Expression handling

        public override object VisitExpr(Z80AsmParser.ExprContext context)
        {
            if (context == null) return null;

            // --- Extract the expression text
            var sb = new StringBuilder(400);
            for (var i = 0; i < context.ChildCount; i++)
            {
                var token = context.GetChild(i).GetText();
                sb.Append(token);
            }

            ExpressionNode expr = null;
            switch (context)
            {
                // --- Primary operators
                case Z80AsmParser.BuiltInFunctionExprContext ctx:
                    expr = (ExpressionNode) VisitBuiltinFunctionInvocation(ctx.builtinFunctionInvocation());
                    break;

                case Z80AsmParser.FunctionInvocationExprContext ctx:
                    expr = new FunctionInvocationNode(ctx.functionInvocation(), this);
                    break;

                case Z80AsmParser.MacroParamExprContext ctx:
                    expr = new MacroParamNode(ctx.macroParam(), this);
                    break;

                // --- Unary operators
                case Z80AsmParser.UnaryPlusExprContext ctx:
                    expr = new UnaryPlusNode(ctx, this);
                    break;
                case Z80AsmParser.UnaryMinusExprContext ctx:
                    expr = new UnaryMinusNode(ctx, this);
                    break;
                case Z80AsmParser.BinaryNotExprContext ctx:
                    expr = new UnaryBitwiseNotNode(ctx, this);
                    break;
                case Z80AsmParser.LogicalNotExprContext ctx:
                    expr = new UnaryLogicalNotNode(ctx, this);
                    break;

                // --- Bracketed/Parenthesized expressions
                case Z80AsmParser.BracketedExprContext ctx:
                    expr = (ExpressionNode) VisitExpr(ctx.expr());
                    break;
                case Z80AsmParser.ParenthesizedExprContext ctx:
                    expr = (ExpressionNode)VisitExpr(ctx.expr());
                    break;

                // --- Literals
                case Z80AsmParser.LiteralExprContext ctx:
                    expr = (ExpressionNode)VisitLiteral(ctx.literal());
                    break;

                case Z80AsmParser.SymbolExprContext ctx:
                    if (ctx.ChildCount != 0 && ctx.symbol()?.IDENTIFIER() != null)
                    {
                        AddIdentifier(ctx);
                        expr = new IdentifierNode(ctx.symbol());
                    }
                    break;

                // --- Min/Max operators
                case Z80AsmParser.MinMaxExprContext ctx:
                    switch (ctx.op?.Text)
                    {
                        case "<?":
                            expr = new MinOperationNode(ctx, this);
                            break;
                        default:
                            expr = new MaxOperationNode(ctx, this);
                            break;
                    }
                    break;

                // --- Multiplication operators
                case Z80AsmParser.MultExprContext ctx:
                    switch (ctx.op?.Text)
                    {
                        case "*":
                            expr = new MultiplyOperationNode(ctx, this);
                            break;
                        case "/":
                            expr = new DivideOperationNode(ctx, this);
                            break;
                        default:
                            expr = new ModuloOperationNode(ctx, this);
                            break;
                    }
                    break;

                // --- Addition operators
                case Z80AsmParser.AddExprContext ctx:
                    switch (ctx.op?.Text)
                    {
                        case "+":
                            expr = new AddOperationNode(ctx, this);
                            break;
                        default:
                            expr = new SubtractOperationNode(ctx, this);
                            break;
                    }
                    break;

                // --- Shift operators
                case Z80AsmParser.ShiftExprContext ctx:
                    switch (ctx.op?.Text)
                    {
                        case "<<":
                            expr = new ShiftLeftOperationNode(ctx, this);
                            break;
                        default:
                            expr = new ShiftRightOperationNode(ctx, this);
                            break;
                    }
                    break;

                // --- Relational operators
                case Z80AsmParser.RelExprContext ctx:
                    switch (ctx.op?.Text)
                    {
                        case "<":
                            expr = new LessThanOperationNode(ctx, this);
                            break;
                        case "<=":
                            expr = new LessThanOrEqualOperationNode(ctx, this);
                            break;
                        case ">":
                            expr = new GreaterThanOperationNode(ctx, this);
                            break;
                        default:
                            expr = new GreaterThanOrEqualOperationNode(ctx, this);
                            break;
                    }
                    break;

                // --- Equality operators
                case Z80AsmParser.EquExprContext ctx:
                    switch (ctx.op?.Text)
                    {
                        case "==":
                            expr = new EqualOperationNode(ctx, this);
                            break;
                        case "===":
                            expr = new CaseInsensitiveEqualOperationNode(ctx, this);
                            break;
                        case "!=":
                            expr = new NotEqualOperationNode(ctx, this);
                            break;
                        default:
                            expr = new CaseInsensitiveNotEqualOperationNode(ctx, this);
                            break;
                    }
                    break;

                // --- Bitwise operators
                case Z80AsmParser.AndExprContext ctx:
                    expr = new BitwiseAndOperationNode(ctx, this);
                    break;
                case Z80AsmParser.XorExprContext ctx:
                    expr = new BitwiseXorOperationNode(ctx, this);
                    break;
                case Z80AsmParser.OrExprContext ctx:
                    expr = new BitwiseOrOperationNode(ctx, this);
                    break;

                // --- Ternary operator
                case Z80AsmParser.TernaryExprContext ctx:
                    expr = new ConditionalExpressionNode(ctx, this);
                    break;
            }

            if (expr != null)
            {
                expr.SourceText = sb.ToString();
            }
            return expr;
        }

        public override object VisitLiteral(Z80AsmParser.LiteralContext context)
        {
            if (context == null) return null;

            switch (context)
            {
                case Z80AsmParser.CurAddrLiteralContext ctx:
                    AddSemiVar(ctx);
                    return new CurrentAddressNode(ctx);

                case Z80AsmParser.CurCounterLiteralContext ctx:
                    AddSemiVar(ctx);
                    return new CurrentLoopCounterNode(ctx);

                case Z80AsmParser.BoolLiteralContext ctx:
                    AddNumber(ctx);
                    var boolValue = new ExpressionValue(ctx.BOOLLIT().GetText().ToLower().Contains("t"));
                    return new LiteralNode(ctx, boolValue);

                case Z80AsmParser.RealLiteralContext ctx:
                    AddNumber(ctx);
                    return double.TryParse(ctx.REALNUM().GetText(), 
                        NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, 
                        CultureInfo.InvariantCulture, out var realValue)
                        ? new LiteralNode(ctx, realValue)
                        : new LiteralNode(ctx, ExpressionValue.Error);

                case Z80AsmParser.StringLiteralContext ctx:
                    AddString(ctx);
                    var stringValue = ctx.STRING().NormalizeString();
                    return new LiteralNode(ctx, stringValue);

            }

            var token = context.NormalizeToken();
            ushort value;

            // --- Hexadecimal literals
            if (token.StartsWith("#") && token.Length > 1)
            {
                AddNumber(context);
                value = ushort.Parse(token.Substring(1), NumberStyles.HexNumber);
            }
            else if (token.StartsWith("0X") && token.Length > 2)
            {
                AddNumber(context);
                value = ushort.Parse(token.Substring(2), NumberStyles.HexNumber);
            }
            else if (token.StartsWith("$") && token.Length > 1)
            {
                AddNumber(context);
                value = ushort.Parse(token.Substring(1), NumberStyles.HexNumber);
            }
            else if (token.EndsWith("H", StringComparison.OrdinalIgnoreCase) && token.Length > 1)
            {
                AddNumber(context);
                value = (ushort)int.Parse(token.Substring(0, token.Length - 1),
                    NumberStyles.HexNumber);
            }
            
            // --- Binary literals
            else if (token.StartsWith("%") && token.Length > 1)
            {
                AddNumber(context);
                value = (ushort)Convert.ToInt32(token.Substring(1).Replace("_", ""), 2);
            }
            else if (token.StartsWith("0B") && token.Length > 2)
            {
                AddNumber(context);
                value = (ushort)Convert.ToInt32(token.Substring(2).Replace("_", ""), 2);
            }
            else if ((token.EndsWith("b") || token.EndsWith("B")) && token.Length > 1)
            {
                AddNumber(context);
                value = (ushort)Convert.ToInt32(token.Substring(0, token.Length - 1).Replace("_", ""), 2);
            }
            
            // --- Octal literals
            else if ((token.EndsWith("q") || token.EndsWith("Q") || token.EndsWith("o") || token.EndsWith("O"))
                && token.Length > 1)
            {
                AddNumber(context);
                value = (ushort)Convert.ToInt32(token.Substring(0, token.Length - 1), 8);
            }
            
            // --- Character literals
            else if ((token.StartsWith("\"") || token.StartsWith("'")) && token.Length > 2)
            {
                AddString(context);
                var charExpr = context.GetText();
                var bytes = Z80Assembler.SpectrumStringToBytes(charExpr.Substring(1, charExpr.Length - 2));
                value = bytes.Count == 0 ? (ushort)0x00 : bytes[0];
            }

            // --- Decimal literals
            else
            {
                AddNumber(context);
                value = (ushort)int.Parse(context.NormalizeToken());
            }

            return new LiteralNode(context, value);
        }

        public override object VisitBuiltinFunctionInvocation(Z80AsmParser.BuiltinFunctionInvocationContext context)
        {
            AddFunction(context);
            string token = null;

            switch (context)
            {
                case Z80AsmParser.TextOfInvokeContext ctx:
                    if (ctx.macroParam() != null)
                    {
                        AddFunction(context);
                        AddMacroParam(ctx.macroParam());
                        if (ctx.macroParam().IDENTIFIER() != null)
                        {
                            AddMacroParamName(ctx.macroParam().IDENTIFIER().GetText());
                        }
                    }
                    if (ctx.mnemonic() != null)
                    {
                        AddMnemonics(ctx.mnemonic());
                        token = ctx.mnemonic().NormalizeToken();
                    }
                    else if (ctx.regsAndConds() != null)
                    {
                        AddOperand(ctx.regsAndConds());
                        token = ctx.regsAndConds().NormalizeToken();
                    }

                    if (ctx.LTEXTOF() != null)
                    {
                        token = token?.ToLower();
                    }
                    return new LiteralNode(ctx, token);

                case Z80AsmParser.DefInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand() != null && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsReg8InvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx,
                        (ctx.operand()?.reg8() != null
                         || ctx.operand()?.reg8Spec() != null
                         || ctx.operand()?.reg8Idx() != null)
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsReg8StdInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8() != null
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsReg8StdSpecInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8Spec() != null
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsReg8IdxInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8Idx() != null
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsReg16InvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx,
                        (ctx.operand()?.reg16() != null
                         || ctx.operand()?.reg16Idx() != null
                         || ctx.operand()?.reg16Spec() != null)
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsReg16StdInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg16() != null
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsReg16IdxInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg16Idx() != null
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegIndirectInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.regIndirect() != null
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsCportInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.cPort() != null
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsIndexedAddrInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.indexedAddr() != null
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsConditionInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx,
                        (ctx.operand()?.condition() != null || ctx.operand().reg8()?.GetText()?.ToLower() == "c")
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsExprInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.expr() != null
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegAInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8() != null && ctx.operand()?.GetText()?.ToLower() == "a"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegBInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8() != null && ctx.operand()?.GetText()?.ToLower() == "b"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegCInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8() != null && ctx.operand()?.GetText()?.ToLower() == "c"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegDInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8() != null && ctx.operand()?.GetText()?.ToLower() == "d"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegEInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8() != null && ctx.operand()?.GetText()?.ToLower() == "e"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegHInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8() != null && ctx.operand()?.GetText()?.ToLower() == "h"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegLInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8() != null && ctx.operand()?.GetText()?.ToLower() == "l"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegIInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8Spec() != null && ctx.operand()?.GetText()?.ToLower() == "i"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegRInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8Spec() != null && ctx.operand()?.GetText()?.ToLower() == "r"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegBCInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg16() != null && ctx.operand()?.GetText()?.ToLower() == "bc"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegDEInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg16() != null && ctx.operand()?.GetText()?.ToLower() == "de"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegHLInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg16() != null && ctx.operand()?.GetText()?.ToLower() == "hl"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegXHInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8Idx() != null && 
                        (ctx.operand()?.GetText()?.ToLower() == "xh" || ctx.operand()?.GetText()?.ToLower() == "ixh")
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegXLInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8Idx() != null &&
                        (ctx.operand()?.GetText()?.ToLower() == "xl" || ctx.operand()?.GetText()?.ToLower() == "ixl")
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegYHInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8Idx() != null &&
                        (ctx.operand()?.GetText()?.ToLower() == "yh" || ctx.operand()?.GetText()?.ToLower() == "iyh")
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegYLInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg8Idx() != null &&
                        (ctx.operand()?.GetText()?.ToLower() == "yl" || ctx.operand()?.GetText()?.ToLower() == "iyl")
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegIXInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg16Idx() != null && ctx.operand()?.GetText()?.ToLower() == "ix"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegIYInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg16Idx() != null && ctx.operand()?.GetText()?.ToLower() == "iy"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegSPInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg16() != null && ctx.operand()?.GetText()?.ToLower() == "sp"
                        && ctx.operand().NONEARG() == null);

                case Z80AsmParser.IsRegAfInvokeContext ctx:
                    CheckForMacroParamNode(ctx.operand());
                    return new LiteralNode(ctx, ctx.operand()?.reg16Spec() != null && ctx.operand()?.GetText()?.ToLower() == "af"
                        && ctx.operand().NONEARG() == null);

            }
            return null;
        }

        /// <summary>
        /// Checks if the operand is used as a macro parameter node
        /// </summary>
        /// <param name="context"></param>
        private void CheckForMacroParamNode(Z80AsmParser.OperandContext context)
        {
            if (context == null) return;

            var op = (Operand) VisitOperand(context);
            if (!MacroParsingPhase && (op.Type != OperandType.Expr || !(op.Expression is MacroParamNode)))
            {
                // --- Built in function can use only macro parameters during the collection phase
                IssueToEmit = Errors.Z0421;
            }
        }

        #endregion

        #region Helper methods

        /// <summary>
        /// Adds an assembly line to the compilation
        /// </summary>
        /// <param name="line">Line to add</param>
        /// <param name="context">The context that generates this line</param>
        /// <returns>The newly added line</returns>
        private SourceLineBase AddLine(SourceLineBase line, ParserRuleContext context)
        {
            line.SourceText = CurrentSourceText;
            line.SourceLine = CurrentSourceLine;
            line.FirstColumn = FirstColumn;
            line.FirstPosition = FirstPosition;
            line.LastPosition = LastPosition;
            line.ParserException = context.exception;
            line.Label = CurrentLabel;
            line.LabelColon = CurrentLabelColon;
            line.LabelSpan = LabelSpan;
            line.KeywordSpan = KeywordSpan;
            line.NumberSpans = NumberSpans;
            line.StringSpans = StringSpans;
            line.FunctionSpans = FunctionSpans;
            line.SemiVarSpans = SemiVarSpans;
            line.MacroParamSpans = MacroParamSpans;
            line.MacroParamNames = MacroParamNames;
            line.IdentifierSpans = IdentifierSpans;
            line.StatementSpans = StatementSpans;
            line.OperandSpans = OperandSpans;
            line.MnemonicSpans = MnemonicSpans;
            line.Comment = CurrentComment;
            line.CommentSpan = CommentSpan;
            line.IssueToEmit = IssueToEmit;
            line.InstructionSpan = KeywordSpan != null 
                ? new TextSpan(KeywordSpan.Start, LastInstructionPos + 1) 
                : new TextSpan(FirstColumn, FirstColumn);
            Compilation.Lines.Add(line);
            LastAsmLine = line;
            if (line is ISupportsFieldAssignment fieldAssignment)
            {
                fieldAssignment.IsFieldAssignment = IsFieldAssignment;
            }
            return line;
        }

        #endregion
    }
}

<|start_filename|>v2/Tests/Spect.Net.Assembler.Test/Assembler/ControlFlowOperationEmitTests.cs<|end_filename|>
﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Spect.Net.Assembler.Assembler;

namespace Spect.Net.Assembler.Test.Assembler
{
    [TestClass]
    public class ControlFlowOperationEmitTests : AssemblerTestBed
    {
        [TestMethod]
        public void DjnzOpWorksAsExpected()
        {
            // --- Start address is #8000!
            CodeEmitWorks("djnz #8022", 0x10, 0x20);
            CodeEmitWorks("djnz #8000", 0x10, 0xFE);
            CodeEmitWorks("djnz #8081", 0x10, 0x7F);
            CodeEmitWorks("djnz #7F82", 0x10, 0x80);
            CodeEmitWorks("djnz #7F84", 0x10, 0x82);
        }

        [TestMethod]
        public void DjnzFailsWithFarAddress()
        {
            // --- Start address is #8000!
            CodeRaisesError("djnz #8082", Errors.Z0022);
            CodeRaisesError("djnz #8100", Errors.Z0022);
            CodeRaisesError("djnz #7F81", Errors.Z0022);
            CodeRaisesError("djnz #7F00", Errors.Z0022);
        }

        [TestMethod]
        public void JrOpsWorksAsExpected()
        {
            // --- Start address is #8000!
            CodeEmitWorks("jr #8022", 0x18, 0x20);
            CodeEmitWorks("jr #8000", 0x18, 0xFE);
            CodeEmitWorks("jr #8081", 0x18, 0x7F);
            CodeEmitWorks("jr #7F82", 0x18, 0x80);
            CodeEmitWorks("jr #7F84", 0x18, 0x82);

            CodeEmitWorks("jr nz,#8022", 0x20, 0x20);
            CodeEmitWorks("jr nz,#8000", 0x20, 0xFE);
            CodeEmitWorks("jr nz,#8081", 0x20, 0x7F);
            CodeEmitWorks("jr nz,#7F82", 0x20, 0x80);
            CodeEmitWorks("jr nz,#7F84", 0x20, 0x82);

            CodeEmitWorks("jr z,#8022", 0x28, 0x20);
            CodeEmitWorks("jr z,#8000", 0x28, 0xFE);
            CodeEmitWorks("jr z,#8081", 0x28, 0x7F);
            CodeEmitWorks("jr z,#7F82", 0x28, 0x80);
            CodeEmitWorks("jr z,#7F84", 0x28, 0x82);

            CodeEmitWorks("jr nc,#8022", 0x30, 0x20);
            CodeEmitWorks("jr nc,#8000", 0x30, 0xFE);
            CodeEmitWorks("jr nc,#8081", 0x30, 0x7F);
            CodeEmitWorks("jr nc,#7F82", 0x30, 0x80);
            CodeEmitWorks("jr nc,#7F84", 0x30, 0x82);

            CodeEmitWorks("jr c,#8022", 0x38, 0x20);
            CodeEmitWorks("jr c,#8000", 0x38, 0xFE);
            CodeEmitWorks("jr c,#8081", 0x38, 0x7F);
            CodeEmitWorks("jr c,#7F82", 0x38, 0x80);
            CodeEmitWorks("jr c,#7F84", 0x38, 0x82);
        }

        [TestMethod]
        public void JrFailsWithFarAddress()
        {
            // --- Start address is #8000!
            CodeRaisesError("djnz #8082", Errors.Z0022);
            CodeRaisesError("djnz #8100", Errors.Z0022);
            CodeRaisesError("djnz #7F81", Errors.Z0022);
            CodeRaisesError("djnz #7F00", Errors.Z0022);

            CodeRaisesError("jr #8082", Errors.Z0022);
            CodeRaisesError("jr #8100", Errors.Z0022);
            CodeRaisesError("jr #7F81", Errors.Z0022);
            CodeRaisesError("jr #7F00", Errors.Z0022);

            CodeRaisesError("jr nz,#8082", Errors.Z0022);
            CodeRaisesError("jr nz,#8100", Errors.Z0022);
            CodeRaisesError("jr nz,#7F81", Errors.Z0022);
            CodeRaisesError("jr nz,#7F00", Errors.Z0022);

            CodeRaisesError("jr z,#8082", Errors.Z0022);
            CodeRaisesError("jr z,#8100", Errors.Z0022);
            CodeRaisesError("jr z,#7F81", Errors.Z0022);
            CodeRaisesError("jr z,#7F00", Errors.Z0022);

            CodeRaisesError("jr nc,#8082", Errors.Z0022);
            CodeRaisesError("jr nc,#8100", Errors.Z0022);
            CodeRaisesError("jr nc,#7F81", Errors.Z0022);
            CodeRaisesError("jr nc,#7F00", Errors.Z0022);

            CodeRaisesError("jr c,#8082", Errors.Z0022);
            CodeRaisesError("jr c,#8100", Errors.Z0022);
            CodeRaisesError("jr c,#7F81", Errors.Z0022);
            CodeRaisesError("jr c,#7F00", Errors.Z0022);
        }

        [TestMethod]
        public void JrFailsWithInvalidCondition()
        {
            // --- Start address is #8000!
            CodeRaisesError("jr po,$", Errors.Z0095);
            CodeRaisesError("jr pe,$", Errors.Z0095);
            CodeRaisesError("jr p,$", Errors.Z0095);
            CodeRaisesError("jr m,$", Errors.Z0095);
        }

        [TestMethod]
        public void JpOpsWorksAsExpected()
        {
            CodeEmitWorks("jp #3024", 0xC3, 0x24, 0x30);
            CodeEmitWorks("jp nz,#3024", 0xC2, 0x24, 0x30);
            CodeEmitWorks("jp z,#3024", 0xCA, 0x24, 0x30);
            CodeEmitWorks("jp nc,#3024", 0xD2, 0x24, 0x30);
            CodeEmitWorks("jp c,#3024", 0xDA, 0x24, 0x30);
            CodeEmitWorks("jp po,#3024", 0xE2, 0x24, 0x30);
            CodeEmitWorks("jp pe,#3024", 0xEA, 0x24, 0x30);
            CodeEmitWorks("jp p,#3024", 0xF2, 0x24, 0x30);
            CodeEmitWorks("jp m,#3024", 0xFA, 0x24, 0x30);

            CodeEmitWorks("jp (hl)", 0xE9);
            CodeEmitWorks("jp (ix)", 0xDD, 0xE9);
            CodeEmitWorks("jp (iy)", 0xFD, 0xE9);
            CodeEmitWorks("jp hl", 0xE9);
            CodeEmitWorks("jp ix", 0xDD, 0xE9);
            CodeEmitWorks("jp iy", 0xFD, 0xE9);
        }

        [TestMethod]
        public void CallOpsWorksAsExpected()
        {
            CodeEmitWorks("call #3024", 0xCD, 0x24, 0x30);
            CodeEmitWorks("call nz,#3024", 0xC4, 0x24, 0x30);
            CodeEmitWorks("call z,#3024", 0xCC, 0x24, 0x30);
            CodeEmitWorks("call nc,#3024", 0xD4, 0x24, 0x30);
            CodeEmitWorks("call c,#3024", 0xDC, 0x24, 0x30);
            CodeEmitWorks("call po,#3024", 0xE4, 0x24, 0x30);
            CodeEmitWorks("call pe,#3024", 0xEC, 0x24, 0x30);
            CodeEmitWorks("call p,#3024", 0xF4, 0x24, 0x30);
            CodeEmitWorks("call m,#3024", 0xFC, 0x24, 0x30);
        }

        [TestMethod]
        public void RetOpsWorksAsExpected()
        {
            CodeEmitWorks("ret", 0xC9);
            CodeEmitWorks("ret nz", 0xC0);
            CodeEmitWorks("ret z", 0xC8);
            CodeEmitWorks("ret nc", 0xD0);
            CodeEmitWorks("ret c", 0xD8);
            CodeEmitWorks("ret po", 0xE0);
            CodeEmitWorks("ret pe", 0xE8);
            CodeEmitWorks("ret p", 0xF0);
            CodeEmitWorks("ret m", 0xF8);
        }

        [TestMethod]
        public void RstOpsWorkAsExpected()
        {
            CodeEmitWorks("rst 0", 0xC7);
            CodeEmitWorks("rst 8", 0xCF);
            CodeEmitWorks("rst #08", 0xCF);
            CodeEmitWorks("rst 08h", 0xCF);
            CodeEmitWorks("rst 08H", 0xCF);
            CodeEmitWorks("rst #10", 0xD7);
            CodeEmitWorks("rst #18", 0xDF);
            CodeEmitWorks("rst #20", 0xE7);
            CodeEmitWorks("rst #28", 0xEF);
            CodeEmitWorks("rst #30", 0xF7);
            CodeEmitWorks("rst #38", 0xFF);
        }

        [TestMethod]
        public void InvalidOpsRaiseError()
        {
            CodeRaisesError("rst 23", Errors.Z0018);
            CodeRaisesError("jp (bc)", Errors.Z0016);
            CodeRaisesError("jp (de)", Errors.Z0016);
            CodeRaisesError("jp (sp)", Errors.Z0016);
            CodeRaisesError("jp (ix+3)", Errors.Z0016);
            CodeRaisesError("jp (iy+3)", Errors.Z0016);
            CodeRaisesError("jp nz,(hl)", Errors.Z0001);
        }

    }
}

<|start_filename|>v2/Tests/Spect.Net.Assembler.Test/Assembler/StructDefinitionTests.cs<|end_filename|>
﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shouldly;
using Spect.Net.Assembler.Assembler;

// ReSharper disable StringLiteralTypo

namespace Spect.Net.Assembler.Test.Assembler
{
    [TestClass]
    public class StructDefinitionTests : AssemblerTestBed
    {
        [TestMethod]
        public void StructWithNoLabelFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                .struct
                .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0432);
        }

        [TestMethod]
        public void StructWithLocalLabelFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                `local .struct
                .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0433);
        }

        [TestMethod]
        public void StructWithEndLabelFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct .struct
                MyEnd: .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0436);
        }

        [TestMethod]
        public void StructWithHangingLabelFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct
                    .struct
                MyEnd:
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0436);
        }

        [TestMethod]
        public void StructWithLabelWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: .struct
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Section.FirstLine.ShouldBe(0);
            def.Section.LastLine.ShouldBe(1);
            def.StructName.ShouldBe("MyStruct");
        }

        [TestMethod]
        public void StructWithExistingLabelFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: nop
                MyStruct: .struct
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0434);
        }

        [TestMethod]
        public void StructWithExistingLabelFailsCs1()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: nop
                mystruct: .struct
                    .ends
                ", new AssemblerOptions { UseCaseSensitiveSymbols = false });

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0434);
        }

        [TestMethod]
        public void StructWithExistingLabelFailsCs2()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: nop
                mystruct: .struct
                    .ends
                ", new AssemblerOptions { UseCaseSensitiveSymbols = true });

            // --- Assert
            output.ErrorCount.ShouldBe(0);
        }

        [TestMethod]
        public void StructWithExistingLabelFailsCs3()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: nop
                MyStruct: .struct
                    .ends
                ", new AssemblerOptions { UseCaseSensitiveSymbols = true });

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0434);
        }

        [TestMethod]
        public void StructWithHangingLabelWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Section.FirstLine.ShouldBe(1);
            def.Section.LastLine.ShouldBe(2);
            def.StructName.ShouldBe("MyStruct");
        }

        [TestMethod]
        public void StructWithNoEndFails()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: .struct
                    ld a,b
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0401);
        }

        [TestMethod]
        [DataRow(".ends")]
        [DataRow("ends")]
        [DataRow(".ENDS")]
        [DataRow("ENDS")]
        public void EndStructWithoutOpenTagFails(string source)
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(source);

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0405);
        }

        [TestMethod]
        [DataRow("ld a,b")]
        [DataRow("jp #1000")]
        public void StructWithInvalidInstructionFails(string stmt)
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile($@"
                MyStruct .struct
                  {stmt}
                .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0435);
        }

        [TestMethod]
        [DataRow("; this is comment")]
        [DataRow("MyField")]
        [DataRow("MyField:")]
        [DataRow(".defb 0x80")]
        [DataRow(".defw 0x8078")]
        [DataRow(".defc \"Hello\"")]
        [DataRow(".defm \"Hello\"")]
        [DataRow(".defn \"Hello\"")]
        [DataRow(".defh \"e345\"")]
        [DataRow(".defs 100")]
        [DataRow(".fillb 10,#ff")]
        [DataRow(".fillw 10,#ffe3")]
        [DataRow(".defgx \"....OOOO\"")]
        [DataRow(".defg \"....OOOO\"")]
        public void StructWithValidPragmaWorks(string stmt)
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile($@"
                MyStruct .struct
                  {stmt}
                  .defb 0x80
                .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
        }

        [TestMethod]
        public void StructDefinitionWithDefbWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .defb 0x13, 0x15
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(2);
        }

        [TestMethod]
        public void StructDefinitionFixupWithDefbWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .defb 0x13, Symb1, 0x15, Sym1*Symb2
                    .ends
                Symb1: .equ 1
                Symb2: .equ 2
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(4);
        }

        [TestMethod]
        public void StructDefinitionWithDefwWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .defw 0x13A5, 0x15A6
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(4);
        }

        [TestMethod]
        public void StructDefinitionFixupWithDefwWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .defw 0x13A5, Symb1, 0x15A6, Sym1*Symb2
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(8);
        }

        [TestMethod]
        public void StructDefinitionWithDefmWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .defm ""ABCD""
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(4);
        }

        [TestMethod]
        public void StructDefinitionWithDefnWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .defn ""ABCD""
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(5);
        }

        [TestMethod]
        public void StructDefinitionWithDefcWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .defc ""ABCD""
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(4);
        }

        [TestMethod]
        public void StructDefinitionWithDefhWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .defh ""12AB23CD""
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(4);
        }

        [TestMethod]
        public void StructDefinitionWithDefsWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .defs 3
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(3);
        }

        [TestMethod]
        public void StructDefinitionWithFillbWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .fillb 3, #A5
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(3);
        }

        [TestMethod]
        public void StructDefinitionWithFillwWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .fillw 2, #A547
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(4);
        }

        [TestMethod]
        public void StructDefinitionWithDefgWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .defg ----OOOO OOOO----
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(2);
        }

        [TestMethod]
        public void StructDefinitionWithDefgxWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .defgx ""----OOOO OOOO----""
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(2);
        }

        [TestMethod]
        public void StructDefinitionWithMultiplePragmasWorks()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .defb 0x12, 0x13
                        ; This is a comment
                        .defgx ""----OOOO OOOO----""
                        .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Size.ShouldBe(10);
        }

        [TestMethod]
        public void StructDefinitionWithFieldsWorks1()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        field1: .defb 0x12, 0x13
                        field2: ; This is a comment
                                .defgx ""----OOOO OOOO----""
                        field4: .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Fields.Count.ShouldBe(3);
            def.Fields["field1"].Offset.ShouldBe((ushort)0);
            def.Fields["field2"].Offset.ShouldBe((ushort)2);
            def.Fields["field4"].Offset.ShouldBe((ushort)4);
            output.Symbols["MyStruct"].Value.AsWord().ShouldBe((ushort)10);
        }

        [TestMethod]
        public void StructDefinitionWithFieldsWorks2()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        field1: .defb 0x12, 0x13
                        field2: ; This is a comment
                        field3: .defgx ""----OOOO OOOO----""
                        field4: .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Structs.ContainsKey("MyStruct").ShouldBeTrue();
            var def = output.Structs["MyStruct"];
            def.ShouldNotBeNull();
            def.Fields.Count.ShouldBe(4);
            def.Fields["field1"].Offset.ShouldBe((ushort)0);
            def.Fields["field2"].Offset.ShouldBe((ushort)2);
            def.Fields["field3"].Offset.ShouldBe((ushort)2);
            def.Fields["field4"].Offset.ShouldBe((ushort)4);
            output.Symbols["MyStruct"].Value.AsWord().ShouldBe((ushort)10);
        }

        [TestMethod]
        public void StructDefinitionWithDuplicatedFieldFails1()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        field1: .defb 0x12, 0x13
                        field2: ; This is a comment
                                .defgx ""----OOOO OOOO----""
                        field1: .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0438);
        }

        [TestMethod]
        public void StructDefinitionWithDuplicatedFieldFailsCs1()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        field1: .defb 0x12, 0x13
                        field2: ; This is a comment
                                .defgx ""----OOOO OOOO----""
                        Field1: .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                ",
                new AssemblerOptions { UseCaseSensitiveSymbols = false });

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0438);
        }

        [TestMethod]
        public void StructDefinitionWithDuplicatedFieldFailsCs2()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        field1: .defb 0x12, 0x13
                        field2: ; This is a comment
                                .defgx ""----OOOO OOOO----""
                        field1: .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                ",
                new AssemblerOptions { UseCaseSensitiveSymbols = true });

            // --- Assert
            output.ErrorCount.ShouldBe(1);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0438);
        }

        [TestMethod]
        public void StructDefinitionWithDuplicatedFieldFailsCs3()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        field1: .defb 0x12, 0x13
                        field2: ; This is a comment
                                .defgx ""----OOOO OOOO----""
                        Field1: .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                ",
                new AssemblerOptions { UseCaseSensitiveSymbols = true });

            // --- Assert
            output.ErrorCount.ShouldBe(0);
        }

        [TestMethod]
        public void StructDefinitionWithDuplicatedFieldFails2()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        field1 .defb 0x12, 0x13
                        field2 ; This is a comment
                        field2 .defgx ""----OOOO OOOO----""
                        field1 .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(2);
            output.Errors[0].ErrorCode.ShouldBe(Errors.Z0438);
            output.Errors[1].ErrorCode.ShouldBe(Errors.Z0438);
        }

        [TestMethod]
        public void StructLabelShowsStructLength()
        {
            // --- Arrange
            var compiler = new Z80Assembler();

            // --- Act
            var output = compiler.Compile(@"
                MyStruct: 
                    .struct
                        .defb 0x12, 0x13
                        ; This is a comment
                        .defgx ""----OOOO OOOO----""
                        .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                .defs MyStruct*10
                ");

            // --- Assert
            output.ErrorCount.ShouldBe(0);
            output.Segments[0].EmittedCode.Count.ShouldBe(100);
        }

        [TestMethod]
        public void StructFieldsCanBeResolved()
        {
            // --- Arrange
            const string SOURCE = @"
                MyStruct: 
                    .struct
                        field1: .defb 0x12, 0x13
                        field2: ; This is a comment
                        field3: .defgx ""----OOOO OOOO----""
                        field4: .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                .defb MyStruct.field1
                .defb MyStruct.field2
                .defb MyStruct.field3
                .defb MyStruct.field4
                ";

            // --- Act/Assert
            CodeEmitWorks(SOURCE, 0x00, 0x02, 0x02, 0x04);
        }

        [TestMethod]
        public void StructFieldsCanBeResolvedWithGlobalModule()
        {
            // --- Arrange
            const string SOURCE = @"
                MyStruct: 
                    .struct
                        field1: .defb 0x12, 0x13
                        field2: ; This is a comment
                        field3: .defgx ""----OOOO OOOO----""
                        field4: .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                .defb ::MyStruct.field1
                .defb ::MyStruct.field2
                .defb ::MyStruct.field3
                .defb ::MyStruct.field4
                ";

            // --- Act/Assert
            CodeEmitWorks(SOURCE, 0x00, 0x02, 0x02, 0x04);
        }

        [TestMethod]
        public void StructFieldsCanBeResolvedOutOfModule()
        {
            // --- Arrange
            const string SOURCE = @"
                MyModule: .module
                MyStruct: 
                    .struct
                        field1: .defb 0x12, 0x13
                        field2: ; This is a comment
                        field3: .defgx ""----OOOO OOOO----""
                        field4: .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                .endmodule
                .defb MyModule.MyStruct.field1
                .defb MyModule.MyStruct.field2
                .defb MyModule.MyStruct.field3
                .defb MyModule.MyStruct.field4
                ";

            // --- Act/Assert
            CodeEmitWorks(SOURCE, 0x00, 0x02, 0x02, 0x04);
        }

        [TestMethod]
        public void StructFieldsCanBeResolvedOutOfModuleFromGlobal()
        {
            // --- Arrange
            const string SOURCE = @"
                MyModule: .module
                MyStruct: 
                    .struct
                        field1: .defb 0x12, 0x13
                        field2: ; This is a comment
                        field3: .defgx ""----OOOO OOOO----""
                        field4: .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                .endmodule
                .defb ::MyModule.MyStruct.field1
                .defb ::MyModule.MyStruct.field2
                .defb ::MyModule.MyStruct.field3
                .defb ::MyModule.MyStruct.field4
                ";

            // --- Act/Assert
            CodeEmitWorks(SOURCE, 0x00, 0x02, 0x02, 0x04);
        }

        [TestMethod]
        public void StructFieldsCanBeResolvedWithinModule()
        {
            // --- Arrange
            const string SOURCE = @"
                MyModule: .module
                MyStruct: 
                    .struct
                        field1: .defb 0x12, 0x13
                        field2: ; This is a comment
                        field3: .defgx ""----OOOO OOOO----""
                        field4: .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                .defb MyStruct.field1
                .defb MyStruct.field2
                .defb MyStruct.field3
                .defb MyStruct.field4
                .endmodule
                ";

            // --- Act/Assert
            CodeEmitWorks(SOURCE, 0x00, 0x02, 0x02, 0x04);
        }

        [TestMethod]
        public void StructCanBeResolvedWithinModule()
        {
            // --- Arrange
            const string SOURCE = @"
                MyModule: .module
                MyStruct: 
                    .struct
                        field1: .defb 0x12, 0x13
                        field2: ; This is a comment
                        field3: .defgx ""----OOOO OOOO----""
                        field4: .fillw 2, #12A3
                        .defw #FEDC
                    .ends
                .defb ::MyModule.MyStruct
                .endmodule
                ";

            // --- Act/Assert
            CodeEmitWorks(SOURCE, 0x0A);
        }
    }
}

<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/ToolWindows/Keyboard/KeyPressHandler.cs<|end_filename|>
﻿using System.Threading.Tasks;
using System.Windows.Input;
using Microsoft.VisualStudio.Shell.Interop;
using Spect.Net.SpectrumEmu.Abstraction.Devices.Keyboard;
using Spect.Net.SpectrumEmu.Machine;

namespace Spect.Net.VsPackage.ToolWindows.Keyboard
{
    /// <summary>
    /// This class is responsible for handling the key events
    /// </summary>
    public class KeyPressHandler
    {
        private volatile bool _isDown;

        /// <summary>
        /// Get the machine keyboard
        /// </summary>
        public KeyboardEmulator Keyboard => SpectNetPackage.Default.EmulatorViewModel.Machine.Keyboard;

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Object" /> class.
        /// </summary>
        public KeyPressHandler()
        {
            _isDown = false;
        }

        /// <summary>
        /// Handles the event when the main key has been clicked
        /// </summary>
        public async void OnMainKeyClicked(object sender, MouseButtonEventArgs e)
        {
            if (!(sender is IKeyCodeProvider keycontrol) || _isDown) return;

            e.Handled = true;
            _isDown = true;
            await WaitKeyReleased(keycontrol.Code,
                keycontrol.SecondaryCode
                ?? (e.ChangedButton == MouseButton.Left
                    ? (SpectrumKeyCode?) null
                    : SpectrumKeyCode.CShift));
        }

        /// <summary>
        /// Handle the event when the shift key has been clicked
        /// </summary>
        public async void OnSymShiftKeyClicked(object sender, MouseButtonEventArgs e)
        {
            if (!(sender is IKeyCodeProvider keycontrol) || _isDown) return;

            e.Handled = true;
            _isDown = true;
            await WaitKeyReleased(keycontrol.Code, SpectrumKeyCode.SShift);
        }

        /// <summary>
        /// Handle the event when the extended key has been clicked
        /// </summary>
        public async void OnExtKeyClicked(object sender, MouseButtonEventArgs e)
        {
            if (!(sender is IKeyCodeProvider keycontrol) || _isDown) return;

            e.Handled = true;
            _isDown = true;
            await SetExtendedModeAsync();
            await WaitKeyReleased(keycontrol.Code);
        }

        /// <summary>
        /// Handle the event when the extended shift key has been clicked
        /// </summary>
        public async void OnExtShiftKeyClicked(object sender, MouseButtonEventArgs e)
        {
            if (!(sender is IKeyCodeProvider keycontrol) || _isDown) return;

            e.Handled = true;
            _isDown = true;
            await SetExtendedModeAsync();
            await WaitKeyReleased(keycontrol.Code, SpectrumKeyCode.SShift);
        }

        /// <summary>
        /// Handle the event when a numeric control key has been clicked
        /// </summary>
        public async void OnNumericControlKeyClicked(object sender, MouseButtonEventArgs e)
        {
            if (!(sender is IKeyCodeProvider keycontrol) || _isDown) return;

            e.Handled = true;
            _isDown = true;
            await SetExtendedModeAsync();
            await WaitKeyReleased(keycontrol.Code, e.ChangedButton == MouseButton.Left
                ? (SpectrumKeyCode?)null
                : SpectrumKeyCode.CShift);
        }

        /// <summary>
        /// Handle the event when the graphics key has been clicked
        /// </summary>
        public async void OnGraphicsControlKeyClicked(object sender, MouseButtonEventArgs e)
        {
            if (!(sender is IKeyCodeProvider keycontrol) || _isDown) return;

            e.Handled = true;
            _isDown = true;
            var set = await SetGraphicsModeAsync();
            await WaitKeyReleased(keycontrol.Code);
            if (set)
            {
                await ReleaseGraphicsModeAsync();
            }
        }

        /// <summary>
        /// Handle the event when the graphics key has been clicked
        /// </summary>
        public async void OnNumericShiftKeyClicked(object sender, MouseButtonEventArgs e)
        {
            if (!(sender is IKeyCodeProvider keycontrol) || _isDown) return;

            e.Handled = true;
            _isDown = true;
            await ReleaseGraphicsModeAsync();
            await WaitKeyReleased(keycontrol.Code, SpectrumKeyCode.SShift);
        }

        /// <summary>
        /// Handle the event when the key has been released
        /// </summary>
        public void OnKeyReleased(object sender, MouseButtonEventArgs e)
        {
            _isDown = false;
            e.Handled = true;
        }

        /// <summary>
        /// Waits while the currently pressed key is released
        /// </summary>
        /// <param name="code">Primary key code</param>
        /// <param name="secondaryCode">Secondary key code</param>
        private async Task WaitKeyReleased(SpectrumKeyCode code, SpectrumKeyCode? secondaryCode = null)
        {
            var refreshPeriod = Keyboard.RefreshPeriod;
            await Task.Delay(refreshPeriod);
            do
            {
                Keyboard.QueueKeyStroke(2, code, secondaryCode);
                await Task.Delay(refreshPeriod);
                
            } while (_isDown);

            // --- Put the focus back to the ZX Spectrum emulator tool window
            var emuWindow = SpectNetPackage.Default.GetToolWindow<SpectrumEmulator.SpectrumEmulatorToolWindow>();
            if (emuWindow?.IsVisible == true)
            {
                var frame = (IVsWindowFrame)emuWindow.Frame;
                frame.Show();
            }
        }

        /// <summary>
        /// Sets the keyboard in Graphics mode
        /// </summary>
        private async Task<bool> SetGraphicsModeAsync()
        {
            if (!GetModeValue(out var modeVal)) return false;
            if ((modeVal & 0x02) != 0) return false;

            Keyboard.QueueKeyStroke(2, SpectrumKeyCode.N9, SpectrumKeyCode.CShift);
            await Task.Delay(Keyboard.RefreshPeriod*2);
            return true;
        }

        /// <summary>
        /// Remove the keyboard from Graphics mode
        /// </summary>
        private async Task ReleaseGraphicsModeAsync()
        {
            await Task.Delay(Keyboard.RefreshPeriod);
            if (!GetModeValue(out var modeVal)) return;
            if ((modeVal & 0x02) == 0) return;

            Keyboard.QueueKeyStroke(2, SpectrumKeyCode.N9, SpectrumKeyCode.CShift);
            await Task.Delay(Keyboard.RefreshPeriod*2);
        }

        /// <summary>
        /// Sets the keyboard in Extended mode
        /// </summary>
        private async Task SetExtendedModeAsync()
        {
            if (!GetModeValue(out var modeVal)) return;
            if ((modeVal & 0x01) != 0) return;

            Keyboard.QueueKeyStroke(2, SpectrumKeyCode.SShift, SpectrumKeyCode.CShift);
            await Task.Delay(Keyboard.RefreshPeriod);
            Keyboard.QueueKeyStroke(2, SpectrumKeyCode.SShift, SpectrumKeyCode.CShift);
            await Task.Delay(Keyboard.RefreshPeriod);
        }

        /// <summary>
        /// Gets the value of the MODE system variable
        /// </summary>
        /// <param name="modeValue">Value of the system variable</param>
        /// <returns>True, if value obtained; otherwise, false</returns>
        private bool GetModeValue(out ushort? modeValue)
        {
            modeValue = null;
            return SpectNetPackage.Default.EmulatorViewModel.MachineState == VmState.Running 
                && Keyboard.GetModeValue(out modeValue);
        }
    }
}

<|start_filename|>v2/Core/Spect.Net.SpectrumEmu/Devices/Memory/Spectrum48MemoryDevice.cs<|end_filename|>
﻿using Spect.Net.SpectrumEmu.Abstraction.Devices;
using Spect.Net.SpectrumEmu.Utility;

namespace Spect.Net.SpectrumEmu.Devices.Memory
{
    /// <summary>
    /// This device represents the Spectrum 48 memory device
    /// </summary>
    public sealed class Spectrum48MemoryDevice : ContendedMemoryDeviceBase
    {
        private byte[] _memory;

        /// <summary>
        /// Resets this device by filling the memory with 0xFF
        /// </summary>
        public override void Reset()
        {
            for (var i = 0; i < _memory.Length; i++)
            {
                Write((ushort)i, 0xFF);
            }
        }

        /// <summary>
        /// Gets the state of the device so that the state can be saved
        /// </summary>
        /// <returns>The object that describes the state of the device</returns>
        public override IDeviceState GetState() => new Spectrum48MemoryDeviceState(this);

        /// <summary>
        /// Sets the state of the device from the specified object
        /// </summary>
        /// <param name="state">Device state</param>
        public override void RestoreState(IDeviceState state) => state.RestoreDeviceState(this);

        /// <summary>
        /// Signs that the device has been attached to the Spectrum virtual machine
        /// </summary>
        public override void OnAttachedToVm(ISpectrumVm hostVm)
        {
            base.OnAttachedToVm(hostVm);
            _memory = new byte[0x10000];
        }

        /// <summary>
        /// Reads the memory at the specified address
        /// </summary>
        /// <param name="addr">Memory address</param>
        /// <param name="suppressContention">Indicates non-contended read operation</param>
        /// <returns>Byte read from the memory</returns>
        public override byte Read(ushort addr, bool suppressContention = false)
        {
            var value = _memory[addr];
            if (suppressContention) return value;

            ContentionWait(addr);
            return value;
        }

        /// <summary>
        /// Sets the memory value at the specified address
        /// </summary>
        /// <param name="addr">Memory address</param>
        /// <param name="value">Memory value to write</param>
        /// <param name="supressContention">
        /// Indicates non-contended write operation
        /// </param>
        public override void Write(ushort addr, byte value, bool supressContention = false)
        {
            // ReSharper disable once SwitchStatementMissingSomeCases
            switch (addr & 0xC000)
            {
                case 0x0000:
                    // --- ROM cannot be overwritten
                    return;
                case 0x4000:
                    if (!supressContention)
                    {
                        ApplyDelay();
                    }
                    break;
            }
            _memory[addr] = value;
        }

        /// <summary>
        /// Gets the buffer that holds memory data
        /// </summary>
        /// <returns></returns>
        public override byte[] CloneMemory()
        {
            var clone = new byte[0x10000];
            _memory.CopyTo(clone, 0);
            return clone;
        }

        /// <summary>
        /// Fills up the memory from the specified buffer
        /// </summary>
        /// <param name="buffer">Contains the row data to fill up the memory</param>
        public override void CopyRom(byte[] buffer)
        {
            buffer?.CopyTo(_memory, 0);
        }

        /// <summary>
        /// Selects the ROM with the specified index
        /// </summary>
        /// <param name="romIndex">Index of the ROM</param>
        public override void SelectRom(int romIndex)
        {
            // --- Spectrum 48 does not support banks, we do nothing
        }

        /// <summary>
        /// Retrieves the index of the selected ROM
        /// </summary>
        /// <returns>
        /// As Spectrum 48K does not support paging, 
        /// this method always return 0
        /// </returns>
        public override int GetSelectedRomIndex() => 0;

        /// <summary>
        /// Pages in the selected bank into the specified slot
        /// </summary>
        /// <param name="slot">Index of the slot</param>
        /// <param name="bank">Index of the bank to page in</param>
        /// <param name="bank16Mode">
        /// True: 16K banks; False: 8K banks
        /// </param>
        public override void PageIn(int slot, int bank, bool bank16Mode = true)
        {
            // --- Spectrum 48 does not support banks, we do nothing
        }

        /// <summary>
        /// Gets the bank paged in to the specified slot
        /// </summary>
        /// <param name="slot">Slot index</param>
        /// <param name="bank16Mode">
        /// True: 16K banks; False: 8K banks
        /// </param>
        /// <returns>
        /// The index of the bank that is pages into the slot
        /// </returns>
        public override int GetSelectedBankIndex(int slot, bool bank16Mode = true) => 0;

        /// <summary>
        /// Gets the data for the specfied ROM page
        /// </summary>
        /// <param name="romIndex">Index of the ROM</param>
        /// <returns>
        /// The buffer that holds the binary data for the specified ROM page
        /// </returns>
        public override byte[] GetRomBuffer(int romIndex)
        {
            var rom = new byte[0x4000];
            for (var i = 0; i < 0x4000; i++) rom[i] = _memory[i];
            return rom;
        }

        /// <summary>
        /// Gets the data for the specfied RAM bank
        /// </summary>
        /// <param name="bankIndex">Index of the RAM bank</param>
        /// <param name="bank16Mode">
        /// True: 16K banks; False: 8K banks
        /// </param>
        /// <returns>
        /// The buffer that holds the binary data for the specified RAM bank
        /// </returns>
        /// <remark>
        /// This implementation ignores the bank16Mode parameter
        /// </remark>
        public override byte[] GetRamBank(int bankIndex, bool bank16Mode = true)
        {
            var ram = new byte[0xC000];
            for (var i = 0; i < 0xC000; i++) ram[i] = _memory[i + 0x4000];
            return ram;
        }

        /// <summary>
        /// Gets the location of the address
        /// </summary>
        /// <param name="addr">Address to check the location</param>
        /// <returns>
        /// IsInRom: true, if the address is in ROM
        /// Index: ROM/RAM bank index
        /// Address: Index within the bank
        /// </returns>
        public override (bool IsInRom, int Index, ushort Address) GetAddressLocation(ushort addr)
        {
            return addr < 0x4000
                ? (true, 0, addr)
                : (false, 0, (ushort)(addr - 0x4000));
        }

        /// <summary>
        /// Checks if the RAM bank with the specified index is paged in
        /// </summary>
        /// <param name="index">RAM bank index</param>
        /// <param name="baseAddress">0x4000</param>
        /// <returns>True</returns>
        /// <remarks>The Single RAM bank of Spectrum 48 is always paged in</remarks>
        public override bool IsRamBankPagedIn(int index, out ushort baseAddress)
        {
            baseAddress = 0x4000;
            return false;
        }

        /// <summary>
        /// Spectrum 48 memory device state
        /// </summary>
        public class Spectrum48MemoryDeviceState : IDeviceState
        {
            public byte[] Memory { get; set; }

            // ReSharper disable once UnusedMember.Global
            public Spectrum48MemoryDeviceState()
            {
            }

            public Spectrum48MemoryDeviceState(Spectrum48MemoryDevice device)
            {
                Memory = CompressionHelper.CompressBytes(device._memory);
            }

            /// <summary>
            /// Restores the dvice state from this state object
            /// </summary>
            /// <param name="device">Device instance</param>
            public void RestoreDeviceState(IDevice device)
            {
                if (!(device is Spectrum48MemoryDevice sp48)) return;

                sp48._memory = CompressionHelper.DecompressBytes(Memory);
            }
        }
    }
}

<|start_filename|>v2/Assembler/Spect.Net.Assembler/Assembler/Z80Assembler.Expressions.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Linq;
using Spect.Net.Assembler.SyntaxTree;
using Spect.Net.Assembler.SyntaxTree.Expressions;
// ReSharper disable IdentifierTypo

// ReSharper disable InlineOutVariableDeclaration

namespace Spect.Net.Assembler.Assembler
{
    /// <summary>
    /// This class implements the Z80 assembler
    /// </summary>
    public partial class Z80Assembler: IEvaluationContext
    {
        /// <summary>
        /// Indicates if the assembler is used in case sensitive mode
        /// </summary>
        public bool IsCaseSensitive => _options?.UseCaseSensitiveSymbols ?? false;

        /// <summary>
        /// Gets the current assembly address
        /// </summary>
        ushort IEvaluationContext.GetCurrentAddress() => GetCurrentInstructionAddress();

        /// <summary>
        /// Gets the value of the specified symbol
        /// </summary>
        /// <param name="symbol">Symbol name</param>
        /// <param name="startFromGlobal">Should resolution start from global scope?</param>
        /// <returns>
        /// Null, if the symbol cannot be found; otherwise, the symbol's value
        /// </returns>
        public (ExpressionValue ExprValue, IHasUsageInfo UsageInfo) GetSymbolValue(string symbol, bool startFromGlobal = false)
        {
            (ExpressionValue ExprValue, IHasUsageInfo UsageInfo) resolved;
            if (startFromGlobal)
            {
                // --- Most be a compound symbol
                resolved = CurrentModule.ResolveCompoundSymbol(symbol, true);
            }
            else if (symbol.Contains("."))
            {
                resolved = CurrentModule.ResolveCompoundSymbol(symbol, false);
                if (resolved.ExprValue == null)
                {
                    resolved = CurrentModule.ResolveSimpleSymbol(symbol);
                }
            }
            else
            {
                resolved = CurrentModule.ResolveSimpleSymbol(symbol);
            }
            return resolved;
        }

        /// <summary>
        /// Gets the current loop counter value
        /// </summary>
        public ExpressionValue GetLoopCounterValue()
        {
            if (IsInGlobalScope)
            {
                ReportError(Errors.Z0412, CurrentSourceLine);
                return ExpressionValue.Error;
            }

            var scope = CurrentModule.LocalScopes.Peek();
            if (!scope.IsLoopScope)
            {
                ReportError(Errors.Z0412, CurrentSourceLine);
                return ExpressionValue.Error;
            }

            return new ExpressionValue(scope.LoopCounter);
        }

        #region Symbol handler methods

        /// <summary>
        /// Tests if the current assembly instruction is in the global scope of the current module
        /// </summary>
        public bool IsInGlobalScope => CurrentModule.LocalScopes.Count(s => !s.IsTemporaryScope) == 0;

        /// <summary>
        /// Checks is the specified error should be reported in the local scope
        /// </summary>
        /// <param name="errorCode">Error code to check</param>
        /// <returns></returns>
        public bool ShouldReportErrorInCurrentScope(string errorCode)
        {
            if (IsInGlobalScope) return true;
            var localScope = CurrentModule.LocalScopes.Peek();
            if (localScope.OwnerScope != null)
            {
                localScope = localScope.OwnerScope;
            }
            return !localScope.IsErrorReported(errorCode);
        }

        /// <summary>
        /// Checks if the specified symbol exists
        /// </summary>
        /// <param name="symbol">Symbol to check</param>
        /// <returns></returns>
        public bool SymbolExists(string symbol)
        {
            var lookup = CurrentModule.LocalScopes.Count > 0
                ? CurrentModule.LocalScopes.Peek().Symbols
                : CurrentModule.Symbols;
            return lookup.TryGetValue(symbol, out var symbolInfo) && symbolInfo.Type == SymbolType.Label;
        }

        /// <summary>
        /// Adds a symbol to the current scope
        /// </summary>
        /// <param name="symbol"></param>
        /// <param name="line">Assembly line</param>
        /// <param name="value"></param>
        public void AddSymbol(string symbol, SourceLineBase line, ExpressionValue value)
        {
            Dictionary<string, AssemblySymbolInfo> GetSymbols() =>
                CurrentModule.LocalScopes.Count > 0
                    ? CurrentModule.LocalScopes.Peek().Symbols
                    : CurrentModule.Symbols;

            var currentScopeIsTemporary = CurrentModule.LocalScopes.Count != 0 
                && CurrentModule.LocalScopes.Peek().IsTemporaryScope;
            var symbolIsTemporary = symbol.StartsWith("`");

            var lookup = GetSymbols();
            if (currentScopeIsTemporary)
            {
                if (!symbolIsTemporary)
                {
                    // --- Remove the previous temporary scope
                    var tempScope = CurrentModule.LocalScopes.Peek();
                    FixupSymbols(tempScope.Fixups, tempScope.Symbols, false);
                    CurrentModule.LocalScopes.Pop();

                    lookup = GetSymbols();
                }
            }
            else
            {
                // --- Create a new temporary scope
                CurrentModule.LocalScopes.Push(new SymbolScope(null, IsCaseSensitive)
                {
                    IsTemporaryScope = true
                });
                if (symbolIsTemporary)
                {
                    // --- Temporary symbol should go into the new temporary scope
                    lookup = GetSymbols();
                }
            }

            if (CurrentModule.LocalScopes.Count > 0)
            {
                // --- We are in a local scope, get the next non-temporary scope
                var localScopes = CurrentModule.LocalScopes;
                var scope = localScopes.Peek();
                if (scope.IsTemporaryScope)
                {
                    var tmpScope = localScopes.Pop();
                    scope = localScopes.Count > 0 ? localScopes.Peek() : null;
                    localScopes.Push(tmpScope);
                }

                if (scope?.LocalSymbolBookings.Count > 0)
                {
                    // --- We already booked local symbols
                    if (!scope.LocalSymbolBookings.Contains(symbol))
                    {
                        lookup = CurrentModule.Symbols;
                    }
                }
                else
                {
                    if (_options.ProcExplicitLocalsOnly)
                    {
                        lookup = CurrentModule.Symbols;
                    }
                }
            }

            // --- Check for already defined symbols
            if (lookup.TryGetValue(symbol, out var symbolInfo) && symbolInfo.Type == SymbolType.Label)
            {
                ReportError(Errors.Z0040, line, symbol);
                return;
            }

            lookup.Add(symbol, AssemblySymbolInfo.CreateLabel(symbol, value));
        }

        /// <summary>
        /// Checks if the variable with the specified name exists
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public bool VariableExists(string name)
        {
            // --- Search for the variable from inside out
            foreach (var scope in CurrentModule.LocalScopes)
            {
                if (scope.Symbols.TryGetValue(name, out var symbolInfo) && symbolInfo.Type == SymbolType.Var)
                {
                    return true;
                }
            }

            // --- Check the global scope
            return CurrentModule.Symbols.TryGetValue(name, out var globalSymbol) 
                && globalSymbol.Type == SymbolType.Var;
        }

        /// <summary>
        /// Sets the value of a variable
        /// </summary>
        /// <param name="name">Variable name</param>
        /// <param name="value">Variable value</param>
        public void SetVariable(string name, ExpressionValue value)
        {
            // --- Search for the variable from inside out
            foreach (var scope in CurrentModule.LocalScopes)
            {
                if (scope.Symbols.TryGetValue(name, out var symbolInfo) && symbolInfo.Type == SymbolType.Var)
                {
                    symbolInfo.Value = value;
                    return;
                }
            }

            // --- Check the global scope
            if (CurrentModule.Symbols.TryGetValue(name, out var globalSymbol) 
                && globalSymbol.Type == SymbolType.Var)
            {
                globalSymbol.Value = value;
                return;
            }

            // --- The variable does not exist, create it in the current scope
            var vars = CurrentModule.LocalScopes.Count > 0
                ? CurrentModule.LocalScopes.Peek().Symbols
                : CurrentModule.Symbols;
            vars[name] = AssemblySymbolInfo.CreateVar(name, value);
        }

        #endregion

        #region Evaluation methods

        /// <summary>
        /// Sets the current value of the symbol to the specified value
        /// </summary>
        /// <param name="symbol">Symbol name</param>
        /// <param name="value">Symbol value</param>
        public void SetSymbolValue(string symbol, ExpressionValue value)
        {
            if (CurrentModule.Symbols.TryGetValue(symbol, out var symbolInfo))
            {
                symbolInfo.Value = value;
            }
            else
            {
                CurrentModule.Symbols.Add(symbol, AssemblySymbolInfo.CreateLabel(symbol, value));
            }
        }

        /// <summary>
        /// Evaluates the specified expression.
        /// </summary>
        /// <param name="opLine">Assembly line with operation</param>
        /// <param name="expr">Expression to evaluate</param>
        /// <returns>
        /// Null, if the expression cannot be evaluated, or evaluation 
        /// results an error (e.g. divide by zero)
        /// </returns>
        public ExpressionValue Eval(SourceLineBase opLine, ExpressionNode expr)
        {
            if (expr == null)
            {
                throw new ArgumentNullException(nameof(expr));
            }
            if (!expr.ReadyToEvaluate(this)) return ExpressionValue.NonEvaluated;
            ExpressionNode.ClearErrors();
            var result = expr.Evaluate(this);

            // --- Certain symbols may not bee be evaluated
            if (result == ExpressionValue.Error)
            {
                ReportError(Errors.Z0200, opLine, expr.EvaluationError);
            }
            return result;
        }

        /// <summary>
        /// Evaluates the specified expression.
        /// </summary>
        /// <param name="opLine">Assembly line with operation</param>
        /// <param name="expr">Expression to evaluate</param>
        /// <returns>
        /// Null, if the expression cannot be evaluated, or evaluation 
        /// results an error (e.g. divide by zero)
        /// </returns>
        public ExpressionValue EvalImmediate(SourceLineBase opLine, ExpressionNode expr)
        {
            if (expr == null)
            {
                throw new ArgumentNullException(nameof(expr));
            }
            ExpressionNode.ClearErrors();
            if (!expr.ReadyToEvaluate(this))
            {
                ReportError(Errors.Z0201, opLine, ExpressionNode.SymbolErrors);
                return ExpressionValue.NonEvaluated;
            }
            var result = expr.Evaluate(this);
            if (result.IsValid)
            {
                return result;
            }

            ReportError(Errors.Z0200, opLine, expr.EvaluationError);
            return ExpressionValue.Error;
        }

        #endregion

        #region Fixup methods

        /// <summary>
        /// Records fixup information
        /// </summary>
        /// <param name="opLine">The operation line</param>
        /// <param name="type">Fixup type</param>
        /// <param name="expression">Fixup expression</param>
        /// <param name="label">Optional EQU label</param>
        /// <param name="structeBytes">Optional structure bytes</param>
        /// <param name="offset">Fixup offset, if not the current position</param>
        private void RecordFixup(SourceLineBase opLine, FixupType type, ExpressionNode expression, 
            string label = null, Dictionary<ushort, byte> structeBytes = null, ushort? offset = null)
        {
            var fixupOffset = CurrentSegment.CurrentOffset;

            // --- Translate field invocation fixups so that field-related fixups will be
            // --- processed only after other fixups.
            if (IsInStructInvocation)
            {
                fixupOffset = _currentStructStartOffset + _currentStructOffset;
                if (type == FixupType.Bit8)
                {
                    type = FixupType.FieldBit8;
                }
                else if (type == FixupType.Bit16)
                {
                    type = FixupType.FieldBit16;
                }
            }

            // --- Create to fixup entry to resolve
            var fixup = new FixupEntry(this, CurrentModule, opLine, type, Output.Segments.Count - 1,
                offset ?? fixupOffset,
                expression, label, structeBytes);

            // --- Record fixups in every local scope up to the root
            foreach (var scope in CurrentModule.LocalScopes)
            {
                scope.Fixups.Add(fixup);
            }

            // --- Record fixup in every module up to the root
            var currentModule = CurrentModule;
            while (currentModule != null)
            {
                currentModule.Fixups.Add(fixup);
                currentModule = currentModule.ParentModule;
            }
        }

        /// <summary>
        /// Fixes the unresolved symbol in the last phase of compilation
        /// </summary>
        /// <returns></returns>
        private bool FixupSymbols()
        {
            // --- Go through all scopes from inside to outside
            foreach (var scope in CurrentModule.LocalScopes)
            {
                if (scope.Fixups.Count == 0) continue;
                if (FixupSymbols(scope.Fixups, scope.Symbols, false))
                {
                    // --- Successful fixup in the local scope
                    break;
                }
            }

            return FixupSymbols(CurrentModule.Fixups, CurrentModule.Symbols, true);
        }

        /// <summary>
        /// Tries to create fixups in the specified scope
        /// </summary>
        /// <param name="fixups">Fixup entries in the scope</param>
        /// <param name="symbols">Symbols in the scope</param>
        /// <param name="signNotEvaluable">Raise error if the symbol is not evaluable</param>
        /// <returns></returns>
        private bool FixupSymbols(IReadOnlyCollection<FixupEntry> fixups, 
            IDictionary<string, AssemblySymbolInfo> symbols, 
            bool signNotEvaluable)
        {
            // --- #1: fix the .equ values
            var success = true;
            foreach (var equ in fixups.Where(f => f.Type == FixupType.Equ && !f.Resolved))
            {
                if (EvaluateFixupExpression(equ, false, signNotEvaluable, out var value))
                {
                    if (symbols.TryGetValue(equ.Label, out var symbolInfo))
                    {
                        symbolInfo.Value = value;
                    }
                    else
                    {
                        symbols.Add(equ.Label, AssemblySymbolInfo.CreateLabel(equ.Label, value));
                    }
                }
                else
                {
                    success = false;
                }
            }

            // --- #2: fix Bit8, Bit16, Jr, Ent, Xent
            foreach (var fixup in fixups.Where(f => !f.Resolved && 
                (f.Type == FixupType.Bit8 || f.Type == FixupType.Bit16 || f.Type == FixupType.Jr
                 || f.Type == FixupType.Ent || f.Type == FixupType.Xent)))
            {
                if (EvaluateFixupExpression(fixup, true, signNotEvaluable, out var value))
                {
                    var segment = Output.Segments[fixup.SegmentIndex];
                    var emittedCode = segment.EmittedCode;
                    switch (fixup.Type)
                    {
                        case FixupType.Bit8:
                            emittedCode[fixup.Offset] = value.AsByte();
                            break;

                        case FixupType.Bit16:
                            emittedCode[fixup.Offset] = value.AsByte();
                            emittedCode[fixup.Offset + 1] = (byte)(value.AsWord() >> 8);
                            break;

                        case FixupType.Jr:
                            // --- Check for Relative address
                            var currentAssemblyAddress = segment.StartAddress
                                + ((ushort)(segment.StartAddress + fixup.Offset) >= segment.DispPragmaOffset ? segment.Displacement ?? 0 : 0)
                                + fixup.Offset;
                            var dist = (short)(ushort)(value.AsWord() - (currentAssemblyAddress + 2));
                            if (dist < -128 || dist > 127)
                            {
                                ReportError(Errors.Z0022, fixup.SourceLine, dist);
                                success = false;
                                break;
                            }
                            emittedCode[fixup.Offset + 1] = (byte)dist;
                            break;

                        case FixupType.Ent:
                            Output.EntryAddress = value.AsWord();
                            break;

                        case FixupType.Xent:
                            Output.ExportEntryAddress = value.AsWord();
                            break;
                    }
                }
                else
                {
                    success = false;
                }
            }

            // --- #3: fix Struct
            foreach (var fixup in fixups.Where(f => !f.Resolved && f.Type == FixupType.Struct))
            {
                var segment = Output.Segments[fixup.SegmentIndex];
                var emittedCode = segment.EmittedCode;

                // --- Override structure bytes
                foreach (var entry in fixup.StructBytes)
                {
                    var offset = (ushort)(fixup.Offset + entry.Key);
                    emittedCode[offset] = entry.Value;
                }
            }

            // --- #4: fix FieldBit8, and FieldBit16
            foreach (var fixup in fixups.Where(f => !f.Resolved 
                && (f.Type == FixupType.FieldBit8 || f.Type == FixupType.FieldBit16)))
            {
                if (EvaluateFixupExpression(fixup, true, signNotEvaluable, out var value))
                {
                    var segment = Output.Segments[fixup.SegmentIndex];
                    var emittedCode = segment.EmittedCode;

                    switch (fixup.Type)
                    {
                        case FixupType.FieldBit8:
                            emittedCode[fixup.Offset] = value.AsByte();
                            break;

                        case FixupType.FieldBit16:
                            emittedCode[fixup.Offset] = value.AsByte();
                            emittedCode[fixup.Offset + 1] = (byte)(value.AsWord() >> 8);
                            break;
                    }
                }
                else
                {
                    success = false;
                }
            }
            return success;
        }

        /// <summary>
        /// Evaluates the fixup entry
        /// </summary>
        /// <param name="fixup"></param>
        /// <param name="numericOnly">Signs if only numeric expressions are accepted</param>
        /// <param name="signNotEvaluable">Raise error if the symbol is not evaluable</param>
        /// <param name="exprValue">The value of the expression</param>
        /// <returns>True, if evaluation successful; otherwise, false</returns>
        private bool EvaluateFixupExpression(FixupEntry fixup, bool numericOnly, bool signNotEvaluable, 
            out ExpressionValue exprValue)
        {
            exprValue = new ExpressionValue(0L);
            ExpressionNode.ClearErrors();
            if (!fixup.Expression.ReadyToEvaluate(fixup))
            {
                if (signNotEvaluable)
                {
                    ReportError(Errors.Z0201, fixup.SourceLine, ExpressionNode.SymbolErrors);
                }
                return false;
            }

            // --- Now resolve the fixup
            exprValue = fixup.Expression.Evaluate(fixup);
            fixup.Resolved = true;

            // --- Check, if resolution was successful
            if (fixup.Expression.EvaluationError != null)
            {
                ReportError(Errors.Z0200, fixup.SourceLine, fixup.Expression.EvaluationError);
                return false;
            }
            if (numericOnly && exprValue.Type == ExpressionValueType.String)
            {
                ReportError(Errors.Z0305, fixup.SourceLine);
                return false;
            }

            // --- Ok, no error
            return true;
        }

        #endregion
    }
}

<|start_filename|>v2/Core/Spect.Net.SpectrumEmu/Devices/Ports/Spectrum128PortDevice.cs<|end_filename|>
﻿using Spect.Net.SpectrumEmu.Abstraction.Devices;
using Spect.Net.SpectrumEmu.Abstraction.Devices.Screen;

namespace Spect.Net.SpectrumEmu.Devices.Ports
{
    /// <summary>
    /// This class represents the port device used by the Spectrum 128 virtual machine
    /// </summary>
    public class Spectrum128PortDevice: UlaGenericPortDeviceBase
    {
        private readonly Spectrum128MemoryPagePortHandler _memoryHandler;
        protected ISoundDevice SoundDevice;

        /// <summary>
        /// Indicates if paging is enabled or not
        /// </summary>
        /// <remarks>
        /// Port 0x7FFD, Bit 5: 
        /// False - paging is enables
        /// True - paging is not enabled and further output to the port
        /// is ignored until the computer is reset
        /// </remarks>
        public bool PagingEnabled { get; protected set; }

        public Spectrum128PortDevice()
        {
            Handlers.Add(new Spectrum48PortHandler(this));
            _memoryHandler = new Spectrum128MemoryPagePortHandler(this);
            Handlers.Add(_memoryHandler);
            Handlers.Add(new SoundRegisterIndexPortHandler(this));
            Handlers.Add(new SoundRegisterValuePortHandler(this));
        }

        /// <summary>
        /// Define how to handle an unattached port
        /// </summary>
        /// <param name="addr">Port address</param>
        /// <returns>Port value for the unhandled port address</returns>
        public override byte UnhandledRead(ushort addr)
        {
            var tact = HostVm.CurrentFrameTact % ScreenDevice.RenderingTactTable.Length;
            var rt = ScreenDevice.RenderingTactTable[tact];
            var memAddr = (ushort)0;
            switch (rt.Phase)
            {
                case ScreenRenderingPhase.BorderFetchPixel:
                case ScreenRenderingPhase.DisplayB1FetchB2:
                case ScreenRenderingPhase.DisplayB2FetchB1:
                    memAddr = rt.PixelByteToFetchAddress;
                    break;
                case ScreenRenderingPhase.BorderFetchPixelAttr:
                case ScreenRenderingPhase.DisplayB1FetchA2:
                case ScreenRenderingPhase.DisplayB2FetchA1:
                    memAddr = rt.AttributeToFetchAddress;
                    break;
            }

            if (memAddr == 0) return 0xFF;
            var readValue = MemoryDevice.Read(memAddr, true);
            return readValue;
        }

        /// <summary>
        /// Gets the state of the device so that the state can be saved
        /// </summary>
        /// <returns>The object that describes the state of the device</returns>
        public override IDeviceState GetState() => new Spectrum128PortDeviceState(this);

        /// <summary>
        /// Sets the state of the device from the specified object
        /// </summary>
        /// <param name="state">Device state</param>
        public override void RestoreState(IDeviceState state) => state.RestoreDeviceState(this);

        /// <summary>
        /// State of the Spectrum 128 port device
        /// </summary>
        public class Spectrum128PortDeviceState : IDeviceState
        {
            public bool PagingEnabled { get; set; }

            public Spectrum128PortDeviceState()
            {
            }

            public Spectrum128PortDeviceState(Spectrum128PortDevice device)
            {
                PagingEnabled = device._memoryHandler.PagingEnabled;
            }

            /// <summary>
            /// Restores the dvice state from this state object
            /// </summary>
            /// <param name="device">Device instance</param>
            public void RestoreDeviceState(IDevice device)
            {
                if (!(device is Spectrum128PortDevice sp128)) return;

                sp128._memoryHandler.PagingEnabled = PagingEnabled;
            }
        }
    }
}

<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/ToolWindows/SpectrumEmulator/KeyboardScanner.cs<|end_filename|>
﻿using Spect.Net.SpectrumEmu.Abstraction.Devices.Keyboard;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Input;
using WindowsKeyboard = System.Windows.Input.Keyboard;

namespace Spect.Net.VsPackage.ToolWindows.SpectrumEmulator
{
    /// <summary>
    /// This class is responsible for scanning the entire keyboard
    /// </summary>
    public class KeyboardScanner
    {
        // --- Keyboard layout codes to define separate key mappings for each of them
        private const string ENG_US_LAYOUT = "00000409";
        private const string HUN_LAYOUT = "0000040E";
        private const string HUN_101_LAYOUT = "0001040E";

        // --- You can create a default layout, provided you have non-implemented custom layout
        private const string DEFAULT_LAYOUT = "default";

        // --- Hungarian 101 Symbol Shift normal mappings
        private static readonly List<Key> s_Hun101SShiftNormal =
            new List<Key> 
            {
                Key.LeftShift, 
                Key.RightShift,
                Key.OemComma, 
                Key.OemPeriod, 
                Key.Decimal, 
                Key.Divide, 
                Key.Multiply,
                Key.Add, 
                Key.Subtract
            };

        // --- Hungarian 101 Caps Shift normal mappings
        private static readonly List<Key> s_Hun101CShiftNormal =
            new List<Key> 
            { 
                Key.RightAlt, 
                Key.Back,
                Key.Left, 
                Key.Up, 
                Key.Down, 
                Key.Right, 
                Key.Home
            };

        // --- Hungarian 101 Symbol Shift swapped mappings
        private static readonly List<Key> s_Hun101SShiftSwapped =
            new List<Key>
            {
                Key.RightAlt,
                Key.OemComma,
                Key.OemPeriod,
                Key.Decimal,
                Key.Divide,
                Key.Multiply,
                Key.Add,
                Key.Subtract
            };

        // --- Hungarian 101 Caps Shift swapped mappings
        private static readonly List<Key> s_Hun101CShiftSwapped =
            new List<Key>
            {
                Key.LeftShift,
                Key.RightShift,
                Key.Back,
                Key.Left,
                Key.Up,
                Key.Down,
                Key.Right,
                Key.Home
            };


        /// <summary>
        /// Maps Spectrum keys to the PC keyboard keys for Hungarian 101 keyboard layout
        /// </summary>
        /// <remarks>
        /// The key specifies the Spectrum keyboard code mapped to a physical key.
        /// The value is a collection of physical keys. If any of them changes 
        /// its state, the Spectrum key changes, too.
        /// </remarks>
        private static readonly Dictionary<SpectrumKeyCode, List<Key>> s_Hun101KeyMappings =
            new Dictionary<SpectrumKeyCode, List<Key>>
            {
                { SpectrumKeyCode.SShift, s_Hun101SShiftNormal },
                { SpectrumKeyCode.CShift, s_Hun101CShiftNormal },
                { SpectrumKeyCode.Space, new List<Key> { Key.Space} },
                { SpectrumKeyCode.Enter, new List<Key> { Key.Enter } },
                { SpectrumKeyCode.Q, new List<Key> { Key.Q } },
                { SpectrumKeyCode.W, new List<Key> { Key.W } },
                { SpectrumKeyCode.E, new List<Key> { Key.E } },
                { SpectrumKeyCode.R, new List<Key> { Key.R } },
                { SpectrumKeyCode.T, new List<Key> { Key.T } },
                { SpectrumKeyCode.Y, new List<Key> { Key.Y } },
                { SpectrumKeyCode.U, new List<Key> { Key.U } },
                { SpectrumKeyCode.I, new List<Key> { Key.I } },
                { SpectrumKeyCode.O, new List<Key> { Key.O } },
                { SpectrumKeyCode.P, new List<Key> { Key.P } },
                { SpectrumKeyCode.A, new List<Key> { Key.A } },
                { SpectrumKeyCode.S, new List<Key> { Key.S } },
                { SpectrumKeyCode.D, new List<Key> { Key.D } },
                { SpectrumKeyCode.F, new List<Key> { Key.F } },
                { SpectrumKeyCode.G, new List<Key> { Key.G } },
                { SpectrumKeyCode.H, new List<Key> { Key.H } },
                { SpectrumKeyCode.J, new List<Key> { Key.J, Key.Subtract } },
                { SpectrumKeyCode.K, new List<Key> { Key.K, Key.Add } },
                { SpectrumKeyCode.L, new List<Key> { Key.L } },
                { SpectrumKeyCode.Z, new List<Key> { Key.Z } },
                { SpectrumKeyCode.X, new List<Key> { Key.X } },
                { SpectrumKeyCode.C, new List<Key> { Key.C } },
                { SpectrumKeyCode.V, new List<Key> { Key.V, Key.Divide } },
                { SpectrumKeyCode.B, new List<Key> { Key.B, Key.Multiply } },
                { SpectrumKeyCode.N, new List<Key> { Key.N, Key.OemComma } },
                { SpectrumKeyCode.M, new List<Key> { Key.M, Key.OemPeriod, Key.Decimal } },
                { SpectrumKeyCode.N0, new List<Key> { Key.D0, Key.NumPad0, Key.Back } },
                { SpectrumKeyCode.N1, new List<Key> { Key.D1, Key.NumPad1, Key.Home } },
                { SpectrumKeyCode.N2, new List<Key> { Key.D2, Key.NumPad2 } },
                { SpectrumKeyCode.N3, new List<Key> { Key.D3, Key.NumPad3 } },
                { SpectrumKeyCode.N4, new List<Key> { Key.D4, Key.NumPad4 } },
                { SpectrumKeyCode.N5, new List<Key> { Key.D5, Key.NumPad5, Key.Left } },
                { SpectrumKeyCode.N6, new List<Key> { Key.D6, Key.NumPad6, Key.Down } },
                { SpectrumKeyCode.N7, new List<Key> { Key.D7, Key.NumPad7, Key.Up } },
                { SpectrumKeyCode.N8, new List<Key> { Key.D8, Key.NumPad8, Key.Right } },
                { SpectrumKeyCode.N9, new List<Key> { Key.D9, Key.NumPad9 } },
            };

        // --- Hungarian Symbol Shift normal mappings
        private static readonly List<Key> s_HunSShiftNormal =
            new List<Key> 
            { 
                Key.LeftShift, 
                Key.RightShift,
                Key.OemComma, 
                Key.OemPeriod, 
                Key.Decimal, 
                Key.Divide, 
                Key.Multiply,
                Key.Add, 
                Key.Subtract
            };

        // --- Hungarian Caps Shift normal mappings
        private static readonly List<Key> s_HunCShiftNormal =
            new List<Key> 
            { 
                Key.RightAlt, 
                Key.Back,
                Key.Left, 
                Key.Up, 
                Key.Down, 
                Key.Right, 
                Key.Home
            };

        // --- Hungarian Symbol Shift normal mappings
        private static readonly List<Key> s_HunSShiftSwapped =
            new List<Key>
            {
                Key.RightAlt,
                Key.OemComma,
                Key.OemPeriod,
                Key.Decimal,
                Key.Divide,
                Key.Multiply,
                Key.Add,
                Key.Subtract
            };

        // --- Hungarian Caps Shift normal mappings
        private static readonly List<Key> s_HunCShiftSwapped =
            new List<Key>
            {
                Key.LeftShift,
                Key.RightShift,
                Key.Back,
                Key.Left,
                Key.Up,
                Key.Down,
                Key.Right,
                Key.Home
            };

        /// <summary>
        /// Maps Spectrum keys to the PC keyboard keys for Hungarian keyboard layout
        /// </summary>
        /// <remarks>
        /// The key specifies the Spectrum keyboard code mapped to a physical key.
        /// The value is a collection of physical keys. If any of them changes 
        /// its state, the Spectrum key changes, too.
        /// </remarks>
        private static readonly Dictionary<SpectrumKeyCode, List<Key>> s_HunKeyMappings =
            new Dictionary<SpectrumKeyCode, List<Key>>
            {
                { SpectrumKeyCode.SShift, s_HunSShiftNormal },
                { SpectrumKeyCode.CShift, s_HunCShiftNormal },
                { SpectrumKeyCode.Space, new List<Key> { Key.Space} },
                { SpectrumKeyCode.Enter, new List<Key> { Key.Enter } },
                { SpectrumKeyCode.Q, new List<Key> { Key.Q } },
                { SpectrumKeyCode.W, new List<Key> { Key.W } },
                { SpectrumKeyCode.E, new List<Key> { Key.E } },
                { SpectrumKeyCode.R, new List<Key> { Key.R } },
                { SpectrumKeyCode.T, new List<Key> { Key.T } },
                { SpectrumKeyCode.Y, new List<Key> { Key.Z } },
                { SpectrumKeyCode.U, new List<Key> { Key.U } },
                { SpectrumKeyCode.I, new List<Key> { Key.I } },
                { SpectrumKeyCode.O, new List<Key> { Key.O } },
                { SpectrumKeyCode.P, new List<Key> { Key.P } },
                { SpectrumKeyCode.A, new List<Key> { Key.A } },
                { SpectrumKeyCode.S, new List<Key> { Key.S } },
                { SpectrumKeyCode.D, new List<Key> { Key.D } },
                { SpectrumKeyCode.F, new List<Key> { Key.F } },
                { SpectrumKeyCode.G, new List<Key> { Key.G } },
                { SpectrumKeyCode.H, new List<Key> { Key.H } },
                { SpectrumKeyCode.J, new List<Key> { Key.J, Key.Subtract } },
                { SpectrumKeyCode.K, new List<Key> { Key.K, Key.Add } },
                { SpectrumKeyCode.L, new List<Key> { Key.L } },
                { SpectrumKeyCode.Z, new List<Key> { Key.Y } },
                { SpectrumKeyCode.X, new List<Key> { Key.X } },
                { SpectrumKeyCode.C, new List<Key> { Key.C } },
                { SpectrumKeyCode.V, new List<Key> { Key.V, Key.Divide } },
                { SpectrumKeyCode.B, new List<Key> { Key.B, Key.Multiply } },
                { SpectrumKeyCode.N, new List<Key> { Key.N, Key.OemComma } },
                { SpectrumKeyCode.M, new List<Key> { Key.M, Key.OemPeriod, Key.Decimal } },
                { SpectrumKeyCode.N0, new List<Key> { Key.D0, Key.NumPad0, Key.Back } },
                { SpectrumKeyCode.N1, new List<Key> { Key.D1, Key.NumPad1, Key.Home } },
                { SpectrumKeyCode.N2, new List<Key> { Key.D2, Key.NumPad2 } },
                { SpectrumKeyCode.N3, new List<Key> { Key.D3, Key.NumPad3 } },
                { SpectrumKeyCode.N4, new List<Key> { Key.D4, Key.NumPad4 } },
                { SpectrumKeyCode.N5, new List<Key> { Key.D5, Key.NumPad5, Key.Left } },
                { SpectrumKeyCode.N6, new List<Key> { Key.D6, Key.NumPad6, Key.Down } },
                { SpectrumKeyCode.N7, new List<Key> { Key.D7, Key.NumPad7, Key.Up } },
                { SpectrumKeyCode.N8, new List<Key> { Key.D8, Key.NumPad8, Key.Right } },
                { SpectrumKeyCode.N9, new List<Key> { Key.D9, Key.NumPad9 } },
            };

        // --- English US Symbol Shift normal mappings
        private static readonly List<Key> s_EngUsSShiftNormal =
            new List<Key> 
            { 
                Key.LeftShift, 
                Key.RightShift,
                Key.OemComma, 
                Key.OemPeriod, 
                Key.Decimal, 
                Key.Divide, 
                Key.Multiply,
                Key.Add, 
                Key.Subtract
            };

        // --- English US Caps Shift normal mappings
        private static readonly List<Key> s_EngUsCShiftNormal =
            new List<Key> 
            { 
                Key.RightAlt, 
                Key.Back,
                Key.Left,
                Key.Up,
                Key.Down,
                Key.Right,
                Key.Home
            };

        // --- English US Symbol Shift swapped mappings
        private static readonly List<Key> s_EngUsSShiftSwapped =
            new List<Key>
            {
                Key.RightAlt,
                Key.OemComma,
                Key.OemPeriod,
                Key.Decimal,
                Key.Divide,
                Key.Multiply,
                Key.Add,
                Key.Subtract
            };

        // --- English US Caps Shift swapped mappings
        private static readonly List<Key> s_EngUsCShiftSwapped =
            new List<Key>
            {
                Key.LeftShift,
                Key.RightShift,
                Key.Back,
                Key.Left,
                Key.Up,
                Key.Down,
                Key.Right,
                Key.Home
            };

        /// <summary>
        /// Maps Spectrum keys to the PC keyboard keys for English US keyboard layout
        /// </summary>
        /// <remarks>
        /// The key specifies the Spectrum keyboard code mapped to a physical key.
        /// The value is a collection of physical keys. If any of them changes 
        /// its state, the Spectrum key changes, too.
        /// </remarks>
        private static readonly Dictionary<SpectrumKeyCode, List<Key>> s_EngUsKeyMappings =
            new Dictionary<SpectrumKeyCode, List<Key>>
            {
                { SpectrumKeyCode.SShift, s_EngUsSShiftNormal },
                { SpectrumKeyCode.CShift, s_EngUsCShiftNormal },
                { SpectrumKeyCode.Space, new List<Key> { Key.Space} },
                { SpectrumKeyCode.Enter, new List<Key> { Key.Enter } },
                { SpectrumKeyCode.Q, new List<Key> { Key.Q } },
                { SpectrumKeyCode.W, new List<Key> { Key.W } },
                { SpectrumKeyCode.E, new List<Key> { Key.E } },
                { SpectrumKeyCode.R, new List<Key> { Key.R } },
                { SpectrumKeyCode.T, new List<Key> { Key.T } },
                { SpectrumKeyCode.Y, new List<Key> { Key.Y } },
                { SpectrumKeyCode.U, new List<Key> { Key.U } },
                { SpectrumKeyCode.I, new List<Key> { Key.I } },
                { SpectrumKeyCode.O, new List<Key> { Key.O } },
                { SpectrumKeyCode.P, new List<Key> { Key.P } },
                { SpectrumKeyCode.A, new List<Key> { Key.A } },
                { SpectrumKeyCode.S, new List<Key> { Key.S } },
                { SpectrumKeyCode.D, new List<Key> { Key.D } },
                { SpectrumKeyCode.F, new List<Key> { Key.F } },
                { SpectrumKeyCode.G, new List<Key> { Key.G } },
                { SpectrumKeyCode.H, new List<Key> { Key.H } },
                { SpectrumKeyCode.J, new List<Key> { Key.J, Key.Subtract } },
                { SpectrumKeyCode.K, new List<Key> { Key.K, Key.Add } },
                { SpectrumKeyCode.L, new List<Key> { Key.L } },
                { SpectrumKeyCode.Z, new List<Key> { Key.Z } },
                { SpectrumKeyCode.X, new List<Key> { Key.X } },
                { SpectrumKeyCode.C, new List<Key> { Key.C } },
                { SpectrumKeyCode.V, new List<Key> { Key.V, Key.Divide } },
                { SpectrumKeyCode.B, new List<Key> { Key.B, Key.Multiply } },
                { SpectrumKeyCode.N, new List<Key> { Key.N, Key.OemComma } },
                { SpectrumKeyCode.M, new List<Key> { Key.M, Key.OemPeriod, Key.Decimal } },
                { SpectrumKeyCode.N0, new List<Key> { Key.D0, Key.NumPad0, Key.Back } },
                { SpectrumKeyCode.N1, new List<Key> { Key.D1, Key.NumPad1, Key.Home } },
                { SpectrumKeyCode.N2, new List<Key> { Key.D2, Key.NumPad2 } },
                { SpectrumKeyCode.N3, new List<Key> { Key.D3, Key.NumPad3 } },
                { SpectrumKeyCode.N4, new List<Key> { Key.D4, Key.NumPad4 } },
                { SpectrumKeyCode.N5, new List<Key> { Key.D5, Key.NumPad5, Key.Left } },
                { SpectrumKeyCode.N6, new List<Key> { Key.D6, Key.NumPad6, Key.Down } },
                { SpectrumKeyCode.N7, new List<Key> { Key.D7, Key.NumPad7, Key.Up } },
                { SpectrumKeyCode.N8, new List<Key> { Key.D8, Key.NumPad8, Key.Right } },
                { SpectrumKeyCode.N9, new List<Key> { Key.D9, Key.NumPad9 } },
            };

        /// <summary>
        /// Stores keyboard layouts and related key mappings
        /// </summary>
        private static readonly Dictionary<string, Dictionary<SpectrumKeyCode, List<Key>>> s_LayoutMappings =
            new Dictionary<string, Dictionary<SpectrumKeyCode, List<Key>>>
            {
                { DEFAULT_LAYOUT, s_Hun101KeyMappings },
                { ENG_US_LAYOUT, s_EngUsKeyMappings },
                { HUN_101_LAYOUT, s_Hun101KeyMappings },
                { HUN_LAYOUT, s_HunKeyMappings },
            };

        /// <summary>
        /// Initiate scanning the entire keyboard
        /// </summary>
        /// <remarks>
        /// If the physical keyboard is not allowed, the device can use other
        /// ways to emulate the virtual machine's keyboard
        /// </remarks>
        public List<KeyStatus> Scan()
        {
            var result = new List<KeyStatus>();
            if (!ApplicationIsActivated() || !SpectNetPackage.Default.EmulatorViewModel.EnableKeyboardScan)
            {
                return result;
            }

            // --- Obtain the layout mappings for the current keyboard layout
            var layoutBuilder = new StringBuilder(256);
            GetKeyboardLayoutName(layoutBuilder);
            var layoutId = layoutBuilder.ToString();

            // --- Obtain the mapping for the current layout
            if (!s_LayoutMappings.TryGetValue(layoutId, out var layoutMappings))
            {
                if (!s_LayoutMappings.TryGetValue(DEFAULT_LAYOUT, out layoutMappings))
                {
                    // --- No default layout 
                    return result;
                }
            }

            // --- Check the state of the keys
            foreach (var keyInfo in layoutMappings)
            {
                var keyState = keyInfo.Value.Any(WindowsKeyboard.IsKeyDown);
                result.Add(new KeyStatus(keyInfo.Key, keyState));
            }

            return result;
        }

        /// <summary>
        /// Binds keyboard shift type change to this object
        /// </summary>
        public void BindShiftChange()
        {
            SpectNetPackage.Default.Options.KeyboardShiftTypeChanged += OnKeyboardShiftChange;
        }

        /// <summary>
        /// Releases keyboard shift type change from this object
        /// </summary>
        public void ReleaseShiftChange()
        {
            SpectNetPackage.Default.Options.KeyboardShiftTypeChanged -= OnKeyboardShiftChange;
        }

        /// <summary>
        /// Responds to keyboard shift type change events
        /// </summary>
        /// <param name="shiftType"></param>
        private void OnKeyboardShiftChange(object sender, KeyboardShiftTypeChangedEventArgs args)
        {
            if (args.KeyboardShiftOptions == KeyboardShiftOptions.Normal)
            {
                s_Hun101KeyMappings[SpectrumKeyCode.SShift] = s_Hun101SShiftNormal;
                s_Hun101KeyMappings[SpectrumKeyCode.CShift] = s_Hun101CShiftNormal;
                s_HunKeyMappings[SpectrumKeyCode.SShift] = s_HunSShiftNormal;
                s_HunKeyMappings[SpectrumKeyCode.CShift] = s_HunCShiftNormal;
                s_EngUsKeyMappings[SpectrumKeyCode.SShift] = s_EngUsSShiftNormal;
                s_EngUsKeyMappings[SpectrumKeyCode.CShift] = s_EngUsCShiftNormal;
            }
            else
            {
                s_Hun101KeyMappings[SpectrumKeyCode.SShift] = s_Hun101SShiftSwapped;
                s_Hun101KeyMappings[SpectrumKeyCode.CShift] = s_Hun101CShiftSwapped;
                s_HunKeyMappings[SpectrumKeyCode.SShift] = s_HunSShiftSwapped;
                s_HunKeyMappings[SpectrumKeyCode.CShift] = s_HunCShiftSwapped;
                s_EngUsKeyMappings[SpectrumKeyCode.SShift] = s_EngUsSShiftSwapped;
                s_EngUsKeyMappings[SpectrumKeyCode.CShift] = s_EngUsCShiftSwapped;
            }
        }

        /// <summary>
        /// Retrieves the name of the active input locale identifier 
        /// (formerly called the keyboard layout) for the system.
        /// </summary>
        /// <param name="pwszKlid">
        /// The buffer (of at least KL_NAMELENGTH characters in length) 
        /// that receives the name of the input locale identifier, including 
        /// the terminating null character. This will be a copy of the string 
        /// provided to the LoadKeyboardLayout function, unless layout 
        /// substitution took place.
        /// </param>
        [DllImport("user32.dll")]
        private static extern long GetKeyboardLayoutName(StringBuilder pwszKlid);

        /// <summary>
        /// Retrieves a handle to the foreground window (the window with which 
        /// the user is currently working). The system assigns a slightly higher 
        /// priority to the thread that creates the foreground window than it 
        /// does to other threads.
        /// </summary>
        /// <returns>
        /// The return value is a handle to the foreground window.
        /// </returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        private static extern IntPtr GetForegroundWindow();

        /// <summary>
        /// Retrieves the identifier of the thread that created the specified 
        /// window and, optionally, the identifier of the process that created 
        /// the window.
        /// </summary>
        /// <param name="handle">
        /// A handle to the window.
        /// </param>
        /// <param name="processId">
        /// A pointer to a variable that receives the process identifier.
        /// </param>
        /// <returns></returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int GetWindowThreadProcessId(IntPtr handle, out int processId);

        /// <summary>
        /// Checks if the current application is activated
        /// </summary>
        private static bool ApplicationIsActivated()
        {
            var activatedHandle = GetForegroundWindow();
            if (activatedHandle == IntPtr.Zero)
            {
                return false;
            }
            var procId = Process.GetCurrentProcess().Id;
            GetWindowThreadProcessId(activatedHandle, out var activeProcId);
            return activeProcId == procId;
        }
    }

}

<|start_filename|>v2/Assembler/Spect.Net.Assembler/Assembler/AssemblerOptions.cs<|end_filename|>
﻿using System.Collections.Generic;

namespace Spect.Net.Assembler.Assembler
{
    /// <summary>
    /// This class represents the input options of the compiler
    /// </summary>
    public class AssemblerOptions
    {
        /// <summary>
        /// Predefined compilation symbols
        /// </summary>
        public List<string> PredefinedSymbols { get; } = new List<string>();

        /// <summary>
        /// The default start address of the compilation
        /// </summary>
        public ushort? DefaultStartAddress { get; set; } = null;

        /// <summary>
        /// The current ZX Spectrum model
        /// </summary>
        public SpectrumModelType CurrentModel { get; set; } = SpectrumModelType.Spectrum48;

        /// <summary>
        /// The maximum number of errors to report within a loop
        /// </summary>
        public int MaxLoopErrorsToReport { get; set; } = 16;

        /// <summary>
        /// Signs that PROC labels and symbols are not locals by default
        /// </summary>
        public bool ProcExplicitLocalsOnly { get; set; } = false;

        /// <summary>
        /// Indicates that assembly symbols should be case sensitively.
        /// </summary>
        public bool UseCaseSensitiveSymbols { get; set; } = false;

        /// <summary>
        /// Allows flexible use of DEFx pragmas
        /// </summary>
        public bool FlexibleDefPragmas { get; set; } = false;
    }
}

<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/ToolWindows/SpectrumEmulator/SpectrumEmulatorToolWindowControl.xaml.cs<|end_filename|>
﻿using System.Windows.Input;
using Spect.Net.VsPackage.VsxLibrary.ToolWindow;

namespace Spect.Net.VsPackage.ToolWindows.SpectrumEmulator
{
    /// <summary>
    /// Interaction logic for SpectrumEmulatorToolWindowControl.
    /// </summary>
    public partial class SpectrumEmulatorToolWindowControl : ISupportsMvvm<SpectrumEmulatorToolWindowViewModel>
    {
        /// <summary>
        /// The view model behind this control
        /// </summary>
        public SpectrumEmulatorToolWindowViewModel Vm { get; private set; }

        /// <summary>
        /// Sets the view model instance
        /// </summary>
        /// <param name="vm">View model instance to set</param>
        void ISupportsMvvm<SpectrumEmulatorToolWindowViewModel>.SetVm(SpectrumEmulatorToolWindowViewModel vm)
        {
            DataContext = Vm = vm;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="SpectrumEmulatorToolWindowViewModel"/> class.
        /// </summary>
        public SpectrumEmulatorToolWindowControl()
        {
            InitializeComponent();
            PreviewKeyDown += OnPreviewKeyDown;
        }

        private void OnPreviewKeyDown(object s, KeyEventArgs arg)
        {
            // --- We prevent the up and down arrow keys to move the focus to the 
            // --- toolbar buttons. If we did not do that, pressing space or Enter
            // --- might activate the Stop or Pause buttons while those have the focus.
            if (arg.Key == Key.Down || arg.Key == Key.Up || arg.Key == Key.Left || arg.Key == Key.Right)
            {
                arg.Handled = true;
            }
            //Vm.HandleDebugKeys(arg);
        }
    }
}

<|start_filename|>v2/Assembler/Spect.Net.Assembler/Assembler/Errors.cs<|end_filename|>
﻿using System.Collections.Generic;
// ReSharper disable StringLiteralTypo

namespace Spect.Net.Assembler.Assembler
{
    /// <summary>
    /// This class is responsible for managing error messages
    /// </summary>
    public static class Errors
    {
        // --- Error code constants
        public const string Z0001 = "Z0001";
        public const string Z0002 = "Z0002";
        public const string Z0004 = "Z0004";
        public const string Z0005 = "Z0005";
        public const string Z0006 = "Z0006";
        public const string Z0007 = "Z0007";
        public const string Z0008 = "Z0008";
        public const string Z0009 = "Z0009";
        public const string Z0010 = "Z0010";
        public const string Z0011 = "Z0011";
        public const string Z0012 = "Z0012";
        public const string Z0013 = "Z0013";
        public const string Z0014 = "Z0014";
        public const string Z0015 = "Z0015";
        public const string Z0016 = "Z0016";
        public const string Z0017 = "Z0017";
        public const string Z0018 = "Z0018";
        public const string Z0019 = "Z0019";
        public const string Z0020 = "Z0020";
        public const string Z0021 = "Z0021";
        public const string Z0022 = "Z0022";
        public const string Z0023 = "Z0023";
        public const string Z0024 = "Z0024";
        public const string Z0040 = "Z0040";
        public const string Z0060 = "Z0060";
        public const string Z0061 = "Z0061";
        public const string Z0062 = "Z0062";
        public const string Z0080 = "Z0080";
        public const string Z0081 = "Z0081";
        public const string Z0082 = "Z0082";
        public const string Z0083 = "Z0083";
        public const string Z0084 = "Z0084";
        public const string Z0085 = "Z0085";
        public const string Z0086 = "Z0086";
        public const string Z0087 = "Z0087";
        public const string Z0088 = "Z0088";
        public const string Z0089 = "Z0089";
        public const string Z0090 = "Z0090";
        public const string Z0091 = "Z0091";
        public const string Z0092 = "Z0092";
        public const string Z0093 = "Z0093";
        public const string Z0094 = "Z0094";
        public const string Z0095 = "Z0095";

        public const string Z0100 = "Z0100";
        public const string Z0101 = "Z0101";
        public const string Z0102 = "Z0102";

        public const string Z0200 = "Z0200";
        public const string Z0201 = "Z0201";

        public const string Z0300 = "Z0300";
        public const string Z0301 = "Z0301";
        public const string Z0302 = "Z0302";
        public const string Z0303 = "Z0303";
        public const string Z0304 = "Z0304";
        public const string Z0305 = "Z0305";
        public const string Z0306 = "Z0306";
        public const string Z0307 = "Z0307";
        public const string Z0308 = "Z0308";
        public const string Z0309 = "Z0309";

        public const string Z0400 = "Z0400";
        public const string Z0401 = "Z0401";
        public const string Z0402 = "Z0402";
        public const string Z0403 = "Z0403";
        public const string Z0404 = "Z0404";
        public const string Z0405 = "Z0405";
        public const string Z0406 = "Z0406";
        public const string Z0407 = "Z0407";
        public const string Z0408 = "Z0408";
        public const string Z0409 = "Z0409";
        public const string Z0410 = "Z0410";
        public const string Z0411 = "Z0411";
        public const string Z0412 = "Z0412";
        public const string Z0413 = "Z0413";
        public const string Z0414 = "Z0414";
        public const string Z0415 = "Z0415";
        public const string Z0416 = "Z0416";
        public const string Z0417 = "Z0417";
        public const string Z0418 = "Z0418";
        public const string Z0419 = "Z0419";
        public const string Z0420 = "Z0420";
        public const string Z0421 = "Z0421";
        public const string Z0422 = "Z0422";
        public const string Z0423 = "Z0423";
        public const string Z0424 = "Z0424";
        public const string Z0425 = "Z0425";
        public const string Z0426 = "Z0426";
        public const string Z0427 = "Z0427";
        public const string Z0428 = "Z0428";
        public const string Z0429 = "Z0429";
        public const string Z0430 = "Z0430";
        public const string Z0431 = "Z0431";
        public const string Z0432 = "Z0432";
        public const string Z0433 = "Z0433";
        public const string Z0434 = "Z0434";
        public const string Z0435 = "Z0435";
        public const string Z0436 = "Z0436";
        public const string Z0437 = "Z0437";
        public const string Z0438 = "Z0438";
        public const string Z0439 = "Z0439";
        public const string Z0440 = "Z0440";
        public const string Z0441 = "Z0441";
        public const string Z0442 = "Z0442";
        public const string Z0443 = "Z0443";
        public const string Z0444 = "Z0444";
        public const string Z0445 = "Z0445";
        public const string Z0446 = "Z0446";
        public const string Z0447 = "Z0447";
        public const string Z0448 = "Z0448";
        public const string Z0449 = "Z0449";
        public const string Z0450 = "Z0450";
        public const string Z0451 = "Z0451";
        public const string Z0452 = "Z0452";
        public const string Z0453 = "Z0453";
        public const string Z0454 = "Z0454";
        public const string Z0455 = "Z0455";

        public const string Z0500 = "Z0500";

        // --- Error messages
        private static readonly IDictionary<string, string> s_Messages = new Dictionary<string, string>
        {
            { Z0001, "The '{0}' operation with the specified operands is invalid" },
            { Z0002, "Bit index should be between 0 and 7. '{0}' is invalid" },
            { Z0004, "{0} operation cannot have {1} as its operand" },
            { Z0005, "'IN reg,(port)' operation can use only 'A' as its register operand" },
            { Z0006, "Output value can only be 0" },
            { Z0007, "The first 8-bit argument of {0} can only be 'A'" },
            { Z0008, "The second operand of '{0} A,{1}' is invalid" },
            { Z0009, "{0} cannot have {1} as its first operand" },
            { Z0010, "'{0} {1},...' cannot have {2} as its second operand" },
            { Z0011, "{0} cannot be used with {1}" },
            { Z0012, "The EX AF,... operation should use AF' as its second argument" },
            { Z0013, "The EX DE,... operation should use HL as its second argument" },
            { Z0014, "The EX operation should use AF, DE, or (SP) as its first argument" },
            { Z0015, "The EX (SP)' operation should use HL, IX, or IY as its second argument" },
            { Z0016, "JP can be used only with (HL), (IX), or (IY), but no other forms of indirection" },
            { Z0017, "JP with an indirect target cannot be used with conditions" },
            { Z0018, "RST can be used only with #00, #08, #10, #18, #20, #28, #30, or #38 arguments. #{0} is invalid." },
            { Z0019, "{0} AF' is invalid" },
            { Z0020, "Interrupt mode can only be 0, 1, or 2. '{0}' is invalid." },
            { Z0021, "'LD {0},{1}' is an invalid operation" },
            { Z0022, "Relative jump distance should be between -128 and 127. {0} is invalid" },
            { Z0023, "The first operand must be A when using the two-argument form of {0}" },
            { Z0024, "POP cannot be used with an expression operand" },
            { Z0040, "Label '{0}' is already defined" },
            { Z0060, "Unexpected #else directive" },
            { Z0061, "Unexpected #endif directive" },
            { Z0062, "Missing #endif directive" },
            { Z0080, "A pragma or an operation line was expected, but '{0}' line received" },
            { Z0081, "SKIP to {0} is invalid, as this address is less then the current address, {1}" },
            { Z0082, "An EQU pragma must have a label" },
            { Z0083, "Unexpected operation type '{0}'" },
            { Z0084, "No processing rules defined for '{0}' operation" },
            { Z0085, "Cannot find code for key {0} in operation '{1}'" },
            { Z0086, "A VAR pragma must have a label" },
            { Z0087, "A VAR pragma cannot redefine a non-VAR-created symbol" },
            { Z0088, "A MODEL pragma can be used only once." },
            { Z0089, "A MODEL pragma can have only these values: 'SPECTRUM48', 'SPECTRUM128', 'SPECTRUMP3', 'NEXT'." },
            { Z0090, "An #ifmod or #ifnmod directive cen be used only with these identifiers: 'SPECTRUM48', 'SPECTRUM128', 'SPECTRUMP3', 'NEXT'." },
            { Z0091, "DEFM/DEFN pragma requires a string argument." },
            { Z0092, "ALIGN pragma must be used with a parameter value between 1 and #4000; {0} in an invalid value." },
            { Z0093, "DEFH pragma requires a string argument." },
            { Z0094, "DEFH pragma requires a string with even hexadecimal digits." },
            { Z0095, "'{0}' is invalid condition for JR." },
            { Z0100, "Unexpected token: '{0}'" },
            { Z0101, "Unexpected end of line" },
            { Z0102, "To use this Spectrum Next-specific instruction, you need to set MODEL type to NEXT explicitly." },
            { Z0200, "Expression evaluation resulted an error: {0}" },
            { Z0201, "This expression cannot be evaluated promptly, it may refer to one or more undefined symbols ({0})" },
            { Z0300, "Cannot find include file: '{0}'" },
            { Z0301, "Error reading include file: '{0}' ({1})" },
            { Z0302, "Include file '{0}' is included more than once into the same parent source file" },
            { Z0303, "Include file '{0}' causes circular file reference" },
            { Z0304, "The current assembly address overflew #FFFF" },
            { Z0305, "A string value is used where a numeric value is expected." },
            { Z0306, "A string value is expected." },
            { Z0307, "Cannot use an empty pattern with DEFG pragma." },
            { Z0308, "An integral value is expected." },
            { Z0309, "The emitted code overflows the segment/bank." },
            { Z0400, "You cannot define a macro without a name." },
            { Z0401, "Missing {0} statement." },
            { Z0402, "Macro name '{0}' has already been declared." },
            { Z0403, "Unknown macro argument is used '{0}' macro definition." },
            { Z0404, "Macro definition cannot be nested into another macro definition." },
            { Z0405, "Orphan '{0}' statement found without a corresponding '{1}' statement." },
            { Z0406, "Loop counter cannot be greater than 65535 (#FFFF)." },
            { Z0407, "The {0} pragma can be used only in the global scope." },
            { Z0408, "Too many errors detected while compiling a loop, further processing aborted." },
            { Z0409, "Loop counter exceeded the maximum value of 65535 (#FFFF)." },
            { Z0410, "IF cannot have an {0} section after a detected ELSE section." },
            { Z0411, "{0} section in IF cannot have a label." },
            { Z0412, "$CNT cannot be used outside of loop constructs." },
            { Z0413, "The STEP value in a FOR-loop cannot be zero." },
            { Z0414, "Variable {0} is already declared, it cannot be used as a FOR-loop variable again." },
            { Z0415, "BREAK cannot be used outside of loop constructs." },
            { Z0416, "CONTINUE cannot be used outside of loop constructs." },
            { Z0417, "Duplicated MACRO argument: {0}." },
            { Z0418, "Unknown MACRO: {0}." },
            { Z0419, "The declaration of MACRO {0} contains {1} argument(s), but it is invoked with more parameters ({2})." },
            { Z0420, "Macro parameter can only be used within a macro declaration." },
            { Z0421, "A parse-time function accepts only macro parameters." },
            { Z0422, "Cannot pass a macro parameter template in a macro parameter." },
            { Z0423, "Cannot open file '{0}' used in INCLUDEBIN pragma ({0})." },
            { Z0424, "Invalid INCLUDEBIN offset value (negative, or greater than the file length)." },
            { Z0425, "Invalid INCLUDEBIN length value (negative, or segment exceends the file length)." },
            { Z0426, "Emitting the INCLUDEBIN segment would overflow the #FFFF assembly address." },
            { Z0427, "You cannot define a macro with a temporary name ({0})." },
            { Z0428, "You cannot define a module without a name." },
            { Z0429, "Module with name '{0}' already exists." },
            { Z0430, "You cannot define a module with a temporary name ({0})." },
            { Z0431, "Only one XORG pragma can be used within a code segment." },
            { Z0432, "You cannot define a struct without a name." },
            { Z0433, "You cannot define a struct with a temporary name ({0})." },
            { Z0434, "Structure name '{0}' has already been declared." },
            { Z0435, "Structures can use only pragmas that emit bytes, words, strings, or reserve space." },
            { Z0436, "The ENDS statement cannot have a label." },
            { Z0437, "Too many errors withing a .struct definition." },
            { Z0438, "Duplicated field label {0} in a .struct definition." },
            { Z0439, "A .struct invocation ({0}) cannot have arguments." },
            { Z0440, "Field assignment instruction cannot be used outside of .struct invocation." },
            { Z0441, "The .struct definition of {0} does not have a field named {1}." },
            { Z0442, "The .struct size of {0} is {1} byte(s). The invocation wants to emit {2} bytes." },
            { Z0443, "Invalid COMPAREBIN offset value (negative, or greater than the file length)." },
            { Z0444, "Invalid COMPAREBIN length value (negative, or segment exceends the file length)." },
            { Z0445, "COMPAREBIN fails: {0}." },
            { Z0446, "Cannot open file '{0}' used in COMPAREBIN pragma ({0})." },
            { Z0447, "You cannot define a local symbol with a temporary name ({0})." },
            { Z0448, "LOCAL can be used only within PROC." },
            { Z0449, "This local symbol is already declared: ({0})." },
            { Z0450, "The .ZXBASIC pragma should be used before any other pragma or instruction." },
            { Z0451, "The .BANK pragma cannot have a label." },
            { Z0452, "The .BANK pragma cannot be used with the ZX Spectrum 48 model type." },
            { Z0453, "The .BANK pragma's value must be between 0 and 7." },
            { Z0454, "You have already used the .BANK pragma for bank {0}." },
            { Z0455, "The .BANK pragma's offset value must be between 0 and #03fff." },
            { Z0500, "ERROR: {0}" },
        };

        /// <summary>
        /// Obtains the error message with the specified code.
        /// </summary>
        /// <param name="errorCode">Error code</param>
        /// <param name="parameters">Optional error parameters</param>
        /// <returns>Full error message</returns>
        public static string GetMessage(string errorCode, params object[] parameters)
        {
            return s_Messages.TryGetValue(errorCode, out var message) 
                ? string.Format(message, parameters) 
                : $"Undefined error message code {errorCode}";
        }
    }
}

<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/ToolWindows/BasicList/BasicListToolWindow.cs<|end_filename|>
﻿using Microsoft.VisualStudio.Shell;
using Spect.Net.SpectrumEmu.Machine;
using Spect.Net.VsPackage.Dialogs.Export;
using Spect.Net.VsPackage.VsxLibrary.Command;
using Spect.Net.VsPackage.VsxLibrary.ToolWindow;
using System;
using System.IO;
using System.Runtime.InteropServices;
using Task = System.Threading.Tasks.Task;

namespace Spect.Net.VsPackage.ToolWindows.BasicList
{
    /// <summary>
    /// This class implements the ZX Spectrum BASIC List tool window
    /// </summary>
    [Guid("62C1D5F3-75CA-4E89-A33C-A6F4C628367E")]
    [Caption("BASIC program loaded")]
    [ToolWindowToolbar(0x1610)]
    public class BasicListToolWindow :
        SpectrumToolWindowPane<BasicListToolWindowControl, BasicListToolWindowViewModel>
    {
        /// <summary>
        /// Invoke this method from the main thread to initialize toolbar commands.
        /// </summary>
        public static void InitializeToolbarCommands()
        {
            new ExportBasicCommand();
            new MimicZxBasicCommand();
        }

        protected override BasicListToolWindowViewModel GetVmInstance()
        {
            return SpectNetPackage.Default.BasicListViewModel;
        }

        /// <summary>
        /// Exports the list to a file
        /// </summary>
        [CommandId(0x1630)]
        public class ExportBasicCommand : SpectNetCommandBase
        {
            /// <summary>
            /// Override this method to define the status query action
            /// </summary>
            protected override void OnQueryStatus(OleMenuCommand mc)
            {
                var state = SpectNetPackage.Default.EmulatorViewModel.Machine.MachineState;
                mc.Enabled = state == VmState.Running || state == VmState.Paused;
            }

            protected override Task ExecuteAsync()
            {
                var tw = SpectNetPackage.Default.GetToolWindow<BasicListToolWindow>();
                if (tw != null && tw.Vm.List != null)
                {
                    if (DisplayExportBasicListDialog(out var vm, tw.Vm.MimicZxBasic))
                    {
                        // --- Export cancelled
                        return Task.FromResult(0);
                    }
                    var list = tw.Vm.List;
                    list.MimicZxBasic = tw.Vm.MimicZxBasic;
                    list.ProgramLines.Clear();
                    list.DecodeBasicProgram();
                    list.ExportToFile(vm.Filename);
                    ExportBasicListViewModel.LatestFolder = Path.GetDirectoryName(vm.Filename);
                }
                return Task.FromResult(0);

                bool DisplayExportBasicListDialog(out ExportBasicListViewModel vm, bool mimicZxb)
                {
                    var exportDialog = new ExportBasicListDialog()
                    {
                        HasMaximizeButton = false,
                        HasMinimizeButton = false
                    };

                    vm = new ExportBasicListViewModel
                    {
                        Filename = Path.Combine(ExportBasicListViewModel.LatestFolder
                            ?? "C:\\Temp", "BasicList.zxbas"),
                        MimicZxBasic = mimicZxb
                    };
                    exportDialog.SetVm(vm);
                    var accepted = exportDialog.ShowModal();
                    return !accepted.HasValue || !accepted.Value;
                }
            }
        }

        /// <summary>
        /// Turns on or off the Mimic ZX BASIC option
        /// </summary>
        [CommandId(0x1631)]
        public class MimicZxBasicCommand : SpectNetCommandBase
        {
            /// <summary>
            /// Override this method to define the status query action
            /// </summary>
            protected override void OnQueryStatus(OleMenuCommand mc)
            {
                var tw = SpectNetPackage.Default.GetToolWindow<BasicListToolWindow>();
                if (tw == null)
                {
                    return;
                }
                mc.Enabled = true;
                mc.Checked = tw.Vm.MimicZxBasic;
            }

            protected override Task ExecuteAsync()
            {
                var tw = SpectNetPackage.Default.GetToolWindow<BasicListToolWindow>();
                if (tw != null)
                {
                    tw.Vm.MimicZxBasic = !tw.Vm.MimicZxBasic;
                    tw.Vm.RefreshBasicList();
                }
                return Task.FromResult(0);
            }
        }

    }
}


<|start_filename|>v2/Assembler/Spect.Net.Assembler/Assembler/StructDefinition.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;

namespace Spect.Net.Assembler.Assembler
{
    /// <summary>
    /// This class represents a structure
    /// </summary>
    public class StructDefinition
    {
        /// <summary>
        /// The name of the macro
        /// </summary>
        public string StructName { get; }

        /// <summary>
        /// Macro definition section
        /// </summary>
        public DefinitionSection Section { get; }

        /// <summary>
        /// The fields of the structure
        /// </summary>
        public Dictionary<string, FieldDefinition> Fields { get; }

        /// <summary>
        /// Get the structure size
        /// </summary>
        public int Size { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:System.Object" /> class.
        /// </summary>
        public StructDefinition(string structName, int macroDefLine, int macroEndLine, bool caseSensitive)
        {
            StructName = structName;
            Section = new DefinitionSection(macroDefLine, macroEndLine);
            Fields = new Dictionary<string, FieldDefinition>(
                caseSensitive ? StringComparer.InvariantCulture : StringComparer.InvariantCultureIgnoreCase);
        }
    }
}

<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/Compilers/SpectrumProjectConfiguration.cs<|end_filename|>
﻿namespace Spect.Net.VsPackage.Compilers
{
    /// <summary>
    /// This class represents the configuration of a Spectrum project
    /// </summary>
    public class SpectrumProjectConfiguration
    {
        /// <summary>
        /// Command to run during the pre-build event
        /// </summary>
        public string PreBuild { get; set; }

        /// <summary>
        /// Command to run during the post-build event
        /// </summary>
        public string PostBuild { get; set; }

        /// <summary>
        /// Command to run during the pre-build event
        /// </summary>
        public string BuildError { get; set; }

        /// <summary>
        /// Command to run during the pre-export event
        /// </summary>
        public string PreExport { get; set; }

        /// <summary>
        /// Command to run during the post-export event
        /// </summary>
        public string PostExport { get; set; }
    }
}

<|start_filename|>v2/Tests/Spect.Net.Assembler.Test/Parser/PreprocessorTests.cs<|end_filename|>
﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Shouldly;
using Spect.Net.Assembler.SyntaxTree;

namespace Spect.Net.Assembler.Test.Parser
{
    [TestClass]
    public class PreprocessorTests : ParserTestBed
    {
        [TestMethod]
        public void PreprocessorDirectivesWorkAsExpected()
        {
            PreprocessingWorks("#ifdef myId", "#IFDEF", "MYID");
            PreprocessingWorks("#ifndef myId", "#IFNDEF", "MYID");
            PreprocessingWorks("#ifmod Spectrum48", "#IFMOD", "SPECTRUM48");
            PreprocessingWorks("#ifnmod Spectrum128", "#IFNMOD", "SPECTRUM128");
            PreprocessingWorks("#define myId", "#DEFINE", "MYID");
            PreprocessingWorks("#undef myId", "#UNDEF", "MYID");
            PreprocessingWorks("#else", "#ELSE", null);
            PreprocessingWorks("#endif", "#ENDIF", null);
        }

        [TestMethod]
        public void IncludeDirectiveWorksWithStringAsExpected()
        {
            // --- Act
            var visitor = Parse("#include \"myfile.z80asm\"");

            // --- Assert
            visitor.Compilation.Lines.Count.ShouldBe(1);
            var line = visitor.Compilation.Lines[0] as IncludeDirective;
            line.ShouldNotBeNull();
            line.Mnemonic.ShouldBe("#INCLUDE");
            line.Filename.ShouldBe("myfile.z80asm");
        }

        [TestMethod]
        public void IncludeFailsWithLabel()
        {
            // --- Act/Assert
            Parse("mylabel #include \"myfile.z80asm\"", 1);
            Parse("mylabel: #include \"myfile.z80asm>\"", 1);
            Parse("mylabel #include <myfile.z80asm>", 1);
            Parse("mylabel: #include <myfile.z80asm>", 1);
        }

        [TestMethod]
        public void LineDirectiveWorksWithNoStringAsExpected()
        {
            // --- Act
            var visitor = Parse("#line 123");

            // --- Assert
            visitor.Compilation.Lines.Count.ShouldBe(1);
            var line = visitor.Compilation.Lines[0] as LineDirective;
            line.ShouldNotBeNull();
            line.Mnemonic.ShouldBe("#LINE");
            line.Expr.ShouldNotBeNull();
            line.Filename.ShouldBeNull();
        }

        [TestMethod]
        public void LineDirectiveWorksWithStringAsExpected1()
        {
            // --- Act
            var visitor = Parse("#line 123, \"hi.asm\"");

            // --- Assert
            visitor.Compilation.Lines.Count.ShouldBe(1);
            var line = visitor.Compilation.Lines[0] as LineDirective;
            line.ShouldNotBeNull();
            line.Mnemonic.ShouldBe("#LINE");
            line.Expr.ShouldNotBeNull();
            line.Filename.ShouldBe("hi.asm");
        }

        [TestMethod]
        public void LineDirectiveWorksWithStringAsExpected2()
        {
            // --- Act
            var visitor = Parse("#line 1232 \"hi.asm\"");

            // --- Assert
            visitor.Compilation.Lines.Count.ShouldBe(1);
            var line = visitor.Compilation.Lines[0] as LineDirective;
            line.ShouldNotBeNull();
            line.Mnemonic.ShouldBe("#LINE");
            line.Expr.ShouldNotBeNull();
            line.Filename.ShouldBe("hi.asm");
        }

        protected void PreprocessingWorks(string instruction, string mnemonic, string identifier)
        {
            // --- Act
            var visitor = Parse(instruction);

            // --- Assert
            visitor.Compilation.Lines.Count.ShouldBe(1);
            var line = visitor.Compilation.Lines[0] as Directive;
            line.ShouldNotBeNull();
            line.Mnemonic.ShouldBe(mnemonic);
            line.Identifier.ShouldBe(identifier);
        }
    }
}


<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/SpectNetExtraOptionsGrid.cs<|end_filename|>
﻿using System.ComponentModel;
using Microsoft.VisualStudio.Shell;

namespace Spect.Net.VsPackage
{
    public class SpectNetExtraOptionsGrid: DialogPage
    {
        // --- Virtual machine options
        [Category("Virtual machine")]
        [DisplayName("Use Fast Load")]
        [Description("Specifies if fast load is enabled for loading tape files")]
        public bool UseFastLoad { get; set; } = false;
    }
}

<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/CustomEditors/RomEditor/RomEditorControl.xaml.cs<|end_filename|>
﻿using Spect.Net.SpectrumEmu.Disassembler;
using Spect.Net.VsPackage.Dialogs.Export;
using Spect.Net.VsPackage.ToolWindows;
using Spect.Net.VsPackage.ToolWindows.BankAware;
using Spect.Net.VsPackage.ToolWindows.BasicList;
using Spect.Net.VsPackage.ToolWindows.Disassembly;
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;

namespace Spect.Net.VsPackage.CustomEditors.RomEditor
{
    /// <summary>
    /// This class defines the user control that displays the ROM
    /// </summary>
    public partial class RomEditorControl
    {
        const string NO_BASIC = "No BASIC listing in this block";

        private MemoryViewModel _vm;

        /// <summary>
        /// The view model that represents the ROM
        /// </summary>
        public MemoryViewModel Vm
        {
            get => _vm;
            set => DataContext = _vm = value;
        }

        /// <summary>
        /// The optional view model of the BASIC listing
        /// </summary>
        public BasicListViewModel BasicList { get; set; }

        public RomEditorControl()
        {
            InitializeComponent();
            PreviewKeyDown += (s, e) => MemoryDumpListBox.HandleListViewKeyEvents(e);
            Prompt.CommandLineEntered += OnCommandLineEntered;
            DataContextChanged += (s, e) => Vm = DataContext as MemoryViewModel;
        }

        /// <summary>
        /// Signs that the Basic list mode has been changed
        /// </summary>
        public event EventHandler BasicListModeChanged;

        /// <summary>
        /// When a valid address is provided, we scroll the memory window to that address
        /// </summary>
        private void OnCommandLineEntered(object sender, CommandLineEventArgs e)
        {
            void SignInvalidCommand()
            {
                Prompt.IsValid = false;
                Prompt.ValidationMessage = "Invalid command syntax";
                e.Handled = false;
            }

            var parser = new RomEditorCommandParser(e.CommandLine);
            switch (parser.Command)
            {
                case RomEditorCommandType.Invalid:
                    SignInvalidCommand();
                    return;

                case RomEditorCommandType.Goto:
                    ScrollToTop(parser.Address);
                    break;

                case RomEditorCommandType.Disassemble:
                    if (!Vm.AllowDisassembly)
                    {
                        SignInvalidCommand();
                        return;
                    }
                    Vm.ShowDisassembly = true;
                    MemoryRow.Height = new GridLength(1, GridUnitType.Star);
                    DisassemblyRow.Height = new GridLength(1, GridUnitType.Star);
                    Vm.Disassembly(parser.Address);
                    break;

                case RomEditorCommandType.SinclairMode:
                    if (BasicList == null)
                    {
                        Prompt.IsValid = false;
                        Prompt.ValidationMessage = NO_BASIC;
                        e.Handled = false;
                        break;
                    }
                    BasicList.MimicZxBasic = false;
                    BasicList.ProgramLines.Clear();
                    BasicList.DecodeBasicProgram();
                    BasicListModeChanged?.Invoke(this, EventArgs.Empty);
                    break;

                case RomEditorCommandType.ZxBasicMode:
                    if (BasicList == null)
                    {
                        Prompt.IsValid = false;
                        Prompt.ValidationMessage = NO_BASIC;
                        e.Handled = false;
                        break;
                    }
                    BasicList.MimicZxBasic = true;
                    BasicList.ProgramLines.Clear();
                    BasicList.DecodeBasicProgram();
                    BasicListModeChanged?.Invoke(this, EventArgs.Empty);
                    break;

                case RomEditorCommandType.ExitDisass:
                    if (!Vm.AllowDisassembly)
                    {
                        SignInvalidCommand();
                        return;
                    }
                    Vm.ShowDisassembly = false;
                    MemoryRow.Height = new GridLength(1, GridUnitType.Star);
                    DisassemblyRow.Height = new GridLength(0);
                    break;

                case RomEditorCommandType.ExportProgram:
                    {
                        if (BasicList == null)
                        {
                            Prompt.IsValid = false;
                            Prompt.ValidationMessage = NO_BASIC;
                            e.Handled = false;
                            break;
                        }
                        if (DisplayExportBasicListDialog(out var vm))
                        {
                            // --- Export cancelled
                            break;
                        }

                        BasicList.MimicZxBasic = vm.MimicZxBasic;
                        BasicList.ProgramLines.Clear();
                        BasicList.DecodeBasicProgram();
                        BasicList.ExportToFile(vm.Filename);
                        ExportBasicListViewModel.LatestFolder =
                            Path.GetDirectoryName(vm.Filename);
                        break;
                    }

                case RomEditorCommandType.ExportDisass:
                    {
                        if (DisplayExportDisassemblyDialog(out var vm, parser.Address, parser.Address2))
                        {
                            // --- Export cancelled
                            break;
                        }

                        var exporter = new DisassemblyExporter(vm, new RomEditorDisassemblyParent());
                        var disassembler = new Z80Disassembler(
                            new List<MemorySection> { new MemorySection(parser.Address, parser.Address2) },
                            Vm.MemoryBuffer);
                        exporter.ExportDisassembly(disassembler);
                        ExportDisassemblyViewModel.LatestFolder =
                            Path.GetDirectoryName(vm.Filename);
                        break;
                    }

                default:
                    e.Handled = false;
                    return;
            }
            e.Handled = true;
        }

        /// <summary>
        /// Scrolls the disassembly item with the specified address into view
        /// </summary>
        /// <param name="address"></param>
        public void ScrollToTop(ushort address)
        {
            address &= 0xFFF7;
            var sw = MemoryDumpListBox.GetScrollViewer();
            sw?.ScrollToVerticalOffset(address / 16.0);
        }

        /// <summary>
        /// Displays the Export Disassembly dialog to collect parameter data
        /// </summary>
        /// <param name="vm">View model with collected data</param>
        /// <param name="startAddress">Disassembly start address</param>
        /// <param name="endAddress">Disassembly end address</param>
        /// <returns>
        /// True, if the user cancels; false, if starts the export
        /// </returns>
        private static bool DisplayExportDisassemblyDialog(out ExportDisassemblyViewModel vm, ushort startAddress, ushort endAddress)
        {
            var exportDialog = new ExportDisassemblyDialog()
            {
                HasMaximizeButton = false,
                HasMinimizeButton = false
            };

            vm = new ExportDisassemblyViewModel
            {
                Filename = Path.Combine(ExportDisassemblyViewModel.LatestFolder
                    ?? "C:\\Temp", "ExportedCode.z80asm"),
                StartAddress = startAddress.ToString(),
                EndAddress = endAddress.ToString(),
                AddToProject = true,
                HangingLabels = true,
                CommentStyle = CommentStyle.Semicolon,
                MaxLineLengthType = LineLengthType.L100,
                IndentDepth = IndentDepthType.Two
            };
            exportDialog.SetVm(vm);
            var accepted = exportDialog.ShowModal();
            return !accepted.HasValue || !accepted.Value;
        }

        /// <summary>
        /// Displays the Export Disassembly dialog to collect parameter data
        /// </summary>
        /// <param name="vm">View model with collected data</param>
        /// <param name="startAddress">Disassembly start address</param>
        /// <param name="endAddress">Disassembly end address</param>
        /// <returns>
        /// True, if the user stars export; false, if the export is cancelled
        /// </returns>
        private static bool DisplayExportBasicListDialog(out ExportBasicListViewModel vm)
        {
            var exportDialog = new ExportBasicListDialog()
            {
                HasMaximizeButton = false,
                HasMinimizeButton = false
            };

            vm = new ExportBasicListViewModel
            {
                Filename = Path.Combine(ExportBasicListViewModel.LatestFolder
                    ?? "C:\\Temp", "BasicList.zxbas"),
                MimicZxBasic = true
            };
            exportDialog.SetVm(vm);
            var accepted = exportDialog.ShowModal();
            return !accepted.HasValue || !accepted.Value;
        }
    }

    /// <summary>
    /// Parent class for disassembly export
    /// </summary>
    class RomEditorDisassemblyParent : IDisassemblyItemParent
    {
        public bool GetComment(ushort address, out string comment)
        {
            comment = string.Empty;
            return false;
        }

        public bool GetLabel(ushort address, out string label)
        {
            label = string.Empty;
            return false;
        }

        public bool GetLiteralReplacement(ushort address, out string symbol)
        {
            symbol = string.Empty;
            return false;
        }

        public bool GetPrefixComment(ushort address, out string comment)
        {
            comment = string.Empty;
            return false;
        }

        public bool HasBreakpoint(ushort address)
        {
            return false;
        }

        public bool HasCondition(ushort itemAddress)
        {
            return false;
        }

        public bool IsCurrentInstruction(ushort address)
        {
            return false;
        }

        public void ToggleBreakpoint(DisassemblyItemViewModel item)
        {
        }
    }
}


<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/Commands/InjectProgramCommand.cs<|end_filename|>
﻿using Microsoft.VisualStudio.Shell;
using Spect.Net.Assembler.Assembler;
using Spect.Net.SpectrumEmu;
using Spect.Net.SpectrumEmu.Machine;
using Spect.Net.VsPackage.Machines;
using Spect.Net.VsPackage.ToolWindows.SpectrumEmulator;
using Spect.Net.VsPackage.VsxLibrary;
using Spect.Net.VsPackage.VsxLibrary.Command;
using Spect.Net.VsPackage.VsxLibrary.Output;
using System;
using System.IO;
using System.Linq;
using System.Windows;
using Microsoft.VisualStudio.Shell.Interop;
using Task = System.Threading.Tasks.Task;

namespace Spect.Net.VsPackage.Commands
{
    /// <summary>
    /// Injects code in the ZX Spectrum virtual machine
    /// </summary>
    [CommandId(0x0810)]
    public class InjectProgramCommand : CompileCodeCommandBase
    {
        /// <summary>
        /// Indicates if the code has been injected
        /// </summary>
        protected bool CodeInjected { get; private set; }

        /// <summary>
        /// Override this command to start the ZX Spectrum virtual machine
        /// </summary>
        protected virtual void ResumeVm()
        {
            // --- We do not start the machine, just inject the code
        }

        /// <summary>
        /// Indicates that this command uses the virtual machine in 
        /// code inject mode
        /// </summary>
        protected virtual bool IsInInjectMode => true;

        /// <summary>
        /// Allows defining a new continuation point
        /// </summary>
        /// <returns>
        /// Address of the continuation point, if a new one should be used;
        /// null, to carry on from the previous point
        /// </returns>
        protected virtual ushort? GetContinuationAddress() => null;

        /// <summary>
        /// Compiles the Z80 code file
        /// </summary>
        protected override async Task ExecuteAsync()
        {
            // --- Prepare the appropriate file to compile/run
            CodeInjected = false;

            // --- Step #1: Compile the code
            await base.ExecuteAsync();
            if (!CompileSuccess) return;

            // --- Step #2: Check machine compatibility
            var modelName = SpectNetPackage.Default.Solution.ActiveProject?.ModelName;
            SpectrumModelType modelType;
            if (Output.ModelType == null)
            {
                switch (modelName)
                {
                    case SpectrumModels.ZX_SPECTRUM_48:
                        modelType = SpectrumModelType.Spectrum48;
                        break;
                    case SpectrumModels.ZX_SPECTRUM_128:
                        modelType = SpectrumModelType.Spectrum128;
                        break;
                    case SpectrumModels.ZX_SPECTRUM_P3_E:
                        modelType = SpectrumModelType.SpectrumP3;
                        break;
                    case SpectrumModels.ZX_SPECTRUM_NEXT:
                        modelType = SpectrumModelType.Next;
                        break;
                    default:
                        modelType = SpectrumModelType.Spectrum48;
                        break;
                }
            }
            else
            {
                modelType = Output.ModelType.Value;
            }

            // --- We may display dialogs, so we go back to the main thread
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            if (!SpectrumModels.IsModelCompatibleWith(modelName, modelType))
            {
                VsxDialogs.Show("The model type defined in the code is not compatible with the " +
                    "Spectrum virtual machine of this project.",
                    "Cannot run code.");
                return;
            }

            // --- Step #3: Check for zero code length
            if (Output.Segments.Sum(s => s.EmittedCode.Count) == 0)
            {
                VsxDialogs.Show("The length of the compiled code is 0, " +
                    "so there is no code to inject into the virtual machine and run.",
                    "No code to run.");
                return;
            }

            // --- Step #4: Check non-zero displacements
            var options = HostPackage.Options;
            if (Output.Segments.Any(s => (s.Displacement ?? 0) != 0) && options.ConfirmNonZeroDisplacement)
            {
                var answer = VsxDialogs.Show("The compiled code contains non-zero displacement" +
                    "value, so the displaced code may fail. Are you sure you want to run the code?",
                    "Non-zero displacement found",
                    MessageBoxButton.YesNo, VsxMessageBoxIcon.Question, 1);
                if (answer == VsxDialogResult.No)
                {
                    return;
                }
            }

            var vm = HostPackage.EmulatorViewModel;
            var pane = OutputWindow.GetPane<SpectrumVmOutputPane>();
            HostPackage.ShowToolWindow<SpectrumEmulatorToolWindow>();

            // --- Step #5: Prepare the machine to be in the appropriate mode
            if (IsInInjectMode)
            {
                if (vm.MachineState == VmState.Running ||
                    vm.MachineState != VmState.Paused && vm.MachineState != VmState.Stopped && vm.MachineState != VmState.None)
                {
                    VsxDialogs.Show("To inject the code into the virtual machine, please pause it first.",
                        "The virtual machine is running");
                    return;
                }
            }
            else
            {
                var stopped = await SpectrumVmManager.StopSpectrumVmAsync(options.ConfirmMachineRestart);
                if (!stopped) return;
            }

            // --- Step #6: Start the virtual machine and run it to the injection point
            if (vm.MachineState == VmState.Stopped || vm.MachineState == VmState.None)
            {
                await pane.WriteLineAsync("Starting the virtual machine in code injection mode.");

                // --- Use specific startup for each model.
                var started = true;
                try
                {
                    switch (modelName)
                    {
                        case SpectrumModels.ZX_SPECTRUM_48:
                            await VmStateFileManager.SetSpectrum48StartupState();
                            break;

                        case SpectrumModels.ZX_SPECTRUM_128:
                            if (modelType == SpectrumModelType.Spectrum48)
                            {
                                await VmStateFileManager.SetSpectrum128In48StartupState();
                            }
                            else
                            {
                                await VmStateFileManager.SetSpectrum128In128StartupState();
                            }
                            break;

                        case SpectrumModels.ZX_SPECTRUM_P3_E:
                            if (modelType == SpectrumModelType.Spectrum48)
                            {
                                await VmStateFileManager.SetSpectrumP3In48StartupState();
                            }
                            else
                            {
                                await VmStateFileManager.SetSpectrumP3InP3StartupState();
                            }
                            break;

                        case SpectrumModels.ZX_SPECTRUM_NEXT:
                            // --- Implement later
                            return;
                        default:
                            // --- Implement later
                            return;
                    }
                }
                catch (Exception)
                {
                    started = false;
                }
                if (!started) return;
            }

            // --- Step #7: Inject the code into the memory, and force
            // --- new disassembly
            await pane.WriteLineAsync("Injecting code into the Spectrum virtual machine.");
            HostPackage.CodeManager.InjectCodeIntoVm(Output);
            CodeInjected = true;

            // --- Step #8: Jump to execute the code
            var continuationPoint = GetContinuationAddress();
            if (continuationPoint.HasValue)
            {
                vm.Machine.SpectrumVm.Cpu.Registers.PC = continuationPoint.Value;
                await pane.WriteLineAsync($"Resuming code execution at address {vm.Machine.SpectrumVm.Cpu.Registers.PC:X4}.");
            }
            vm.MemViewPoint = (ushort)MemoryStartAddress;
            vm.DisAssViewPoint = (ushort)DisassemblyStartAddress;
            vm.StackDebugSupport.ClearStepOutStack();

            GetAffectedItem(out var hierarchy, out var itemId);
            if (hierarchy is IVsProject project)
            {
                project.GetMkDocument(itemId, out var itemFullPath);
            }

            if (Output.SourceType == "zxbasic")
            {
                // --- Push the MAIN_EXECUTION loop address to the stack
                var memDevice = vm.Machine.SpectrumVm.MemoryDevice;
                var spValue = vm.Machine.SpectrumVm.Cpu.Registers.SP;
                var mainExec = VmStateFileManager.SP48_MAIN_EXEC_ADDR;
                memDevice.Write((ushort)(spValue - 1), (byte)(mainExec >> 8));
                memDevice.Write((ushort)(spValue - 2), (byte)mainExec);
                vm.Machine.SpectrumVm.Cpu.Registers.SP -= 2;
            }
            ResumeVm();
        }

        /// <summary>
        /// Override this method to define the action to execute on the main
        /// thread of Visual Studio -- finally
        /// </summary>
        protected override async Task FinallyOnMainThreadAsync()
        {
            await base.FinallyOnMainThreadAsync();
            if (IsInInjectMode)
            {
                if (HostPackage.Options.ConfirmInjectCode && CodeInjected)
                {
                    VsxDialogs.Show("The code has been injected.");
                }
            }
            else
            {
                if (HostPackage.Options.ConfirmCodeStart && Output.ErrorCount > 0)
                {
                    VsxDialogs.Show("The code has been started.");
                }
            }
        }
    }
}

<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/VsxLibrary/Command/SingleProjectItemCommandBase.cs<|end_filename|>
﻿
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using EnvDTE;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Spect.Net.VsPackage.SolutionItems;

#pragma warning disable VSTHRD010 // Invoke single-threaded types on Main thread

namespace Spect.Net.VsPackage.VsxLibrary.Command
{
    /// <summary>
    /// This class represents a command that can be associated with a .z80asm file.
    /// </summary>
    public abstract class SingleProjectItemCommandBase : SpectNetCommandBase
    {
        /// <summary>
        /// Gets the file item extensions accepted by this command
        /// </summary>
        public abstract IEnumerable<string> ItemExtensionsAccepted { get; }

        /// <summary>
        /// Override this method to define the status query action
        /// </summary>
        /// <param name="mc"></param>
        protected override void OnQueryStatus(OleMenuCommand mc)
        {
            mc.Visible = SpectNetPackage.Default.ActiveProject != null
                && ItemPath != null;
        }

        /// <summary>
        /// Gets the currently selected Z80 program item
        /// </summary>
        /// <param name="hierarchy"></param>
        /// <param name="itemId"></param>
        public void GetItem(out IVsHierarchy hierarchy, out uint itemId) =>
            IsSingleItemSelection(out hierarchy, out itemId);

        /// <summary>
        /// Gets the full path of the item; or null, if there is no .z80asm item selected.
        /// </summary>
        public string ItemPath
        {
            get
            {
                var singleItem = IsSingleItemSelection(out var hierarchy, out var itemId);
                if (!singleItem) return null;

                // ReSharper disable once SuspiciousTypeConversion.Global
                if (hierarchy is IVsProject project)
                {
                    project.GetMkDocument(itemId, out var itemFullPath);
                    var ext = Path.GetExtension(itemFullPath);
                    return ItemExtensionsAccepted.Any(e => string.Compare(e, ext, StringComparison.OrdinalIgnoreCase) == 0)
                        ? itemFullPath
                        : null;
                }
                return null;
            }
        }

        /// <summary>
        /// Gets the extension of the item
        /// </summary>
        public string ItemExtension => Path.GetExtension(ItemPath);

        /// <summary>
        /// Gets the identity of the project item.
        /// </summary>
        public string Identity
        {
            get
            {
                var singleItem = IsSingleItemSelection(out var hierarchy, out var itemId);
                if (!singleItem) return null;

                hierarchy.GetProperty(itemId, (int)__VSHPROPID.VSHPROPID_ExtObject, out var objProj);
                if (objProj is ProjectItem projItem)
                {
                    var identity = projItem.Properties.Item("Identity");
                    return identity?.Value?.ToString();
                }
                return null;
            }
        }

        /// <summary>
        /// Tests if the file behind the command is in the active project
        /// </summary>
        public bool IsInActiveProject 
            => SpectNetPackage.Default.Solution.IsFileInActiveProject(ItemPath);

        /// <summary>
        /// Gets the ZX Spectrum project of this item
        /// </summary>
        public SpectrumProject SpectrumProject => 
            SpectNetPackage.Default.Solution.Projects
                .FirstOrDefault(project => project.ContainsFile(ItemPath));

        /// <summary>
        /// This method checks if there is only a single item selected in Solution Explorer.
        /// </summary>
        /// <param name="hierarchy">The selected hierarchy</param>
        /// <param name="itemid">The selected item in the hierarchy</param>
        /// <returns>
        /// True, if only a single item is selected; otherwise, false
        /// </returns>
        public static bool IsSingleItemSelection(out IVsHierarchy hierarchy, out uint itemid)
        {
            hierarchy = null;
            itemid = VSConstants.VSITEMID_NIL;

            if (!(Package.GetGlobalService(typeof(SVsShellMonitorSelection)) is IVsMonitorSelection monitorSelection) 
                || !(Package.GetGlobalService(typeof(SVsSolution)) is IVsSolution solution))
            {
                return false;
            }

            var hierarchyPtr = IntPtr.Zero;
            var selectionContainerPtr = IntPtr.Zero;

            try
            {
                // --- Obtain the current selection
                var hr = monitorSelection.GetCurrentSelection(out hierarchyPtr,
                    out itemid,
                    out var multiItemSelect,
                    out selectionContainerPtr);

                if (ErrorHandler.Failed(hr) || hierarchyPtr == IntPtr.Zero || itemid == VSConstants.VSITEMID_NIL)
                {
                    // --- There is no selection
                    return false;
                }

                // --- Multiple items are selected
                if (multiItemSelect != null) return false;

                // --- No hierarchy, no selection
                hierarchy = Marshal.GetObjectForIUnknown(hierarchyPtr) as IVsHierarchy;
                if (hierarchy == null) return false;

                // --- Return true only when the hierarchy is a project inside the Solution
                // --- and it has a ProjectID Guid
                return !ErrorHandler.Failed(solution.GetGuidOfProject(hierarchy, out _));
            }
            finally
            {
                // --- Release unmanaged resources
                if (selectionContainerPtr != IntPtr.Zero)
                {
                    Marshal.Release(selectionContainerPtr);
                }
                if (hierarchyPtr != IntPtr.Zero)
                {
                    Marshal.Release(hierarchyPtr);
                }
            }
        }
    }

}

#pragma warning restore VSTHRD010 // Invoke single-threaded types on Main thread


<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/ToolWindows/BankAware/DisassemblyAnnotationHandler.cs<|end_filename|>
﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
using Newtonsoft.Json;
using Spect.Net.SpectrumEmu.Abstraction.Providers;
using Spect.Net.SpectrumEmu.Disassembler;
using Spect.Net.VsPackage.ToolWindows.Disassembly;
using Spect.Net.VsPackage.VsxLibrary;

namespace Spect.Net.VsPackage.ToolWindows.BankAware
{
    /// <summary>
    /// This class is responsible for managing disassembly annotations
    /// </summary>
    public class DisassemblyAnnotationHandler : IDisposable
    {
        /// <summary>
        /// The parent view model
        /// </summary>
        public BankAwareToolWindowViewModelBase Parent { get; }

        /// <summary>
        /// Annotations for ROM pages
        /// </summary>
        public Dictionary<int, DisassemblyAnnotation> RomPageAnnotations { get; private set; }

        /// <summary>
        /// ROM annotation files
        /// </summary>
        public Dictionary<int, string> RomAnnotationFiles { get; private set; }

        /// <summary>
        /// Annotations for RAM banks
        /// </summary>
        public Dictionary<int, DisassemblyAnnotation> RamBankAnnotations { get; private set; }

        /// <summary>
        /// The file to save RAM annotations to
        /// </summary>
        public string RamBankAnnotationFile { get; private set; }

        /// <summary>
        /// Initializes a new instance of the this class.
        /// </summary>
        /// <param name="parent">Parent view model</param>
        public DisassemblyAnnotationHandler(BankAwareToolWindowViewModelBase parent)
        {
            Parent = parent;
        }

        /// <summary>
        /// Sets up the annotations for the current machine.
        /// </summary>
        public void SetupMachineAnnotations()
        {
            // --- Read ROM annotations
            var spectrumVm = Parent.SpectrumVm;
            RomPageAnnotations = new Dictionary<int, DisassemblyAnnotation>();
            RomAnnotationFiles = new Dictionary<int, string>();
            var romConfig = spectrumVm.RomConfiguration;
            var roms = romConfig.NumberOfRoms;
            for (var i = 0; i < roms; i++)
            {
                var annFile = spectrumVm.RomProvider.GetAnnotationResourceName(romConfig.RomName,
                    roms == 1 ? -1 : i);
                var annData = spectrumVm.RomProvider.LoadRomAnnotations(romConfig.RomName,
                    roms == 1 ? -1 : i);

                DisassemblyAnnotation.Deserialize(annData, out var annotation);
                RomPageAnnotations.Add(i, annotation);
                RomAnnotationFiles.Add(i, annFile);
            }

            // --- Read the initial RAM annotations
            RamBankAnnotations = new Dictionary<int, DisassemblyAnnotation>();
            SpectNetPackage.Default.CodeManager.AnnotationFileChanged += OnAnnotationFileChanged;
            OnAnnotationFileChanged(null, EventArgs.Empty);

            // --- Register Disassembly providers to use
            if (RomPageAnnotations.TryGetValue(romConfig.Spectrum48RomIndex, out var spectrumRomAnn))
            {
                Z80Disassembler.SetProvider<ISpectrum48RomLabelProvider>(
                    new Spectrum48RomLabelProvider(spectrumRomAnn));
            }
        }

        /// <summary>
        /// Updates the RAM annotation file according to changes
        /// </summary>
        private void OnAnnotationFileChanged(object sender, EventArgs eventArgs)
        {
            var project = SpectNetPackage.Default.ActiveProject;
            var annFile = project?.DefaultAnnotationItem
                          ?? project?.AnnotationProjectItems?.FirstOrDefault();
            RamBankAnnotations.Clear();
            if (annFile == null) return;

            RamBankAnnotationFile = annFile.Filename;
            try
            {
                var disAnn = File.ReadAllText(annFile.Filename);
                DisassemblyAnnotation.DeserializeBankAnnotations(disAnn, out var annotations);
                RamBankAnnotations = annotations;
            } 
            catch (Exception ex)
            {
                VsxDialogs.Show(ex.Message, "Error loading annotation file", MessageBoxButton.OK, VsxMessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// Stores the label in the annotations
        /// </summary>
        /// <param name="address">Label address</param>
        /// <param name="label">Label text</param>
        /// <param name="validationMessage">Validation message to display</param>
        public void SetLabel(ushort address, string label, out string validationMessage)
        {
            validationMessage = null;
            if (!string.IsNullOrWhiteSpace(label))
            {
                if (LabelDefinedInOtherBank(label))
                {
                    validationMessage = "Label name is duplicated";
                    return;
                }
            }
            var annotation = Parent.GetAnnotationFor(address, out var annAddr);
            var result = annotation.SetLabel(annAddr, label);
            if (result)
            {
                SaveAnnotations(annotation, address);
                return;
            }
            validationMessage = "Label name is invalid/duplicated";
        }

        /// <summary>
        /// Stores a comment in annotations
        /// </summary>
        /// <param name="address">Comment address</param>
        /// <param name="comment">Comment text</param>
        public void SetComment(ushort address, string comment)
        {
            var annotation = Parent.GetAnnotationFor(address, out var annAddr);
            annotation.SetComment(annAddr, comment);
            SaveAnnotations(annotation, address);
        }

        /// <summary>
        /// Stores a prefix name in this collection
        /// </summary>
        /// <param name="address">Comment address</param>
        /// <param name="comment">Comment text</param>
        public void SetPrefixComment(ushort address, string comment)
        {
            var annotation = Parent.GetAnnotationFor(address, out var annAddr);
            annotation.SetPrefixComment(annAddr, comment);
            SaveAnnotations(annotation, address);
        }

        /// <summary>
        /// Stores a section in this collection
        /// </summary>
        /// <param name="startAddress">Start address</param>
        /// <param name="endAddress">End address</param>
        /// <param name="type">Memory section type</param>
        public void AddSection(ushort startAddress, ushort endAddress, MemorySectionType type)
        {
            var startAnn = Parent.GetAnnotationFor(startAddress, out var start);
            var endAnn = Parent.GetAnnotationFor((ushort)(endAddress - 1), out var end);
            if (startAnn == endAnn)
            {
                // --- The section is within one bank
                var tempSection = new MemorySection(start, end, type);
                startAnn.MemoryMap.Add(tempSection);
                startAnn.MemoryMap.Normalize();
                SaveAnnotations(startAnn, startAddress);
            }
            else
            {
                // --- The section overlaps multiple banks
                // --- We must be in FullViewMode to get here
                var origSection = new MemorySection(startAddress, endAddress, type);
                for (var bank = 0; bank <= 3; bank++)
                {
                    var bankSection = new MemorySection((ushort)(bank * 0x4000), (ushort)(bank * 0x4000 + 0x3FFF));
                    if (origSection.Overlaps(bankSection))
                    {
                        // --- There is a memory section for this bank
                        var cutSection = origSection.Intersect(bankSection);
                        var bankAnn = Parent.GetAnnotationFor(cutSection.StartAddress, out var cutStart);
                        Parent.GetAnnotationFor(cutSection.EndAddress, out var cutEnd);
                        bankAnn.MemoryMap.Add(new MemorySection(cutStart, cutEnd, type));
                        bankAnn.MemoryMap.Normalize();
                        SaveAnnotations(bankAnn, startAddress);
                    }
                }
            }
        }

        /// <summary>
        /// Replaces a literal in the disassembly item for the specified address. If
        /// the named literal does not exists, creates one for the symbol.
        /// </summary>
        /// <param name="address">Disassembly item address</param>
        /// <param name="literalName">Literal name</param>
        /// <param name="lineIndexes">Indexes for disassembly lines</param>
        /// <param name="disassemblyItems">All disassembly items</param>
        /// <returns>Null, if operation id ok, otherwise, error message</returns>
        /// <remarks>If the literal already exists, it must have the symbol's value.</remarks>
        public string ApplyLiteral(ushort address, string literalName,
            Dictionary<ushort, int> lineIndexes, Collection<DisassemblyItemViewModel> disassemblyItems)
        {
            if (!lineIndexes.TryGetValue(address, out int lineIndex))
            {
                return $"No disassembly line is associated with address #{address:X4}";
            }

            var disassItem = disassemblyItems[lineIndex];
            if (!disassItem.Item.HasSymbol)
            {
                return $"Disassembly line #{address:X4} does not have an associated value to replace";
            }

            var symbolValue = disassItem.Item.SymbolValue;
            if (disassItem.Item.HasLabelSymbol)
            {
                return
                    $"%L {symbolValue:X4} {literalName}%Disassembly line #{address:X4} refers to a label. Use the 'L {symbolValue:X4}' command to define a label.";
            }

            var annotation = Parent.GetAnnotationFor(address, out _);
            var message = annotation.ApplyLiteral(address, symbolValue, literalName);
            if (message != null) return message;

            SaveAnnotations(annotation, address);
            return null;
        }

        /// <summary>
        /// Saves the annotation file for the specified address
        /// </summary>
        /// <param name="annotation">Annotation to save</param>
        /// <param name="address"></param>
        public void SaveAnnotations(DisassemblyAnnotation annotation, ushort address)
        {
            string filename;
            var isRom = false;
            var spectrumVm = SpectNetPackage.Default.EmulatorViewModel.Machine.SpectrumVm;
            if (Parent.FullViewMode)
            {
                var memDevice = spectrumVm.MemoryDevice;
                var (isInRom, index, _) = memDevice.GetAddressLocation(address);
                if (isInRom)
                {
                    filename = RomAnnotationFiles.TryGetValue(index, out var romFile)
                        ? romFile : null;
                    isRom = true;
                }
                else
                {
                    filename = RamBankAnnotationFile;
                }
            }
            else if (Parent.RomViewMode)
            {
                filename = RomAnnotationFiles.TryGetValue(Parent.RomIndex, out var romFile)
                    ? romFile : null;
                isRom = true;
            }
            else
            {
                filename = RamBankAnnotationFile;
            }
            if (filename == null) return;

            var annotationData = isRom ? annotation.Serialize() : SerializeRamBankAnnotations();
            File.WriteAllText(filename, annotationData);
        }

        /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
        public void Dispose()
        {
            SpectNetPackage.Default.CodeManager.AnnotationFileChanged -= OnAnnotationFileChanged;
            Parent?.Dispose();
        }

        #region Helper methods

        /// <summary>
        /// Serializes RAM bank annotations
        /// </summary>
        /// <returns></returns>
        private string SerializeRamBankAnnotations()
        {
            var annData = RamBankAnnotations.ToDictionary(k => k.Key,
                v => v.Value.ToDisassemblyDecorationData());
            return JsonConvert.SerializeObject(annData, Formatting.Indented);
        }

        /// <summary>
        /// Checks if the specified label is already defined
        /// </summary>
        /// <param name="label">Label to check</param>
        /// <returns>True, if label is already defined; otherwise, false</returns>
        private bool LabelDefinedInOtherBank(string label)
        {
            var memoryDevice = SpectNetPackage.Default.EmulatorViewModel.Machine.SpectrumVm.MemoryDevice;
            if (Parent.RomViewMode)
            {
                // --- The label is allowed in another ROM, but not in the current one
                return false;
            }
            if (Parent.RamBankViewMode || Parent.FullViewMode)
            {
                var contains = RamBankAnnotations.Values.Any(ann => ann.Labels.Values.Any(
                    l => string.Compare(l, label, StringComparison.OrdinalIgnoreCase) == 0));
                if (contains) return true;
            }
            if (!Parent.FullViewMode) return false;
            return RomPageAnnotations.TryGetValue(memoryDevice.GetSelectedRomIndex(), out var romAnn) &&
                romAnn.Labels.Values.Any(l => string.Compare(l, label,
                    StringComparison.OrdinalIgnoreCase) == 0);
        }

        #endregion
    }

}

<|start_filename|>v2/VsIntegration/Spect.Net.VsPackage/CustomEditors/RomEditor/RomEditorCommandType.cs<|end_filename|>
﻿namespace Spect.Net.VsPackage.CustomEditors.RomEditor
{
    /// <summary>
    /// Command types available in the ROM editor
    /// </summary>
    public enum RomEditorCommandType
    {
        None,
        Invalid,
        Goto,
        Disassemble,
        ExportDisass,
        ExportProgram,
        ExitDisass,
        SinclairMode,
        ZxBasicMode
    }
}
