mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 20:39:01 +00:00
119 lines
3.8 KiB
C#
119 lines
3.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace Cosmos.Compiler.XSharp {
|
|
public class TokenList : List<Token> {
|
|
|
|
public Token this[int aIdx] {
|
|
get {
|
|
if (aIdx < 0) {
|
|
aIdx = Count + aIdx;
|
|
}
|
|
return base[aIdx];
|
|
}
|
|
set {
|
|
if (aIdx < 0) {
|
|
aIdx = Count + aIdx;
|
|
}
|
|
base[aIdx] = value;
|
|
}
|
|
}
|
|
|
|
public Token Last() {
|
|
return base[Count - 1];
|
|
}
|
|
|
|
public int GetPatternHashCode() {
|
|
int xResult = 0;
|
|
var xBytes = new byte[4];
|
|
for (int i = 0; i < Count; i = i + 4) {
|
|
for (int j = 0; j < 4; j++) {
|
|
if (j < Count) {
|
|
xBytes[j] = (byte)base[i].Type;
|
|
} else {
|
|
xBytes[j] = 0;
|
|
}
|
|
}
|
|
xResult = xResult ^ BitConverter.ToInt32(xBytes, 0);
|
|
}
|
|
xResult = xResult ^ Count;
|
|
return xResult;
|
|
}
|
|
|
|
protected bool RegistersMatch(string aThisUpper, string aThatUpper, string aPattern, string[] aRegisters) {
|
|
// ONLY check if its our pattern. We need to return true to continue other pattern checks
|
|
// if not current pattern.
|
|
if (aThisUpper == aPattern || aThatUpper == aPattern) {
|
|
if (aRegisters.Contains(aThatUpper) || aRegisters.Contains(aThisUpper)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public bool PatternMatches(string aPattern) {
|
|
var xParser = new Parser(aPattern, false, true);
|
|
return PatternMatches(xParser.Tokens);
|
|
}
|
|
public bool PatternMatches(TokenList aObj) {
|
|
// Dont compare TokenHashCodes, they take just as long to calculate
|
|
// as a full comparison. Besides this function is often called after
|
|
// comparing hash codes already.
|
|
|
|
if (Count != aObj.Count) {
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < aObj.Count; i++) {
|
|
var xThis = this[i];
|
|
var xThat = aObj[i];
|
|
if (xThis.Type != xThat.Type) {
|
|
return false;
|
|
} else if (xThis.Type == TokenType.AlphaNum || xThis.Type == TokenType.Keyword || xThis.Type == TokenType.Operator || xThis.Type == TokenType.Delimiter) {
|
|
if (xThis.Value == null || aObj[i].Value == null) {
|
|
} else if (string.Compare(xThis.Value, xThat.Value, true) != 0) {
|
|
return false;
|
|
}
|
|
} else if (xThis.Type == TokenType.Register) {
|
|
string xThisUpper = xThis.Value.ToUpper();
|
|
string xThatUpper = xThat.Value.ToUpper();
|
|
|
|
if (xThisUpper == "_REG" || xThatUpper == "_REG") {
|
|
// true, ie continue
|
|
} else if (RegistersMatch(xThisUpper, xThatUpper, "_REG8", Parser.Registers8)) {
|
|
} else if (RegistersMatch(xThisUpper, xThatUpper, "_REG16", Parser.Registers16)) {
|
|
} else if (RegistersMatch(xThisUpper, xThatUpper, "_REG32", Parser.Registers32)) {
|
|
} else if (RegistersMatch(xThisUpper, xThatUpper, "_REGIDX", Parser.RegistersIdx)) {
|
|
} else if (RegistersMatch(xThisUpper, xThatUpper, "_REGADDR", Parser.RegistersAddr)) {
|
|
} else if (xThisUpper == xThatUpper) {
|
|
// This covers _REG==_REG, _REG8==_REG8, ... and DX==DX
|
|
// Must be last, after patterns
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public int IndexOf(string aValue) {
|
|
for (int i = 0; i < Count; i++) {
|
|
if (this[i].Value == aValue) {
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
// We could use values to further differntiate, however
|
|
// with types alone it still provides a decent and fash hash.
|
|
public override int GetHashCode() {
|
|
return GetPatternHashCode();
|
|
}
|
|
}
|
|
}
|