public void DefwPragmaWorksWithImmediateEvaluation() { // --- Arrange var compiler = new Z80Assembler(); var expected = new byte[] { 0x01, 0xA0, 0x45, 0x23, 0x12, 0xAE, 122, 0 }; // --- Act var output = compiler.Compile(@" .defw #A001, #2345, #AE12, 122"); // --- Assert output.ErrorCount.ShouldBe(0); output.Segments.Count.ShouldBe(1); var segment = output.Segments[0]; segment.EmittedCode.Count.ShouldBe(expected.Length); for (var i = 0; i < expected.Length; i++) { segment.EmittedCode[i].ShouldBe(expected[i]); } }
public void DefwPragmaWorksWithFunctions() { // --- Arrange var compiler = new Z80Assembler(); var expected = new byte[] { 0xE5, 0x03 }; // --- Act var output = compiler.Compile(@" .defw 1000*sin(1.5)"); // --- Assert output.ErrorCount.ShouldBe(0); output.Segments.Count.ShouldBe(1); var segment = output.Segments[0]; segment.EmittedCode.Count.ShouldBe(expected.Length); for (var i = 0; i < expected.Length; i++) { segment.EmittedCode[i].ShouldBe(expected[i]); } }
public void SkipPragmaWorksWithFillValue() { // --- Arrange var compiler = new Z80Assembler(); var expected = new byte[] { 0x3A, 0x3A, 0x3A, 0x3A, 0x3A }; // --- Act var output = compiler.Compile(@" .skip $+#05, #3A"); // --- Assert output.ErrorCount.ShouldBe(0); output.Segments.Count.ShouldBe(1); var segment = output.Segments[0]; segment.EmittedCode.Count.ShouldBe(expected.Length); for (var i = 0; i < expected.Length; i++) { segment.EmittedCode[i].ShouldBe(expected[i]); } }
public void IfndefTrueWorksWithoutElseBranch() { // --- Arrange var compiler = new Z80Assembler(); var options = new AssemblerOptions(); const string SOURCE = @" nop ; 1 #ifndef MySymbol nop ; 2 nop ; 3 nop ; 4 #endif nop ; 5"; // --- Act var output = compiler.Compile(SOURCE, options); // --- Assert output.ErrorCount.ShouldBe(0); compiler.PreprocessedLines.Count.ShouldBe(5); }
public void IfFalseWorksWithoutElseBranch() { // --- Arrange var compiler = new Z80Assembler(); var options = new AssemblerOptions(); const string SOURCE = @" nop ; 1 #if 2 == 3 nop nop nop #endif nop ; 2"; // --- Act var output = compiler.Compile(SOURCE, options); // --- Assert output.ErrorCount.ShouldBe(0); compiler.PreprocessedLines.Count.ShouldBe(2); }
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); }
public void IntegrationTest1() { List <string> programrows = new List <string> { "ORG $3000", "RST $30", "DB $05", "LD BC,$010C", "RST $30", "DB $03", "LD DE,SZOVEG", "LD BC,21", "RST $30", "DB $02", "RET", "SZOVEG DB 'ÁRVÍZTŰRŐTÜKÖRFÚRÓGÉP'" }; string fileName = @"IntegrationTest1.cas"; var assembler = new Z80Assembler(programrows); var assembled = assembler.BuildProgram(); Assert.AreEqual(assembled, true); var loader = new TvcBasicLoader(assembler.AssembledProgram, 1, 1, 0x3000); bool loaderGenerated = loader.GenerateBasicLoader(); Assert.AreEqual(loaderGenerated, true); CasFileWriter writer = new CasFileWriter(fileName); writer.Write(loader.BasicLoaderProgramBytes.ToArray()); var bytesOfCreatedFile = File.ReadAllBytes(fileName); var bytesOfBaseFile = File.ReadAllBytes(IntegrationTest1TestFileName); Assert.AreEqual(bytesOfCreatedFile.SequenceEqual(bytesOfBaseFile), true); }
public void TooManyErrorsStopProcessing() { // --- Arrange var options = new AssemblerOptions { MaxLoopErrorsToReport = 3 }; var compiler = new Z80Assembler(); // --- Act var output = compiler.Compile(@" counter = 0; .repeat Value: .var 100 + Other; counter = counter + 1; .until counter >= 100 ", options); // --- Assert output.ErrorCount.ShouldBe(4); output.Errors[3].ErrorCode.ShouldBe(Errors.Z0408); }
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); }
public void ModuleWithDuplicatedNameFails1() { // --- Arrange var compiler = new Z80Assembler(); // --- Act var output = compiler.Compile(@" .org #6000 MyModule .module ld a,b .endmodule ld b,c MyModule .module ld a,b .endmodule "); // --- Assert output.ErrorCount.ShouldBe(2); output.Errors[0].ErrorCode.ShouldBe(Errors.Z0040); output.Errors[1].ErrorCode.ShouldBe(Errors.Z0429); }
public void InternalModuleLabelDoesNotWorkWithoutScope() { // --- Arrange var compiler = new Z80Assembler(); // --- Act var output = compiler.Compile(@" .org #6000 Start: .module MyModule ld a,b ld bc,t1 t1: ld a,b .endmodule ld hl,t1 "); // --- Assert output.ErrorCount.ShouldBe(1); output.Errors[0].ErrorCode.ShouldBe(Errors.Z0201); }
public void OrgPragmaWorksWithNewSegment() { // --- Arrange var compiler = new Z80Assembler(); // --- Act var output = compiler.Compile(@" ld a,c .org #6400 ld a,b ld a,c"); // --- Assert output.ErrorCount.ShouldBe(0); output.Segments.Count.ShouldBe(2); output.Segments[0].StartAddress.ShouldBe((ushort)0x8000); output.Segments[0].Displacement.ShouldBeNull(); output.Segments[0].EmittedCode.Count.ShouldBe(1); output.Segments[1].StartAddress.ShouldBe((ushort)0x6400); output.Segments[1].Displacement.ShouldBeNull(); output.Segments[1].EmittedCode.Count.ShouldBe(2); }
public void UnknownModuleNameIsCaught2() { // --- Arrange var compiler = new Z80Assembler(); // --- Act var output = compiler.Compile(@" .org #6000 Start: .module MyModule ld a,b ld bc,t1 t1: ld a,b .endmodule ld hl,::OtherModule.t1 "); // --- Assert output.ErrorCount.ShouldBe(1); output.Errors[0].ErrorCode.ShouldBe(Errors.Z0201); }
protected void EvalExpression(string expr, string expected, bool hasEvaluationError = false, Dictionary <string, ushort> symbols = null) { var assembler = new Z80Assembler(); assembler.Compile(""); if (symbols != null) { foreach (var pair in symbols) { assembler.SetSymbolValue(pair.Key, new ExpressionValue(pair.Value)); } } var exprNode = ParseExpr(expr); var result = assembler.Eval(null, exprNode); result.AsString().ShouldBe(expected); if (hasEvaluationError) { exprNode.EvaluationError.ShouldNotBeNull(); } }
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"); }
public void DefsPragmaWorksWithIndirectEvaluation1() { // --- Arrange var compiler = new Z80Assembler(); var expected = new byte[] { 0x00, 0x00, 0x00 }; // --- Act var output = compiler.Compile(@" Count: .equ 3 .defs Count"); // --- Assert output.ErrorCount.ShouldBe(0); output.Segments.Count.ShouldBe(1); var segment = output.Segments[0]; segment.EmittedCode.Count.ShouldBe(expected.Length); for (var i = 0; i < expected.Length; i++) { segment.EmittedCode[i].ShouldBe(expected[i]); } }
public void MultipleLabelIssuesDetected() { // --- Arrange var compiler = new Z80Assembler(); // --- Act var output = compiler.Compile(@" .if true Label1: .elif true Label2: .elif true Label3: .else .endif "); // --- Assert output.ErrorCount.ShouldBe(3); output.Errors[0].ErrorCode.ShouldBe(Errors.Z0411); output.Errors[1].ErrorCode.ShouldBe(Errors.Z0411); output.Errors[2].ErrorCode.ShouldBe(Errors.Z0411); }
public void NestedIfdefTrueTrueElseElseWorks() { // --- Arrange var compiler = new Z80Assembler(); var options = new AssemblerOptions(); options.PredefinedSymbols.Add("MYSYMBOL"); options.PredefinedSymbols.Add("MYSYMBOL2"); const string SOURCE = @" #ifdef MySymbol nop ; 1 #ifdef MySymbol2 nop ; 2 nop ; 3 #else nop nop nop #endif nop ; 4 nop ; 5 nop ; 6 nop ; 7 #else nop nop nop nop nop #endif"; // --- Act var output = compiler.Compile(SOURCE, options); // --- Assert output.ErrorCount.ShouldBe(0); compiler.PreprocessedLines.Count.ShouldBe(7); }
public void UnexpectedEndifRaisesError() { // --- Arrange var compiler = new Z80Assembler(); var options = new AssemblerOptions(); const string SOURCE = @"nop #endif ; 1 nop nop nop #endif ; 2 nop nop"; // --- Act var output = compiler.Compile(SOURCE, options); // --- Assert output.ErrorCount.ShouldBe(2); output.Errors[0].ErrorCode.ShouldBe(Errors.Z0061); output.Errors[1].ErrorCode.ShouldBe(Errors.Z0061); compiler.PreprocessedLines.Count.ShouldBe(6); }
public void IfnmodWithInvalidModelTypeRaisesError() { // --- Arrange var compiler = new Z80Assembler(); var options = new AssemblerOptions { CurrentModel = SpectrumModelType.Spectrum48 }; const string SOURCE = @" nop ; 1 #ifnmod Unknown nop ; 2 nop ; 3 nop ; 4 #endif nop ; 5"; // --- Act var output = compiler.Compile(SOURCE, options); // --- Assert output.ErrorCount.ShouldBe(1); output.Errors[0].ErrorCode.ShouldBe(Errors.Z0090); }
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); }
public void IfnmodFalseWorksWithoutElseBranch() { // --- Arrange var compiler = new Z80Assembler(); var options = new AssemblerOptions { CurrentModel = SpectrumModelType.Spectrum128 }; const string SOURCE = @" nop ; 1 #ifnmod Spectrum48 nop nop nop #endif nop ; 2"; // --- Act var output = compiler.Compile(SOURCE, options); // --- Assert output.ErrorCount.ShouldBe(0); compiler.PreprocessedLines.Count.ShouldBe(5); }
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); }
public override void AnalyzeCode() { ClearResults(); var programLines = Document.Lines.Select(dl => Document.GetText(dl.Offset, dl.TotalLength) .TrimStart(' ', '\t').Replace(Environment.NewLine, "").ToUpper()).ToList(); var fileName = Path.GetFileName(m_ProgramFullPath); var programDirectory = Path.GetDirectoryName(m_ProgramFullPath); m_Assembler = new Z80Assembler(programLines, new List <string> { programDirectory }, fileName); if (!m_Assembler.BuildProgram()) { MarkLineAsWrong(Document.GetLineByNumber(m_Assembler.WrongLineNumber), m_Assembler.StatusMessage); WrongLine.Add(new Tuple <string, int>(m_Assembler.StatusMessage, m_Assembler.WrongLineNumber)); AnalizingFinished?.Invoke(this, new EventArgs()); return; } InterpretedSymbols.AddRange(m_Assembler.AssembledProgram.SymbolTable.Where(sd => sd.Key != @".LC").Select(kvp => new SymbolData { SymbolName = kvp.Key, SymbolText = kvp.Value.ToString(), LineNumber = kvp.Value.LineNumber, SymbolType = kvp.Value.Type == SymbolType.Address ? @"Cím" : "Konstans" })); if (Settings.AssemblyEditorSettings.MarkInactiveCode) { MarkSkippedLines(m_Assembler.SkippedLineNumbers); } AnalizingFinished?.Invoke(this, new EventArgs()); }
public void MultipleElifAndElseAfterElseFails() { // --- Arrange var compiler = new Z80Assembler(); // --- Act var output = compiler.Compile(@" .if true .elif true .else .elif false .elif false .else .else .endif "); // --- Assert output.ErrorCount.ShouldBe(4); output.Errors[0].ErrorCode.ShouldBe(Errors.Z0410); output.Errors[1].ErrorCode.ShouldBe(Errors.Z0410); output.Errors[2].ErrorCode.ShouldBe(Errors.Z0410); output.Errors[3].ErrorCode.ShouldBe(Errors.Z0410); }
public void NonLocalModuleNameIsVisible() { // --- Arrange var compiler = new Z80Assembler(); // --- Act var output = compiler.Compile(@" .org #6000 Start: .module MyModule ld a,b .module Nested Inner: nop .endmodule ld bc,t1 t1: ld a,b .endmodule ld hl,MyModule.Nested.Inner "); // --- Assert output.ErrorCount.ShouldBe(0); }
public override void Build() { if (!OpenInputFile()) { return; } OnBuildMessageSent(@"Assembly program fordítása..."); var fileName = Path.GetFileName(BuildSettings.ProgramPath); var programDirectory = Path.GetDirectoryName(BuildSettings.ProgramPath); Z80Assembler assembler = new Z80Assembler(ProgramLines, new List <string> { programDirectory }, fileName); if (!assembler.BuildProgram()) { OnBuildMessageSent(assembler.StatusMessage); return; } float programSizeInKb = (float)assembler.AssembledProgramBytes.Length / 1024; OnBuildMessageSent($"Lefordított assembly program mérete: {programSizeInKb:F3} KB ({assembler.AssembledProgramBytes.Length} byte)"); if (BuildSettings.GenerateNativeFile) { OnBuildMessageSent($"Nativ tárgykód létrehozása({BuildSettings.NativePath})..."); if (!CreateNativeFile(assembler)) { return; } } if (BuildSettings.GenerateListFile) { OnBuildMessageSent($"Lista file létrehozása({BuildSettings.LstFilePath})..."); if (!CreateListFile(assembler)) { return; } } if (!BuildSettings.GenerateLoader) { if (BuildSettings.GenerateCasFile) { OnBuildMessageSent($"CAS file létrehozása ({BuildSettings.CasFilePath})..."); if (!CreateCasFile(assembler.AssembledProgramBytes, CasFileContent.NativProgramCode)) { OnBuildMessageSent(@"CAS file létrehozása sikertelen!"); } } if (BuildSettings.GenerateWavFile) { OnBuildMessageSent($"WAV file létrehozása ({BuildSettings.WavFilePath})..."); CreateWavFile(assembler.AssembledProgramBytes); } return; } ushort startAddress = assembler.AssembledProgram.ProgramSections[0].ProgramStartAddress; if (BuildSettings.StartAddress.HasValue) { var selectedprogramSection = assembler.AssembledProgram.ProgramSections .Where(ps => ps.ProgramStartAddress == BuildSettings.StartAddress.Value) .Select(ps => ps).FirstOrDefault(); if (selectedprogramSection == null) { OnBuildMessageSent($"A megadott indítási cím:{BuildSettings.StartAddress.Value:D} (${BuildSettings.StartAddress.Value:X4}) érvénytelen!"); var addressList = assembler.AssembledProgram.ProgramSections .Select(ps => $"{ps.ProgramStartAddress}(${ps.ProgramStartAddress:x4})").ToList(); OnBuildMessageSent($"A lehetséges indítási címek:{string.Join(",", addressList)}"); return; } startAddress = selectedprogramSection.ProgramStartAddress; } var loader = new TvcBasicLoader(assembler.AssembledProgram, 1, 1, startAddress); OnBuildMessageSent(@"Basic loader generálása..."); OnBuildMessageSent($"Program indítási cím:{startAddress:D} (${startAddress:X4})"); if (!loader.GenerateBasicLoader()) { OnBuildMessageSent(loader.StatusMessage); return; } if (!CreateLoaderFile(loader)) { return; } if (BuildSettings.GenerateCasFile) { OnBuildMessageSent($"CAS file létrehozása basic betöltővel ({BuildSettings.CasFilePath})..."); if (!CreateCasFile(loader.BasicLoaderProgramBytes.ToArray(), CasFileContent.BasicProgram)) { OnBuildMessageSent(@"CAS file létrehozása sikertelen!"); return; } } if (BuildSettings.GenerateWavFile) { OnBuildMessageSent($"WAV file létrehozása basic betöltővel ({BuildSettings.WavFilePath})..."); CreateWavFile(loader.BasicLoaderProgramBytes.ToArray()); } }
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(), 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)); }
/// <summary> /// Visit a parse tree produced by <see cref="Generated.Z80AsmParser.literalExpr"/>. /// </summary> /// <param name="context">The parse tree.</param> /// <return>The visitor result.</return> public override object VisitLiteralExpr(Z80AsmParser.LiteralExprContext context) { var token = context.NormalizeToken(); if (context.CURADDR() != null || context.MULOP() != null || context.DOT() != null) { AddSemiVar(context); return(new CurrentAddressNode()); } if (context.CURCNT() != null) { AddSemiVar(context); return(new CurrentLoopCounterNode()); } // --- Check for Boolean values if (context.BOOLLIT() != null) { AddNumber(context); var boolValue = new ExpressionValue(context.BOOLLIT().GetText().ToLower().Contains("t")); return(new LiteralNode(boolValue)); } // --- Check for real values if (context.REALNUM() != null) { AddNumber(context); return(double.TryParse(context.REALNUM().GetText(), out var realValue) ? new LiteralNode(realValue) : new LiteralNode(ExpressionValue.Error)); } // --- Check for string values if (context.STRING() != null) { AddString(context); var stringValue = context.STRING().NormalizeString(); return(new LiteralNode(stringValue)); } ushort value; // --- Hexadecimal literals if (token.StartsWith("#")) { AddNumber(context); value = ushort.Parse(token.Substring(1), NumberStyles.HexNumber); } else if (token.StartsWith("0X")) { AddNumber(context); value = ushort.Parse(token.Substring(2), NumberStyles.HexNumber); } else if (token.StartsWith("$")) { AddNumber(context); value = ushort.Parse(token.Substring(1), NumberStyles.HexNumber); } else if (token.EndsWith("H", StringComparison.OrdinalIgnoreCase)) { AddNumber(context); value = (ushort)int.Parse(token.Substring(0, token.Length - 1), NumberStyles.HexNumber); } // --- Binary literals else if (token.StartsWith("%")) { AddNumber(context); value = (ushort)Convert.ToInt32(token.Substring(1).Replace("_", ""), 2); } else if (token.StartsWith("0B")) { AddNumber(context); value = (ushort)Convert.ToInt32(token.Substring(2).Replace("_", ""), 2); } else if (token.EndsWith("b") || token.EndsWith("B")) { 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")) { AddNumber(context); value = (ushort)Convert.ToInt32(token.Substring(0, token.Length - 1), 8); } // --- Character literals else if (token.StartsWith("\"") || token.StartsWith("'")) { 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(value)); }
/// <summary> /// Visit a parse tree produced by <see cref="Generated.Z80AsmParser.literalExpr"/>. /// </summary> /// <param name="context">The parse tree.</param> /// <return>The visitor result.</return> public override object VisitLiteralExpr(Z80AsmParser.LiteralExprContext context) { if (IsInvalidContext(context)) { return(null); } var token = context.NormalizeToken(); if (token == "$") { return(new CurrentAddressNode()); } ushort value; // --- Hexadecimal literals if (token.StartsWith("#")) { _numbers.Add(new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1)); value = ushort.Parse(token.Substring(1), NumberStyles.HexNumber); } else if (token.StartsWith("0X")) { _numbers.Add(new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1)); value = ushort.Parse(token.Substring(2), NumberStyles.HexNumber); } else if (token.EndsWith("H", StringComparison.OrdinalIgnoreCase)) { _numbers.Add(new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1)); value = (ushort)int.Parse(token.Substring(0, token.Length - 1), NumberStyles.HexNumber); } // --- Binary literals else if (token.StartsWith("%")) { _numbers.Add(new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1)); value = (ushort)Convert.ToInt32(token.Substring(1).Replace("_", ""), 2); } else if (token.StartsWith("0B")) { _numbers.Add(new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1)); value = (ushort)Convert.ToInt32(token.Substring(2).Replace("_", ""), 2); } // --- Character literals else if (token.StartsWith("\"")) { 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 { _numbers.Add(new TextSpan(context.Start.StartIndex, context.Start.StopIndex + 1)); value = (ushort)int.Parse(context.NormalizeToken()); } return(new LiteralNode { LiteralValue = value }); }