Original Post
I've just written my first Lexer, Parser, Compiler and Interpreter. It's not anywhere near complex, but it does confirm that 2 + 2 = 4. I'm looking for, specifically, critique of the basic concepts and base code I'm using. Best to make sure the foundation isn't cracked and all that. Any comments about 'highly incomplete' will be fed to the dragons. Thanks for any and all help. Lexer Parser (With Rules) Compiler and PTNode and derivatives. Yes, I've stuck the compilation function in the PTNode class. It makes sense to me. If there's some reason not to, please tell me - This is my first real compiler (My first two, I had no idea what I was doing. Now I have a slight clue) And interpreter. [Edited by - Narf the Mouse on October 1, 2009 7:52:24 PM]
public class Lexer
{
public Lexer()
{
tokenConverter.Add("+", "+");
tokenConverter.Add(" +", "+");
tokenConverter.Add(" + ", "+");
tokenConverter.Add("+ ", "+");
}
public string Lexigate(string script)
{
foreach (KeyValuePair<string, string> kvp in tokenConverter)
{
script = script.Replace(kvp.Key, kvp.Value);
}
return script;
}
protected Dictionary<string, string> tokenConverter =
new Dictionary<string,string>();
}
public class Parser
{
public PTNode Parse(string script)
{
int t = 0,
count = script.Length;
bool found = false,
check = false;
PTNode root = new PTNode(),
checkForNode;
do
{
foreach (Rule rule in baseRules)
{
if (tokens.Contains(script[t]))
{
if (rule.CheckFor(script, ref t, 1, out checkForNode))
{
check = true;
root.Add(checkForNode);
}
}
else
{
++t;
check = true;
}
}
found = check;
}while(found == true && t < count);
return root;
}
public List<char> tokens = new List<char>(
new char[]
{
'+'
}
);
public List<Rule> baseRules = new List<Rule>(
new Rule[]
{
new RuleAddition()
}
);
}
public abstract class Rule
{
public abstract bool CheckFor(string text, ref int pointer, int scanDir, out PTNode ret);
}
public class RuleAddition : Rule
{
public override bool CheckFor(string text, ref int pointer, int scanDir, out PTNode ret)
{
if (text[pointer] == '+')
{
PTNode left;
PTNode right;
if (ruleInteger.CheckFor(text, ref pointer, -1, out left) &&
ruleInteger.CheckFor(text, ref pointer, 1, out right))
ret = new PTNodeAdd(left, right);
else throw new InvalidOperationException("Difficulty finding things to add.");
pointer += scanDir;
return true;
}
ret = null;
return false;
}
protected RuleInteger ruleInteger = new RuleInteger();
}
public class RuleInteger : Rule
{
public override bool CheckFor(string text, ref int pointer, int scanDir, out PTNode ret)
{
string subString;
bool success = false;
int value = 0;
int from = pointer;
if (scanDir < 0)
{
do
{
from += scanDir;
subString = text.Substring(from, (pointer - from));
success = int.TryParse(subString, out value);
} while (!success && pointer - scanDir <= 13);
}
else if (scanDir > 0)
{
do
{
from += scanDir;
subString = text.Substring(pointer + 1, from - (pointer));
success = int.TryParse(subString, out value);
} while (!success && scanDir - (pointer + 1) <= 13);
if (success)
pointer = from;
}
if (success)
ret = new PTNodeAssign(value);
else
ret = null;
return success;
}
}
public class PTNode
{
protected PTNodeType nodeType;
protected List<PTNode> subNodes;
public int? value;
public void Add(PTNode node) { if (subNodes == null) subNodes = new List<PTNode>(); subNodes.Add(node); }
public Stack<int> Compile()
{
Stack<int> stack = new Stack<int>();
foreach (PTNode node in subNodes)
{
node.Compile(stack);
}
return stack;
}
public virtual void Compile(Stack<int> stack)
{
if (subNodes != null)
foreach (PTNode node in subNodes)
{
node.Compile(stack);
}
}
public override string ToString()
{
string toString = "Root: ";
foreach (PTNode node in subNodes)
toString += node.ToString();
return toString;
}
}
public class PTNodeAdd : PTNode
{
public PTNodeAdd(PTNode left, PTNode right) { Add(left); Add(right); nodeType = PTNodeType.Binary; }
public override void Compile(Stack<int> stack)
{
stack.Push((int)FuncCodes.Add);
base.Compile(stack);
}
public override string ToString()
{
return subNodes[0].ToString() + " + " + subNodes[1].ToString() + ", ";
}
}
public class PTNodeAssign : PTNode
{
public PTNodeAssign(int value) { this.value = value; nodeType = PTNodeType.Assignary; }
public override void Compile(Stack<int> stack)
{
if (value.HasValue)
stack.Push(value.Value);
base.Compile(stack);
}
public override string ToString()
{
return value.ToString();
}
}
public class Interpreter
{
public Interpreter()
{
operationLookupTable.Add(FuncCodes.Add, Add);
}
public Stack<int> Run(Stack<int> stack)
{
Stack<int> stack2 = new Stack<int>(stack);
pointer = 0;
while (pointer < operationLookupTable.Count)
operationLookupTable[(FuncCodes)stack2.Pop()](stack2);
return stack2;
}
protected int pointer;
protected List<FuncCodes> program = new List<FuncCodes>(
new FuncCodes[]
{
FuncCodes.Add
}
);
protected delegate void Op(Stack<int> stackList);
protected Dictionary<FuncCodes, Op> operationLookupTable =
new Dictionary<FuncCodes,Op>();
protected void Add(Stack<int> stack)
{
stack.Push(stack.Pop() + stack.Pop());
++pointer;
}
}
public enum FuncCodes
{
Add
}