ln.lexer/SharpLexer/Grammar.cs

182 lines
3.6 KiB
C#

using System;
using System.Xml;
using System.Collections.Generic;
using lexer.match;
using lexer.buffer;
namespace lexer
{
public class Grammar
{
Dictionary<String, Sequence> sequences = new Dictionary<string, Sequence>();
public Grammar(){
}
public Grammar(String filename)
{
Load(filename);
}
public Grammar(XmlDocument xml)
{
Load(xml);
}
public void Load(String filename)
{
XmlDocument xml = new XmlDocument();
xml.Load(filename);
Load(xml);
}
public void Load(XmlDocument xml)
{
XmlNodeList tokens = xml.SelectNodes("/Grammar/Tokens/Token");
foreach (XmlNode _ntoken in tokens)
{
XmlElement ntoken = (XmlElement)_ntoken;
Console.WriteLine("Loading Token: {0}", ntoken.Attributes["name"].Value);
CharacterBuffer chb = new CharacterBuffer(ntoken.InnerText);
Sequence sequence = parseSequence(chb, ntoken.Attributes["name"].Value);
sequence.Grouping = ntoken.HasAttribute("grouping");
sequence.Notice = ntoken.HasAttribute("notice");
this.sequences.Add(ntoken.Attributes["name"].Value, sequence);
}
}
public Sequence getSequence(String name)
{
return this.sequences[name];
}
public Sequence parseSequence(CharacterBuffer chbuffer, String name = null)
{
Sequence sequence = new Sequence(name);
int min, max;
while (!chbuffer.EndOfBuffer)
{
parseWhiteSpace(chbuffer);
if (chbuffer.EndOfBuffer)
break;
min = 1;
max = 1;
if (chbuffer.Current == '[')
{
CharacterGroup cg = new CharacterGroup(chbuffer);
parseMinMax(chbuffer, ref min, ref max);
Expression e = new Expression(cg, min, max);
sequence.addMatchable(e);
}
else if (chbuffer.Current == '"')
{
CharacterSequence cs = new CharacterSequence(chbuffer);
parseMinMax(chbuffer, ref min, ref max);
Expression e = new Expression(cs, min, max);
sequence.addMatchable(e);
}
else if (chbuffer.Current == '(')
{
chbuffer.MoveNext();
Sequence s = parseSequence(chbuffer);
parseMinMax(chbuffer, ref min, ref max);
Expression e = new Expression(s, min, max);
sequence.addMatchable(e);
}
else if (chbuffer.Current == '|')
{
Alternative alt = new Alternative();
alt.addMatchable(sequence);
chbuffer.MoveNext();
alt.addMatchable(parseSequence(chbuffer));
return alt;
}
else if (chbuffer.Current == ')')
{
chbuffer.MoveNext();
return sequence;
}
else
{
char[] sym = chbuffer.findSymbol();
Matchable m = Matchable.getNamedMatchable(sym);
if (m == null){
m = new Matchable.DeferredMatchable(sym);
}
parseMinMax(chbuffer, ref min, ref max);
Expression e = new Expression(m, min, max);
sequence.addMatchable(e);
}
}
return sequence;
}
public void parseWhiteSpace(CharacterBuffer chbuffer)
{
while (chbuffer.Current <= 0x20)
{
chbuffer.MoveNext();
}
}
public void parseMinMax(CharacterBuffer chbuffer, ref int min,ref int max){
if (chbuffer.Current == '{'){
chbuffer.MoveNext();
char[] def = chbuffer.find('}');
if (def.Length > 0)
{
int pcomma = -1;
while ((++pcomma < def.Length) && (def[pcomma] != ',')) { }
if (pcomma == 0)
{
min = 0;
} else {
min = int.Parse(new String(def, 0, pcomma));
}
if (pcomma == def.Length - 1)
{
max = int.MaxValue;
} else if (pcomma == def.Length){
max = min;
} else {
pcomma++;
max = int.Parse(new String(def, pcomma, def.Length - pcomma));
}
return;
}
}
min = 1;
max = 1;
}
}
}