248 lines
7.9 KiB
C#
Executable File
248 lines
7.9 KiB
C#
Executable File
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using Axiom.Utils;
|
|
|
|
namespace Axiom.Interpreter
|
|
{
|
|
public class Emitter
|
|
{
|
|
private bool emitting = true;
|
|
private int lastSymbol;
|
|
private BinaryReader inputStream;
|
|
private BinaryWriter outputStream; // the assigned output stream
|
|
private BinaryWriter activeStream; // the active stream
|
|
private Stack<BinaryWriter> writeStack = new Stack<BinaryWriter>();
|
|
private Stack<CapturedCode> captureStack = new Stack<CapturedCode>();
|
|
private bool isCapturing = false;
|
|
private bool debug = true;
|
|
|
|
public Emitter(BinaryReader inputStream, BinaryWriter outputStream)
|
|
{
|
|
this.inputStream = inputStream;
|
|
this.outputStream = outputStream;
|
|
this.activeStream = outputStream;
|
|
}
|
|
|
|
public bool Debug
|
|
{
|
|
get { return debug; }
|
|
set { debug = value; }
|
|
}
|
|
|
|
public void BeginCapture()
|
|
{
|
|
writeStack.Push(activeStream);
|
|
activeStream = new BinaryWriter(new MemoryStream());
|
|
isCapturing = true;
|
|
}
|
|
|
|
public void EndCapture()
|
|
{
|
|
if (!isCapturing)throw new InvalidOperationException("EndCapture called without a matching BeginCapture.");
|
|
activeStream.Flush();
|
|
MemoryStream memoryStream = (MemoryStream)activeStream.BaseStream;
|
|
byte[] capturedBytes = memoryStream.ToArray();
|
|
activeStream.Close();
|
|
activeStream.Dispose();
|
|
activeStream = writeStack.Pop();
|
|
isCapturing = writeStack.Count > 0;
|
|
captureStack.Push(new CapturedCode(capturedBytes));
|
|
}
|
|
|
|
/// <summary>
|
|
/// EmitCapture - Later, for CONTINUE semantics, we can Peek() at the top of the captureStack to get the increment code without popping it.
|
|
/// </summary>
|
|
public void EmitCapture()
|
|
{
|
|
if(0==captureStack.Count)throw new InvalidOperationException("The CaptureList is empty.");
|
|
CapturedCode code = captureStack.Pop();
|
|
activeStream.Write(code.Bytes,0,code.Length);
|
|
}
|
|
|
|
public void Emit(String literalValue)
|
|
{
|
|
if (!emitting) return;
|
|
activeStream.Write(literalValue.Length);
|
|
activeStream.Write(literalValue);
|
|
}
|
|
|
|
public void Emit(Scanner.ScanSymbols code)
|
|
{
|
|
if (!emitting) return;
|
|
activeStream.Write((int)code);
|
|
if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Scanner.SymbolToString(code));
|
|
}
|
|
|
|
public void Emit(Scanner.ScanSymbols code,int value)
|
|
{
|
|
if (!emitting) return;
|
|
activeStream.Write((int)code);
|
|
activeStream.Write(value);
|
|
if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Scanner.SymbolToString(code) + "," + value.ToString());
|
|
}
|
|
|
|
public void Emit(Scanner.ScanSymbols code,double value)
|
|
{
|
|
if (!emitting) return;
|
|
activeStream.Write((int)code);
|
|
activeStream.Write(value);
|
|
if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Scanner.SymbolToString(code) + "," + value.ToString());
|
|
}
|
|
|
|
public void Emit(Scanner.ScanSymbols code,String value)
|
|
{
|
|
if (!emitting) return;
|
|
activeStream.Write((int)code);
|
|
activeStream.Write(value);
|
|
if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Scanner.SymbolToString(code) + "," + value.ToString());
|
|
}
|
|
|
|
public long CodePointer()
|
|
{
|
|
return activeStream.BaseStream.Position;
|
|
}
|
|
|
|
public void Seek(long position)
|
|
{
|
|
activeStream.BaseStream.Seek(position, SeekOrigin.Begin);
|
|
}
|
|
|
|
public void Emit(Parser.ParserSymbols code)
|
|
{
|
|
if (!emitting) return;
|
|
long positionBefore = activeStream.BaseStream.Position;
|
|
activeStream.Write((int)code);
|
|
long positionAfter = activeStream.BaseStream.Position;
|
|
if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Parser.SymbolToString(code) + "[" + positionBefore + "," + positionAfter + "]");
|
|
}
|
|
|
|
public void Emit(Parser.ParserSymbols code,Object value)
|
|
{
|
|
if (!emitting) return;
|
|
long positionBefore = activeStream.BaseStream.Position;
|
|
activeStream.Write((int)code);
|
|
Type type = value.GetType();
|
|
activeStream.Write(type.ToString());
|
|
activeStream.Write(value.ToString());
|
|
long positionAfter = activeStream.BaseStream.Position;
|
|
if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Parser.SymbolToString(code) + "," + type.ToString() + "," + value.ToString() + "[" + positionBefore + "," + positionAfter + "]");
|
|
}
|
|
|
|
public void Emit(Parser.ParserSymbols code,Object value,int intValue)
|
|
{
|
|
if (!emitting) return;
|
|
long positionBefore = activeStream.BaseStream.Position;
|
|
activeStream.Write((int)code);
|
|
Type type = value.GetType();
|
|
activeStream.Write(type.ToString());
|
|
activeStream.Write(value.ToString());
|
|
activeStream.Write(intValue);
|
|
long positionAfter = activeStream.BaseStream.Position;
|
|
if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Parser.SymbolToString(code) + "," + type.ToString() + "," + value.ToString() + "," + intValue + "[" + positionBefore + "," + positionAfter + "]");
|
|
}
|
|
|
|
public void Emit(Parser.ParserSymbols code,long value)
|
|
{
|
|
if (!emitting) return;
|
|
long positionBefore = activeStream.BaseStream.Position;
|
|
activeStream.Write((int)code);
|
|
activeStream.Write(value);
|
|
long positionAfter = activeStream.BaseStream.Position;
|
|
if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Parser.SymbolToString(code) + "," + value.ToString() + "," + value.ToString() + "[" + positionBefore + "," + positionAfter + "]");
|
|
}
|
|
|
|
public void EmitAsNull(Parser.ParserSymbols code)
|
|
{
|
|
if (!emitting) return;
|
|
long positionBefore = activeStream.BaseStream.Position;
|
|
activeStream.Write((int)code);
|
|
Type type = typeof(System.Nullable);
|
|
activeStream.Write(type.ToString());
|
|
activeStream.Write("null".ToString());
|
|
long positionAfter = activeStream.BaseStream.Position;
|
|
if (Debug) MDTrace.WriteLine(LogLevel.DEBUG, Parser.SymbolToString(code) + "," + type.ToString() + "," + "null" + "[" + positionBefore + "," + positionAfter + "]");
|
|
}
|
|
|
|
public void Emit(int code,int op)
|
|
{
|
|
if (!emitting) return;
|
|
activeStream.Write(code);
|
|
activeStream.Write(op);
|
|
}
|
|
|
|
public void Emit(int identifier)
|
|
{
|
|
if (!emitting) return;
|
|
activeStream.Write(identifier);
|
|
}
|
|
|
|
public void Emit(byte value)
|
|
{
|
|
if (!emitting) return;
|
|
activeStream.Write(value);
|
|
}
|
|
|
|
public int Peek(ref int value)
|
|
{
|
|
value = inputStream.PeekChar();
|
|
return value;
|
|
}
|
|
|
|
public int Peek()
|
|
{
|
|
int value = inputStream.PeekChar();
|
|
return value;
|
|
}
|
|
|
|
public int PeekIgnore(ref int value,int[] ignoreChars)
|
|
{
|
|
long streamPosition = inputStream.BaseStream.Position;
|
|
while (true)
|
|
{
|
|
int readValue = (int)inputStream.ReadChar();
|
|
value = readValue;
|
|
if (!ignoreChars.Any(x => x.Equals(readValue))) break;
|
|
}
|
|
inputStream.BaseStream.Seek(streamPosition, SeekOrigin.Begin);
|
|
return value;
|
|
}
|
|
|
|
public int Read()
|
|
{
|
|
lastSymbol = inputStream.Read();
|
|
return lastSymbol;
|
|
}
|
|
|
|
public int Read(ref String literal)
|
|
{
|
|
literal = inputStream.ReadString();
|
|
return 0;
|
|
}
|
|
|
|
public int Read(ref byte value)
|
|
{
|
|
try { value = inputStream.ReadByte(); return 0; }
|
|
catch (EndOfStreamException) { return 0xFFFF; }
|
|
}
|
|
|
|
public int Read(ref int value)
|
|
{
|
|
try { value = inputStream.ReadInt32(); return 0; }
|
|
catch (EndOfStreamException) { return 0xFFFF; }
|
|
}
|
|
|
|
public int Read(ref double value)
|
|
{
|
|
try { value = inputStream.ReadDouble(); return 0; }
|
|
catch (EndOfStreamException) { return 0xFFFF; }
|
|
}
|
|
|
|
public bool Emitting
|
|
{
|
|
get { return emitting; }
|
|
set { emitting = value; }
|
|
}
|
|
}
|
|
} |