1 using System;
2
3 namespace Calculator
4 {
5 public inline bool IsNumberChar(uchar c)
6 {
7 return IsAsciiDigit(c) || c == '.';
8 }
9
10 public class Scanner
11 {
12 public nothrow Scanner(const ustring& input_) : input(input_)
13 {
14 }
15 public inline nothrow Token* CurrentToken() const
16 {
17 return token.Get();
18 }
19 public void NextToken()
20 {
21 SkipWhiteSpace();
22 if (pos < input.Length())
23 {
24 if (IsNumberChar(input[pos]))
25 {
26 int start = pos;
27 ++pos;
28 while (pos < input.Length() && IsNumberChar(input[pos]))
29 {
30 ++pos;
31 }
32 double number = ParseDouble(ToUtf8(input.Substring(start, pos - start)));
33 token.Reset(new NumberToken(number));
34 }
35 else if (IsIdStart(input[pos]))
36 {
37 int start = pos;
38 ++pos;
39 while (pos < input.Length() && IsIdCont(input[pos]))
40 {
41 ++pos;
42 }
43 ustring variableName = input.Substring(start, pos - start);
44 if (ToLower(variableName) == u"print")
45 {
46 token.Reset(new PrintToken());
47 }
48 else
49 {
50 token.Reset(new VariableNameToken(variableName));
51 }
52 }
53 else
54 {
55 token.Reset(new OperatorToken(input[pos]));
56 ++pos;
57 }
58 }
59 else
60 {
61 token.Reset(new EndToken());
62 }
63 }
64 public void Rewind()
65 {
66 pos = 0;
67 }
68 private void SkipWhiteSpace()
69 {
70 while (pos < input.Length() && (input[pos] == ' ' || input[pos] == '\t'))
71 {
72 ++pos;
73 }
74 }
75 private UniquePtr<Token> token;
76 private ustring input;
77 private int pos;
78 }
79 }