| 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 // |