using System; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; namespace Microsoft.HaniA.MathEvaluater { class Scanner { private string _str; private int _index; private Token _currentToken; private string _value; private int _tokenIndex; private static List _tokenRegs; class TokenRegularExpression { Token _token; Regex _regex; public TokenRegularExpression(Token token, string pattern) { _token = token; _regex = new Regex(pattern, RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Singleline); } public Token Token { get { return _token; } } public Regex Regex { get { return _regex; } } } static Scanner() { _tokenRegs = new List(); // Initialize all the patters for Tokens _tokenRegs.Add(new TokenRegularExpression(Token.Addition, @"\G\+")); _tokenRegs.Add(new TokenRegularExpression(Token.Subtraction, @"\G-")); _tokenRegs.Add(new TokenRegularExpression(Token.Number, @"\G[0-9]+(\.[0-9]+)?")); _tokenRegs.Add(new TokenRegularExpression(Token.Symbol, @"\G[_a-z][_a-z0-9]*")); _tokenRegs.Add(new TokenRegularExpression(Token.Assignment, @"\G=")); _tokenRegs.Add(new TokenRegularExpression(Token.Division, @"\G[/\\]")); _tokenRegs.Add(new TokenRegularExpression(Token.Multiplication, @"\G\*")); _tokenRegs.Add(new TokenRegularExpression(Token.Power, @"\G\^")); _tokenRegs.Add(new TokenRegularExpression(Token.CloseParenthesis, @"\G\)")); _tokenRegs.Add(new TokenRegularExpression(Token.OpenParenthesis, @"\G\(")); _tokenRegs.Add(new TokenRegularExpression(Token.Comma, @"\G,")); _tokenRegs.Add(new TokenRegularExpression(Token.Semicolon, @"\G;")); _tokenRegs.Add(new TokenRegularExpression(Token.QuestionMark, @"\G\?")); } public Scanner() : this(null) { } public Scanner(string str) { Source = str; } public string Source { get { return _str; } set { _str = value; _index = 0; _tokenIndex = -1; _currentToken = Token.None; _value = null; } } public bool ReadNext() { EatSpaces(); if (_index < _str.Length) { foreach (TokenRegularExpression tokenReg in _tokenRegs) { Match m = tokenReg.Regex.Match(_str, _index); if (m.Success) { // found a match _currentToken = tokenReg.Token; _value = m.Value; _tokenIndex = _index; _index += m.Length; return true; } } // Couldn't find any match, throw an error throw new ApplicationException(string.Format("Unrecognized character at {0} '{1}'.", _index + 1, _str[_index])); } else { // We finished scanning the string _currentToken = Token.End; _value = null; _tokenIndex = _str.Length; return false; } } private void EatSpaces() { while (_index < _str.Length && (_str[_index] == ' ' || _str[_index] == '\t')) { _index++; } } public Token CurrentToken { get { return _currentToken; } } public string Value { get { return _value; } } public int TokenIndex { get { return _tokenIndex; } } } enum Token { None, OpenParenthesis, CloseParenthesis, Comma, Semicolon, QuestionMark, Addition, Subtraction, Multiplication, Division, Power, Assignment, Number, Symbol, End, } }