summaryrefslogtreecommitdiff
path: root/src/lexer.cpp
diff options
context:
space:
mode:
authorMike Buland <mike@xagasoft.com>2013-04-22 13:05:22 -0600
committerMike Buland <mike@xagasoft.com>2013-04-22 13:05:22 -0600
commit2909f50d008920568f0e50da760b266388ccc124 (patch)
tree6789c162a2b950c2006c944e9d21e6ed9bda7069 /src/lexer.cpp
parentd7ccd9c4d8e5a5bb4f12b36b3e4ad3105c5a9317 (diff)
downloadclic-2909f50d008920568f0e50da760b266388ccc124.tar.gz
clic-2909f50d008920568f0e50da760b266388ccc124.tar.bz2
clic-2909f50d008920568f0e50da760b266388ccc124.tar.xz
clic-2909f50d008920568f0e50da760b266388ccc124.zip
There is now a parser & calculator interface.
Diffstat (limited to 'src/lexer.cpp')
-rw-r--r--src/lexer.cpp163
1 files changed, 163 insertions, 0 deletions
diff --git a/src/lexer.cpp b/src/lexer.cpp
new file mode 100644
index 0000000..834d3bc
--- /dev/null
+++ b/src/lexer.cpp
@@ -0,0 +1,163 @@
1#include "lexer.h"
2#include "token.h"
3#include "number.h"
4
5#include <bu/sio.h>
6
7Lexer::Lexer( Bu::Stream &rIn ) :
8 rIn( rIn ),
9 iBufPos( 0 ),
10 iScale( 0 ),
11 iRadix( 10 ),
12 numRangeTop('9'),
13 ascRangeTop(0)
14{
15}
16
17Lexer::~Lexer()
18{
19}
20
21Token Lexer::nextToken()
22{
23 for(;;)
24 {
25 if( iBufPos >= sBuf.getSize() )
26 {
27 iBufPos = -1;
28 return Token( Token::tEndOfLine );
29 }
30
31 if( iBufPos < 0 )
32 {
33 if( rIn.isEos() )
34 return Token( Token::tEndOfInput );
35
36 sBuf = rIn.readLine();
37 if( sBuf.getSize() == 0 )
38 {
39 iBufPos = -1;
40 continue;
41 }
42 iBufPos = 0;
43 }
44
45 //Bu::println("Testing char '%1' at %2").arg( sBuf[iBufPos] ).arg( iBufPos );
46 switch( sBuf[iBufPos] )
47 {
48 case ' ':
49 case '\t':
50 iBufPos++;
51 break;
52
53 case '\\':
54 {
55 Bu::String *sTmp = new Bu::String();
56 for( iBufPos++; iBufPos < sBuf.getSize() &&
57 sBuf[iBufPos] != ' ' && sBuf[iBufPos] != '\t';
58 iBufPos++ )
59 {
60 sTmp->append( sBuf[iBufPos] );
61 }
62 return Token( Token::tCommand, sTmp );
63 }
64 break;
65
66 case '+':
67 iBufPos++;
68 return Token( Token::tPlus );
69
70 case '-':
71 iBufPos++;
72 return Token( Token::tMinus );
73
74 case '*':
75 iBufPos++;
76 return Token( Token::tMultiply );
77
78 case '/':
79 iBufPos++;
80 return Token( Token::tDivide );
81
82 case '(':
83 iBufPos++;
84 return Token( Token::tOpenParen );
85
86 case ')':
87 iBufPos++;
88 return Token( Token::tCloseParen );
89
90 default:
91 {
92 Bu::String *sTmp = new Bu::String();
93 if( (sBuf[iBufPos] >= '0' &&
94 sBuf[iBufPos] <= numRangeTop) ||
95 (sBuf[iBufPos] >= 'a' &&
96 sBuf[iBufPos] <= ascRangeTop) ||
97 sBuf[iBufPos] == '.' )
98 {
99 for( ; iBufPos < sBuf.getSize() ; iBufPos++ )
100 {
101 if( (sBuf[iBufPos] >= '0' &&
102 sBuf[iBufPos] <= numRangeTop) ||
103 (sBuf[iBufPos] >= 'a' &&
104 sBuf[iBufPos] <= ascRangeTop) ||
105 sBuf[iBufPos] == '.' )
106 {
107 sTmp->append( sBuf[iBufPos] );
108 }
109 else
110 {
111 break;
112 }
113 }
114 Number *n = new Number( *sTmp, iScale, iRadix );
115 delete sTmp;
116 return Token( Token::tNumber, n );
117 }
118 else if( (sBuf[iBufPos]>=(ascRangeTop+1) && sBuf[iBufPos]<='z') ||
119 (sBuf[iBufPos]>='A' && sBuf[iBufPos]<='Z') ||
120 sBuf[iBufPos] == '_' )
121 {
122 for( ; iBufPos < sBuf.getSize(); iBufPos++ )
123 {
124 if( (sBuf[iBufPos]>='a' && sBuf[iBufPos]<='z') ||
125 (sBuf[iBufPos]>='A' && sBuf[iBufPos]<='Z') ||
126 (sBuf[iBufPos]>='0' && sBuf[iBufPos]<='9') ||
127 sBuf[iBufPos] == '_' )
128 {
129 sTmp->append( sBuf[iBufPos] );
130 }
131 else
132 {
133 break;
134 }
135 }
136 return Token( Token::tString, sTmp );
137 }
138 else
139 {
140 sBuf.clear();
141 Bu::println("Invalid character discovered!");
142 }
143 }
144 break;
145 }
146 }
147}
148
149void Lexer::setRadix( int i )
150{
151 iRadix = i;
152 if( iRadix <= 10 )
153 {
154 numRangeTop = '0'+iRadix-1;
155 ascRangeTop = 0;
156 }
157 else
158 {
159 numRangeTop = '9';
160 ascRangeTop = 'a'+iRadix-11;
161 }
162}
163