Console calculator Part 1 : The Scanner

Please support our C# advertiser: Intel Parallel Studio Home
ddanbe ddanbe is offline Offline Nov 17th, 2008, 6:54 pm |
0
This is a series of 3 code snippets which together form a completly working "calculator".
I used a console application in VS C# 2008, but 2005 should cause no problems.
To start with : here you have the code for a scanner class.
A scanner reads the inputline and tries to get some meaningfull words(sometimes called tokens) from it. It then passes that information to a parser.
Quick reply to this message  
C# Syntax
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5.  
  6. namespace ConsoleCalculator
  7. {
  8. class Scanner
  9. {
  10. /// <summary>
  11. /// Scanner class, main routine here is get_token.
  12. /// get_token returns the next token_value to the parser,
  13. /// and sets some variables. It is up to the parser to decide
  14. /// what to do next.
  15. /// </summary>
  16.  
  17. public enum token_value
  18. {
  19. NAME, NUMBER, END, LIST, HELP, SQRT,
  20. PLUS = '+', MINUS = '-',
  21. MUL = '*', DIV = '/',
  22. PRINT = ';', ASSIGN = '=',
  23. LPAREN = '(', RPAREN = ')',
  24. };
  25.  
  26. public token_value curr_tok; //current token value found
  27. public double number_value; //if the token was a number the value is held here
  28. public string name_string; //if the token was a variable name, the name can be found here
  29.  
  30. private char[] StringToParse; //the "inputstream"
  31. private int charpos = 0; //position of the next character to read from the inputstream
  32. private StringBuilder numberSB = new StringBuilder();
  33. private StringBuilder nameSB = new StringBuilder();
  34.  
  35.  
  36. /// <summary>
  37. /// Two generic Dictionary's that use hashing to store string keys and values for
  38. /// variables, commands and reserved words.
  39. /// SymbolTable is public, the parser likes this table too
  40. /// </summary>
  41. public Dictionary<string, double> SymbolTable = new Dictionary<string, double>();
  42. private Dictionary<string, token_value> ReservedWords = new Dictionary<string, token_value>();
  43.  
  44. /// <summary>
  45. /// Scanner default custom constructor, defines a small set of reseved words,
  46. /// used to give special commands to the calculator.
  47. /// </summary>
  48. public Scanner()
  49. {
  50. ReservedWords.Add("END", token_value.END); //Quit the application.
  51. ReservedWords.Add("LIST", token_value.LIST);//Show a list of all variables in the calculator.
  52. ReservedWords.Add("?", token_value.HELP); //Display help info
  53. ReservedWords.Add("SQRT", token_value.SQRT); //Function to take the square root
  54. }
  55.  
  56. //property to pass the inputline to the scanner
  57. //---------------------------------------------
  58. public string InputLine
  59. {
  60. set
  61. {
  62. string line = value + "\n";
  63. StringToParse = line.ToCharArray();
  64. }
  65. }
  66.  
  67. //for functions we must first find a left parentesis
  68. //--------------------------------------------------
  69. public bool FindLeftParentesis()
  70. {
  71. char ch;
  72. try
  73. {
  74. do
  75. {
  76. ch = GetChar();
  77. }
  78. while (!ch.Equals('('));
  79. return true;
  80. }
  81. catch
  82. {
  83. Error("( expected"); return false;
  84. }
  85. }
  86.  
  87. //find a character in the "inputstream"
  88. //-------------------------------------
  89. private char GetChar()
  90. {
  91. char ch = StringToParse[charpos];
  92. charpos++;
  93. return ch;
  94. }
  95.  
  96. public void PutBackChar()
  97. {
  98. charpos--;
  99. }
  100.  
  101. public void InitScan()
  102. {
  103. charpos = 0;
  104. number_value = 0.0;
  105. name_string = "";
  106. }
  107.  
  108. public void Error(string message)
  109. {
  110. //minor error handling, but sufficient for the moment
  111. Console.ForegroundColor = ConsoleColor.Black;
  112. Console.BackgroundColor = ConsoleColor.Cyan;
  113. Console.WriteLine(message);
  114. Console.ResetColor();
  115. }
  116.  
  117. /// <summary>
  118. /// Main function of the scanner returns the current token and
  119. /// sets the variables name_string and number_value when appropriate.
  120. /// </summary>
  121. /// <returns></returns>
  122. public token_value get_token()
  123. {
  124. char ch;
  125.  
  126. do //skip whitespace except '\n'
  127. {
  128. ch = GetChar();
  129. }
  130. while (ch != '\n' && char.IsWhiteSpace(ch));
  131. switch (ch)
  132. {
  133. case ';': case '\n':
  134. curr_tok = token_value.PRINT;
  135. return curr_tok;
  136. case '*':
  137. case '/':
  138. case '+':
  139. case '-':
  140. case '(':
  141. case ')':
  142. case '=':
  143. curr_tok = (token_value)(ch);
  144. return curr_tok;
  145. case '0':
  146. case '1':
  147. case '2':
  148. case '3':
  149. case '4':
  150. case '5':
  151. case '6':
  152. case '7':
  153. case '8':
  154. case '9':
  155. case '.':
  156. case ',':
  157. if (ch == '.') ch = ',';
  158. numberSB.Append(ch);
  159. ch = GetChar();
  160. if (ch == '.') ch = ',';
  161. while (char.IsDigit(ch) || ch == ',')
  162. {
  163. numberSB.Append(ch);
  164. ch = GetChar();
  165. }
  166. PutBackChar();
  167. try
  168. {
  169. number_value = Convert.ToDouble(numberSB.ToString());
  170. numberSB.Remove(0, numberSB.Length);
  171. }
  172. catch
  173. {
  174. Error("Fout in formaat van getal.");
  175. }
  176. return token_value.NUMBER;
  177. default:
  178. if (char.IsLetter(ch) | ch.Equals('?'))
  179. {
  180. nameSB.Append(ch);
  181. ch = GetChar();
  182. while (char.IsLetterOrDigit(ch))
  183. {
  184. nameSB.Append(ch);
  185. ch = GetChar();
  186. }
  187. PutBackChar();
  188. name_string = nameSB.ToString();
  189. nameSB.Remove(0, nameSB.Length);
  190. if (ReservedWords.TryGetValue(name_string.ToUpper(), out curr_tok)) return curr_tok;
  191. return token_value.NAME;
  192. }
  193.  
  194. Error("Bad token.");
  195. return token_value.PRINT;
  196. }
  197. } //end get_token
  198.  
  199. //print a list of all the variables defined in the symboltable
  200. //------------------------------------------------------------
  201. public void ListVars()
  202. {
  203. Console.WriteLine("+-------------------------------------------+");
  204. Console.WriteLine("| List of variables : |");
  205. Console.WriteLine("+-------------------------------------------+");
  206. Console.WriteLine();
  207. foreach (KeyValuePair<string, double> kvp in SymbolTable)
  208. {
  209. Console.WriteLine("Var = {0} \t = {1}", kvp.Key, kvp.Value);
  210. } //yeah, generics is something to get used to
  211. Console.WriteLine("+-------------------------------------------+");
  212. }
  213. }
  214. }
0
ddanbe ddanbe is offline Offline | Nov 18th, 2008
application in VS C# 2008, but 2005 should cause no problems.
The application makes use of generics in C# I don't know if version 2005 supports generics...
 
 

Message:


Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC