mirror of
https://github.com/creeperlv/SVM.git
synced 2026-01-10 20:39:54 +00:00
Working on the assembler and linker.
This commit is contained in:
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace SVM.Assembler.Core
|
||||
{
|
||||
public delegate OperationResult<IntermediateInstruction?> AssemblerFunction(ILexer lexer, IntermediateInstruction instruction, LexSegment leadingSegment);
|
||||
public class Assembler
|
||||
{
|
||||
public const string LexDefinition =
|
||||
@@ -54,6 +55,7 @@ LabelData InternalLbl
|
||||
LabelConstant InternalLbl
|
||||
";
|
||||
LexerDefinition? definition;
|
||||
public Dictionary<string, AssemblerFunction> assemblerFunctions = new Dictionary<string, AssemblerFunction>();
|
||||
public Assembler()
|
||||
{
|
||||
if (LexerDefinition.TryParse(LexDefinition, out definition))
|
||||
@@ -61,17 +63,73 @@ LabelConstant InternalLbl
|
||||
definition.Substitute();
|
||||
}
|
||||
}
|
||||
public OperationResult<IntermediateObject> Assemble(string input, string ID = "main.asm")
|
||||
public OperationResult<LexSegment?> Lex(ILexer lexer)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var r = lexer.Lex();
|
||||
if (r.HasError()) return r;
|
||||
if (r.Result == null) return r;
|
||||
if (r.Result.LexSegmentId != null && r.Result.LexMatchedItemId != null)
|
||||
{
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
public OperationResult<(string, string)?> ParseKVPair(ILexer lexer, LexSegment currentSeg)
|
||||
{
|
||||
OperationResult<(string, string)?> operationResult = new OperationResult<(string, string)?>(null);
|
||||
var r = Lex(lexer);
|
||||
if (operationResult.CheckAndInheritErrorAndWarnings(r)) { return operationResult; }
|
||||
if (currentSeg.Content == null) return operationResult;
|
||||
if (r.Result == null) return operationResult;
|
||||
if (r.Result.Content == null) return operationResult;
|
||||
return (currentSeg.Content, r.Result.Content);
|
||||
}
|
||||
private OperationResult<IntermediateInstruction?> ParseInstruction(StringLexer lexer, LexSegment CurrentSeg, LexSegment? Label)
|
||||
{
|
||||
OperationResult<IntermediateInstruction?> operationResult = new OperationResult<IntermediateInstruction?>(null);
|
||||
IntermediateInstruction intermediateInstruction = new IntermediateInstruction();
|
||||
intermediateInstruction.Label = Label;
|
||||
LexSegment LexDef;
|
||||
if (Label is null)
|
||||
{
|
||||
LexDef = CurrentSeg;
|
||||
}
|
||||
else
|
||||
{
|
||||
var next = Lex(lexer);
|
||||
if (operationResult.CheckAndInheritErrorAndWarnings(next))
|
||||
{
|
||||
return operationResult;
|
||||
}
|
||||
if (next.Result is null)
|
||||
{
|
||||
return operationResult;
|
||||
}
|
||||
LexDef = next.Result;
|
||||
}
|
||||
if (LexDef.LexMatchedItemId == null)
|
||||
{
|
||||
return operationResult;
|
||||
}
|
||||
if (!assemblerFunctions.TryGetValue(LexDef.LexMatchedItemId, out var assemblerFunction))
|
||||
{
|
||||
return operationResult;
|
||||
}
|
||||
return assemblerFunction(lexer, intermediateInstruction, LexDef);
|
||||
}
|
||||
public OperationResult<IntermediateObject> AssembleIntermediateObject(string input, string ID = "main.asm")
|
||||
{
|
||||
StringLexer lexer = new StringLexer();
|
||||
lexer.SetDefinition(definition);
|
||||
lexer.Content = input;
|
||||
lexer.SourceID = ID;
|
||||
OperationResult<IntermediateObject> operationResult = new OperationResult<IntermediateObject>();
|
||||
OperationResult<IntermediateObject> operationResult = new OperationResult<IntermediateObject>(new IntermediateObject());
|
||||
InternalLabel CurrentLabel = InternalLabel.Code;
|
||||
while (true)
|
||||
{
|
||||
var lexResult = lexer.Lex();
|
||||
var lexResult = Lex(lexer);
|
||||
if (lexResult.Result == null) break;
|
||||
var r = lexResult.Result;
|
||||
switch (r.LexSegmentId)
|
||||
@@ -96,17 +154,47 @@ LabelConstant InternalLbl
|
||||
switch (CurrentLabel)
|
||||
{
|
||||
case InternalLabel.Code:
|
||||
switch (r.LexSegmentId)
|
||||
{
|
||||
case "GenericLabel":
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
OperationResult<IntermediateInstruction?> instR = r.LexSegmentId switch
|
||||
{
|
||||
"GenericLabel" => ParseInstruction(lexer, r, r),
|
||||
_ => ParseInstruction(lexer, r, null),
|
||||
};
|
||||
if (operationResult.CheckAndInheritErrorAndWarnings(instR))
|
||||
{
|
||||
return operationResult;
|
||||
}
|
||||
if (instR.Result is null) return operationResult;
|
||||
operationResult.Result.instructions.Add(instR.Result);
|
||||
}
|
||||
break;
|
||||
case InternalLabel.Data:
|
||||
{
|
||||
var KV = ParseKVPair(lexer, r);
|
||||
if (operationResult.CheckAndInheritErrorAndWarnings(KV))
|
||||
{
|
||||
return operationResult;
|
||||
}
|
||||
if (KV.Result == null)
|
||||
{
|
||||
return operationResult;
|
||||
}
|
||||
operationResult.Result.data.Add(KV.Result.Value.Item1, KV.Result.Value.Item2);
|
||||
}
|
||||
break;
|
||||
case InternalLabel.Const:
|
||||
{
|
||||
var KV = ParseKVPair(lexer, r);
|
||||
if (operationResult.CheckAndInheritErrorAndWarnings(KV))
|
||||
{
|
||||
return operationResult;
|
||||
}
|
||||
if (KV.Result == null)
|
||||
{
|
||||
return operationResult;
|
||||
}
|
||||
operationResult.Result.consts.Add(KV.Result.Value.Item1, KV.Result.Value.Item2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -132,7 +220,7 @@ LabelConstant InternalLbl
|
||||
[Serializable]
|
||||
public class IntermediateInstruction
|
||||
{
|
||||
public string? Label = null;
|
||||
public LexSegment? Label = null;
|
||||
public PrimaryInstruction inst;
|
||||
public List<LexSegment> Parameters = new List<LexSegment>();
|
||||
}
|
||||
|
||||
43
src/SVM.Assembler.Core/Linker.cs
Normal file
43
src/SVM.Assembler.Core/Linker.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using LibCLCC.NET.Operations;
|
||||
using SVM.Core;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SVM.Assembler.Core
|
||||
{
|
||||
public class Linker
|
||||
{
|
||||
public static OperationResult<IntermediateObject?> Link(List<IntermediateObject> objs)
|
||||
{
|
||||
OperationResult<IntermediateObject?> operationResult = new OperationResult<IntermediateObject?>(null);
|
||||
IntermediateObject intermediateObject = new IntermediateObject();
|
||||
foreach (var item in objs)
|
||||
{
|
||||
foreach (var inst in item.instructions)
|
||||
{
|
||||
intermediateObject.instructions.Add(inst);
|
||||
}
|
||||
foreach (var data in item.data)
|
||||
{
|
||||
if (!intermediateObject.data.TryAdd(data.Key, data.Value))
|
||||
{
|
||||
intermediateObject.data[data.Key] = data.Value;
|
||||
}
|
||||
}
|
||||
foreach (var kv in item.consts)
|
||||
{
|
||||
if (!intermediateObject.consts.TryAdd(kv.Key, kv.Value))
|
||||
{
|
||||
intermediateObject.consts[kv.Key] = kv.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return operationResult;
|
||||
}
|
||||
public static OperationResult<ManagedSVMProgram?> Freeze(List<IntermediateObject> objs)
|
||||
{
|
||||
OperationResult<ManagedSVMProgram?> operationResult = new OperationResult<ManagedSVMProgram?>(null);
|
||||
|
||||
return operationResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,15 @@
|
||||
using SVM.Core.Utils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using static SVM.Core.stdc.stdlib;
|
||||
namespace SVM.Core
|
||||
{
|
||||
public unsafe class ManagedSVMProgram
|
||||
{
|
||||
public List<SVMInstruction> instructions = new List<SVMInstruction>();
|
||||
public List<byte> Datas = new List<byte>();
|
||||
}
|
||||
public unsafe struct SVMProgram : IDisposable
|
||||
{
|
||||
public UInt64 InstructionCount;
|
||||
|
||||
Reference in New Issue
Block a user