73 // |
73 // |
74 ExpressionSymbol* Expression::ParseSymbol() |
74 ExpressionSymbol* Expression::ParseSymbol() |
75 { |
75 { |
76 int pos = mLexer->GetPosition(); |
76 int pos = mLexer->GetPosition(); |
77 ExpressionValue* op = null; |
77 ExpressionValue* op = null; |
78 enum ELocalException { failed }; |
78 |
79 |
79 if (mLexer->GetNext (tkColon)) |
80 try |
80 return new ExpressionColon; |
81 { |
81 |
82 mLexer->MustGetNext (tkAny); |
82 // Check for operator |
83 |
83 for (const OperatorInfo& op : gOperators) |
84 if (mLexer->GetTokenType() == tkColon) |
84 if (mLexer->GetNext (op.token)) |
85 return new ExpressionColon; |
85 return new ExpressionOperator ((EOperator) (&op - &gOperators[0])); |
86 |
86 |
87 // Check for operator |
87 // Check sub-expression |
88 for (const OperatorInfo& op : gOperators) |
88 if (mLexer->GetNext (tkParenStart)) |
89 if (mLexer->GetTokenType() == op.token) |
89 { |
90 return new ExpressionOperator ((EOperator) (&op - &gOperators[0])); |
90 Expression expr (mParser, mLexer, mType); |
91 |
91 mLexer->MustGetNext (tkParenEnd); |
92 // Check sub-expression |
92 return expr.GetResult()->Clone(); |
93 if (mLexer->GetTokenType() == tkParenStart) |
93 } |
94 { |
94 |
95 Expression expr (mParser, mLexer, mType); |
95 op = new ExpressionValue (mType); |
96 mLexer->MustGetNext (tkParenEnd); |
96 |
97 return expr.GetResult()->Clone(); |
97 // Check function |
98 } |
98 if (CommandInfo* comm = FindCommandByName (mLexer->PeekNextString())) |
99 |
99 { |
100 op = new ExpressionValue (mType); |
100 mLexer->Skip(); |
101 |
101 |
102 // Check function |
102 if (mType != EUnknownType && comm->returnvalue != mType) |
103 if (CommandInfo* comm = FindCommandByName (GetTokenString())) |
103 Error ("%1 returns an incompatible data type", comm->name); |
104 { |
104 |
105 if (mType != EUnknownType && comm->returnvalue != mType) |
105 op->SetBuffer (mParser->ParseCommand (comm)); |
106 Error ("%1 returns an incompatible data type", comm->name); |
106 return op; |
107 |
107 } |
108 op->SetBuffer (mParser->ParseCommand (comm)); |
108 |
109 return op; |
109 // Check for variables |
110 } |
110 if (mLexer->GetNext (tkDollarSign)) |
111 |
111 { |
112 // Check for variables |
112 mLexer->MustGetNext (tkSymbol); |
113 if (mLexer->GetTokenType() == tkDollarSign) |
113 Variable* var = mParser->FindVariable (GetTokenString()); |
114 { |
114 |
115 mLexer->MustGetNext (tkSymbol); |
115 if (var == null) |
116 Variable* globalvar = mParser->FindVariable (GetTokenString()); |
116 Error ("unknown variable %1", GetTokenString()); |
117 |
117 |
118 if (globalvar == null) |
118 if (var->type != mType) |
119 Error ("unknown variable %1", GetTokenString()); |
119 Error ("expression requires %1, variable $%2 is of type %3", |
120 |
120 GetTypeName (mType), var->name, GetTypeName (var->type)); |
121 if (globalvar->writelevel == Variable::WRITE_Constexpr) |
121 |
122 op->SetValue (globalvar->value); |
122 if (var->isarray) |
|
123 { |
|
124 mLexer->MustGetNext (tkBracketStart); |
|
125 Expression expr (mParser, mLexer, EIntType); |
|
126 expr.GetResult()->ConvertToBuffer(); |
|
127 DataBuffer* buf = expr.GetResult()->GetBuffer()->Clone(); |
|
128 buf->WriteDWord (dhPushGlobalArray); |
|
129 buf->WriteDWord (var->index); |
|
130 op->SetBuffer (buf); |
|
131 mLexer->MustGetNext (tkBracketEnd); |
|
132 } |
|
133 elif (var->writelevel == Variable::WRITE_Constexpr) |
|
134 op->SetValue (var->value); |
|
135 else |
|
136 { |
|
137 DataBuffer* buf = new DataBuffer (8); |
|
138 |
|
139 if (var->IsGlobal()) |
|
140 buf->WriteDWord (dhPushGlobalVar); |
123 else |
141 else |
124 { |
142 buf->WriteDWord (dhPushLocalVar); |
125 DataBuffer* buf = new DataBuffer (8); |
143 |
126 buf->WriteDWord (dhPushGlobalVar); |
144 buf->WriteDWord (var->index); |
127 buf->WriteDWord (globalvar->index); |
145 op->SetBuffer (buf); |
128 op->SetBuffer (buf); |
146 } |
129 } |
147 |
130 |
148 return op; |
131 return op; |
149 } |
132 } |
150 |
133 |
151 // Check for literal |
134 EToken tt; |
152 switch (mType) |
135 |
153 { |
136 // Check for literal |
154 case EVoidType: |
137 switch (mType) |
155 case EUnknownType: |
138 { |
156 { |
139 case EVoidType: |
157 Error ("unknown identifier `%1` (expected keyword, function or variable)", GetTokenString()); |
140 case EUnknownType: |
158 break; |
141 { |
159 } |
142 Error ("unknown identifier `%1` (expected keyword, function or variable)", GetTokenString()); |
160 |
143 break; |
161 case EBoolType: |
144 } |
162 { |
145 |
163 if (mLexer->GetNext (tkTrue) || mLexer->GetNext (tkFalse)) |
146 case EBoolType: |
164 { |
147 { |
165 EToken tt = mLexer->GetTokenType(); |
148 if ((tt = mLexer->GetTokenType()) == tkTrue || tt == tkFalse) |
166 op->SetValue (tt == tkTrue ? 1 : 0); |
149 { |
167 return op; |
150 op->SetValue (tt == tkTrue ? 1 : 0); |
168 } |
151 return op; |
169 } |
152 } |
170 |
153 } |
171 case EIntType: |
154 case EIntType: |
172 { |
155 { |
173 if (mLexer->GetNext (tkNumber)) |
156 if (mLexer->GetTokenType() != tkNumber) |
174 { |
157 throw failed; |
|
158 |
|
159 op->SetValue (GetTokenString().ToLong()); |
175 op->SetValue (GetTokenString().ToLong()); |
160 return op; |
176 return op; |
161 } |
177 } |
162 |
178 } |
163 case EStringType: |
179 |
164 { |
180 case EStringType: |
165 if (mLexer->GetTokenType() != tkString) |
181 { |
166 throw failed; |
182 if (mLexer->GetNext (tkString)) |
167 |
183 { |
168 op->SetValue (GetStringTableIndex (GetTokenString())); |
184 op->SetValue (GetStringTableIndex (GetTokenString())); |
169 return op; |
185 return op; |
170 } |
186 } |
171 } |
187 } |
172 |
188 } |
173 assert (false); |
189 |
174 throw failed; |
190 mBadTokenText = mLexer->GetToken()->text; |
175 } |
191 mLexer->SetPosition (pos); |
176 catch (ELocalException&) |
192 delete op; |
177 { |
|
178 // We use a local enum here since catch(...) would catch Error() calls. |
|
179 mBadTokenText = mLexer->GetToken()->text; |
|
180 mLexer->SetPosition (pos); |
|
181 delete op; |
|
182 return null; |
|
183 } |
|
184 |
|
185 assert (false); |
|
186 return null; |
193 return null; |
187 } |
194 } |
188 |
195 |
189 // ============================================================================= |
196 // ============================================================================= |
190 // |
197 // |