using System; using sharp.extensions; using System.Collections.Generic; using System.Linq; namespace sharp.parser { public class CharBuffer { char[] chars; int position; int lineno, linepos, linestart; int[] lineStarts; public char[] Characters { get { return this.chars; } } public CharBuffer(char[] source) { this.chars = source; this.initialize(); } public CharBuffer(string source){ this.chars = source.ToCharArray(); this.initialize(); } private void initialize(){ this.lineno = 1; this.linepos = 1; this.linestart = 0; List lineStartList = new List(); lineStartList.Add(0); for (int n = 0; n < this.chars.Length;n++) { if (this.chars[n] == 0x0a){ lineStartList.Add(n); } } lineStartList.Add(this.chars.Length); this.lineStarts = lineStartList.ToArray(); } private int lineEnd(){ int p = position; while (this.chars[p]!='\n'){ p++; if (p >= this.chars.Length){ break; } } return p; } public string getLineAt(int pos){ int n; if (pos >= this.chars.Length){ return null; } for (n = 0; n < this.lineStarts.Count();n++){ if (pos >= this.lineStarts[n]){ break; } } return new string( this.chars.Segment(this.lineStarts[n],this.lineStarts[n+1]-this.lineStarts[n]) ); } public int Position { get { return position; } set { this.position = value >= chars.Length ? chars.Length : value; } } public bool MoveNext(){ if (position < this.chars.Length){ position++; this.linepos++; if (Last == '\n'){ this.linepos = 1; this.linestart = position; this.lineno++; } return true; } return false; } public bool MoveBack(){ if (position > 0){ position--; return true; } return false; } public bool EndOfBuffer(){ return (this.position >= this.chars.Length); } public void BypassWhiteSpace(){ while (Current <= 0x20){ MoveNext(); } } public int CurrentLineNumber { get { return this.lineno; } } public int CurrentLinePosition { get { return this.linepos; } } public string CurrentLine { get { return new String(this.chars.Segment(this.linestart,lineEnd()-this.linestart)); } } public char Last { get { if (position > 0) { return this.chars[position - 1]; }; throw new IndexOutOfRangeException("No character before the first one"); } } public char Current { get { if (position < this.chars.Length){ return this.chars[position]; } throw new IndexOutOfRangeException("No character after the last one"); } } public char Next { get { if (position < this.chars.Length-1) { return this.chars[position + 1]; }; throw new IndexOutOfRangeException("No character after the last one"); } } public string Following(int len) { return new string(this.chars.Segment(position, len)); } public string Preceding(int len) { return new string(this.chars.Segment(position-len, len)); } public void Pass(char ch){ if (Current != ch){ throw new ParserFormatException(String.Format("Expected {0}, but got {1}",ch,Current),lineno,linepos,CurrentLine); } MoveNext(); } } }