mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-20 21:08:51 +00:00
148 lines
No EOL
4.2 KiB
C#
148 lines
No EOL
4.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.IO;
|
|
|
|
namespace Cosmos.Compiler.XSharp {
|
|
public class Generator {
|
|
public static void Execute(TextReader input, string inputFilename, TextWriter output, string defaultNamespace) {
|
|
var xGenerator = new Generator();
|
|
xGenerator.Name = Path.GetFileNameWithoutExtension(inputFilename);
|
|
xGenerator.Namespace = defaultNamespace;
|
|
xGenerator.Execute(input, output);
|
|
}
|
|
|
|
public string Namespace {
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public string Name {
|
|
get;
|
|
set;
|
|
}
|
|
|
|
private void EnsureHeaderWritten() {
|
|
if (mHeaderWritten) {
|
|
return;
|
|
}
|
|
mHeaderWritten = true;
|
|
EmitHeader();
|
|
}
|
|
|
|
private bool mHeaderWritten = false;
|
|
|
|
private TextReader mInput;
|
|
private TextWriter mOutput;
|
|
|
|
public void Execute(TextReader aInput, TextWriter aOutput) {
|
|
mInput = aInput;
|
|
mOutput = aOutput;
|
|
|
|
while (true) {
|
|
string xLine = aInput.ReadLine();
|
|
if (xLine == null) {
|
|
break;
|
|
}
|
|
|
|
ProcessLine(xLine);
|
|
}
|
|
|
|
EmitFooter();
|
|
}
|
|
|
|
private void EmitHeader() {
|
|
mOutput.WriteLine("using System;");
|
|
mOutput.WriteLine("using System.Linq;");
|
|
mOutput.WriteLine("using Cosmos.Assembler;");
|
|
mOutput.WriteLine("using Cosmos.Assembler.x86;");
|
|
mOutput.WriteLine();
|
|
mOutput.WriteLine("namespace {0}", Namespace);
|
|
mOutput.WriteLine("{");
|
|
mOutput.WriteLine("\tpublic class {0}: Cosmos.IL2CPU.Plugs.AssemblerMethod", Name);
|
|
mOutput.WriteLine("\t{");
|
|
mOutput.WriteLine("\t\tpublic override void AssembleNew(object aAssembler, object aMethodInfo)");
|
|
mOutput.WriteLine("\t\t{");
|
|
}
|
|
|
|
private void EmitFooter() {
|
|
EnsureHeaderWritten();
|
|
mOutput.WriteLine("\t\t}");
|
|
mOutput.WriteLine("\t}");
|
|
mOutput.WriteLine("}");
|
|
}
|
|
|
|
// +-[].=
|
|
protected Regex mRegex = new Regex(@"(\W)");
|
|
|
|
protected void ProcessLine(string aLine) {
|
|
aLine = aLine.Trim();
|
|
if (String.IsNullOrEmpty(aLine)) {
|
|
// Skip
|
|
} else if (aLine[0] == '#') {
|
|
ProcessComment(aLine.Substring(1));
|
|
} else if (aLine[0] == '!') {
|
|
ProcessLiteral(aLine.Substring(1));
|
|
} else {
|
|
if (aLine.EndsWith("++")) {
|
|
// TODO
|
|
} else if (aLine.EndsWith("--")) {
|
|
// TODO
|
|
} else {
|
|
var xParts = mRegex.Split(aLine);
|
|
xParts = xParts.Where(q => string.IsNullOrWhiteSpace(q) == false).ToArray();
|
|
|
|
if (xParts.Contains("=")) {
|
|
ProcessAssignment(xParts);
|
|
} else {
|
|
throw new Exception("Syntax error: '" + aLine + "'");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ProcessAssignment(string[] aParts) {
|
|
if (aParts.Length != 3) {
|
|
throw new Exception("Wrong Assignment");
|
|
}
|
|
|
|
string xLeft = aParts[0];
|
|
string xRight = aParts[2];
|
|
|
|
if (IsRegister(xLeft)) {
|
|
uint xValue;
|
|
if (UInt32.TryParse(xRight, out xValue)) {
|
|
mOutput.WriteLine("new Move{{DestinationReg = RegistersEnum.{0}, SourceValue = {1}}};", xLeft, xRight);
|
|
return;
|
|
}
|
|
}
|
|
|
|
throw new Exception("Wrong Assignment");
|
|
}
|
|
|
|
private void ProcessLiteral(string line) {
|
|
EnsureHeaderWritten();
|
|
mOutput.WriteLine("new LiteralAssemblerCode(\"{0}\");", line);
|
|
}
|
|
|
|
private void ProcessComment(string line) {
|
|
EnsureHeaderWritten();
|
|
mOutput.WriteLine("new Comment(\"{0}\");", line);
|
|
}
|
|
|
|
private bool IsRegister(string aWord) {
|
|
aWord = aWord.ToLower();
|
|
return
|
|
aWord == "eax" || aWord == "ax" || aWord == "ah" || aWord == "al" ||
|
|
aWord == "ebx" || aWord == "bx" || aWord == "bh" || aWord == "bl" ||
|
|
aWord == "ecx" || aWord == "cx" || aWord == "ch" || aWord == "cl" ||
|
|
aWord == "edx" || aWord == "dx" || aWord == "dh" || aWord == "dl" ||
|
|
aWord == "esp" ||
|
|
aWord == "ebp" ||
|
|
aWord == "esi" ||
|
|
aWord == "edi";
|
|
}
|
|
}
|
|
} |