ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
ast.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !defined(ALIB_DOX)
10# if !defined (HPP_ALIB_EXPRESSIONS_DETAIL_AST)
12# endif
13
14# if !defined (HPP_ALIB_EXPRESSIONS_COMPILERPLUGIN)
16# endif
17
18# if !defined (HPP_ALIB_EXPRESSIONS_DETAIL_PROGRAM)
20# endif
21
22# if !defined (HPP_ALIB_STRINGS_FORMAT)
24# endif
25
26#endif // !defined(ALIB_DOX)
27
28
29namespace alib { namespace expressions { namespace detail {
30
31
32
33// #################################################################################################
34// Anonymous helpers
35// #################################################################################################
36//! @cond NO_DOX
37namespace {
38
39const String normSpace(A_CHAR(" "));
41const String normBracketOpen [4] {A_CHAR("("), A_CHAR("( "), A_CHAR(" ("), A_CHAR(" ( ")};
42const String normBracketClose[4] {A_CHAR(")"), A_CHAR(" )"), A_CHAR(") "), A_CHAR(" ) ")};
44
45#define SPACE(flag) ( HasBits(format, Normalization::flag ) ? normSpace : EmptyString() )
46#define COND_SPACE(flag, force) if( HasBits(format, Normalization::flag ) || force ) normalized << ' '
47
48void checkForbiddenStrings( Compiler& compiler, AString& normalized, integer positionToCheck, integer spaceInsertionPos )
49{
50 for( auto& it : compiler.CfgNormalizationDisallowed )
51 if( it.Length() > spaceInsertionPos && normalized.ContainsAt( it, positionToCheck ) )
52 {
53 normalized.InsertAt( A_CHAR(" "), positionToCheck + spaceInsertionPos );
54 return;
55 }
56}
57} // anonymous namespace
58//! @endcond
59
60// #################################################################################################
61// Optimize implementations
62// #################################################################################################
63AST* ASTLiteral ::Optimize( Normalization ) { return this; }
65AST* ASTFunction ::Optimize( Normalization normalization )
66{
67 for( auto& arg : Arguments )
68 arg= arg->Optimize( normalization );
69 return this;
70}
71
73{
74 Lhs= Lhs->Optimize( normalization );
75 Rhs= Rhs->Optimize( normalization );
76 return this;
77}
78
80{
81 Q= Q->Optimize( normalization );
82 T= T->Optimize( normalization );
83 F= F->Optimize( normalization );
84 return this;
85}
86
87
88
90{
91 Argument= Argument->Optimize( normalization );
92
93 if( HasBits( normalization, Normalization::RemoveRedundantUnaryOpsOnNumberLiterals ) )
94 {
95 if( Argument->NodeType == Types::Literal && (Operator == A_CHAR("+") || Operator == A_CHAR("-")) )
96 {
97 ASTLiteral* astLiteral= dynamic_cast<ASTLiteral*>( Argument );
98
99 if( astLiteral->Value.IsType<integer>() )
100 {
101 if( Operator.CharAtStart<false>() == '-' )
102 astLiteral->Value= - astLiteral->Value.Unbox<integer>();
103 Argument= nullptr;
104 return astLiteral;
105 }
106
107 if( astLiteral->Value.IsType<double>() )
108 {
109 if( Operator.CharAtStart<false>() == '-' )
110 astLiteral->Value= - astLiteral->Value.Unbox<double>();
111 Argument= nullptr;
112 return astLiteral;
113 }
114 }
115 }
116
117 return this;
118}
119
120
121
122// #################################################################################################
123// Assemble implementations
124// #################################################################################################
125
126void ASTLiteral::Assemble( Program& program, MonoAllocator&, AString & normalized )
127{
128 integer idxInNormalized= normalized.Length();
129
131 if( func )
132 {
133 Value.CallDirect <FToLiteral>( func, normalized );
134 }
135 else if( Value.IsType<String>() )
136 {
137 normalized << '"';
138 integer startExternalization= normalized.Length();
139 normalized << Value;
140 normalized << Format::Escape( lang::Switch::On, startExternalization );
141 normalized << '"';
142 }
143 else if( Value.IsType<double>() )
144 {
145 NumberFormat* nf= &program.compiler.CfgFormatter->DefaultNumberFormat;
146 auto oldFlags= nf->Flags;
149 nf->Flags+= NumberFormatFlags::ForceScientific;
150
151 normalized << alib::Format( Value.Unbox<double>(), &program.compiler.CfgFormatter->DefaultNumberFormat);
152 nf->Flags= oldFlags;
153 }
154 else if( Value.IsType<integer>() )
155 {
156 NFHint format= Format;
158 format= NFHint::Hexadecimal;
159 else if( HasBits(program.compiler.CfgNormalization, Normalization::ForceOctal ) )
160 format= NFHint::Octal;
161 else if( HasBits(program.compiler.CfgNormalization, Normalization::ForceBinary ) )
162 format= NFHint::Binary;
163
164 NumberFormat* nf = &program.compiler.CfgFormatter->DefaultNumberFormat;
165 integer value= Value.Unbox<integer>();
166 if( format == NFHint::Hexadecimal ) normalized << nf->HexLiteralPrefix << alib::Format::Hex(static_cast<uint64_t>(value), 0, nf );
167 else if( format == NFHint::Octal ) normalized << nf->OctLiteralPrefix << alib::Format::Oct(static_cast<uint64_t>(value), 0, nf );
168 else if( format == NFHint::Binary ) normalized << nf->BinLiteralPrefix << alib::Format::Bin(static_cast<uint64_t>(value), 0, nf );
169 else normalized << alib::Format(value, 0, nf);
170 }
171 else
172 normalized << Value;
173
174 program.AssembleConstant( Value, Position, idxInNormalized );
175}
176
177void ASTIdentifier::Assemble( Program& program, MonoAllocator&, AString & normalized )
178{
179 auto format= program.compiler.CfgNormalization;
180
181 String64 identifier;
183 identifier << Name;
184
185 // -1 indicates that not even parentheses were given
186 program.AssembleFunction( identifier, -1, Position, normalized.Length() );
187
188 normalized << (HasBits( format, Normalization::ReplaceFunctionNames ) ? identifier : Name);
189}
190
191
192void ASTFunction::Assemble( Program& program, MonoAllocator& allocator, AString& normalized )
193{
194 auto format= program.compiler.CfgNormalization;
195 String64 functionName;
197
198 bool completeIdentifierNames= HasBits( format, Normalization::ReplaceFunctionNames );
199 functionName << Name;
200
201 integer namePos= normalized.Length();
202 normalized << functionName;
203 integer nameLen= normalized.Length() - namePos;
204 normalized << SPACE(FunctionSpaceBeforeOpeningBracket);
205
206 auto qtyArgs= Arguments.Size();
207
208 // the function used for nested expressions?
209 bool replacedNestedExpressionIdentifierByLiteral= false;
210 bool thirdArgumentIsThrowIdentifier= false;
212 {
213 if( qtyArgs < 1 || qtyArgs > 3 )
214 {
217 }
218
219 // if an identifier is given for the first argument, we optionally convert the identifier
220 // to a string value.
222 && (*Arguments.begin())->NodeType == Types::Identifier )
223 {
224 ASTIdentifier* astIdentifier= dynamic_cast<ASTIdentifier*>( *Arguments.begin() );
225 ASTLiteral* astLiteral = allocator.Emplace<ASTLiteral>( astIdentifier->Name, astIdentifier->Position );
226 *Arguments.begin()= astLiteral;
227 replacedNestedExpressionIdentifierByLiteral= true;
228 }
229
230 // if third parameter given it must be an identifier and equal to "throw"
231 if( qtyArgs == 3 )
232 {
233 auto argIt= Arguments.begin();
234 ++argIt;
235 ++argIt;
236 if( (*argIt)->NodeType != Types::Identifier
237 || !dynamic_cast<ASTIdentifier*>( (*argIt) )->Name.Equals<false, lang::Case::Ignore>(
239 {
242 }
243 thirdArgumentIsThrowIdentifier= true;
244 }
245 }
246
247
248 if( qtyArgs > 0 )
249 {
250 normalized << '(' << SPACE(FunctionInnerBracketSpace);
251 int no= -1;
252 for( auto* argAst : Arguments )
253 {
254 ++no;
255 if( no==0 )
256 {
257 // optionally remove quotes if we previously converted an identifier to string type
258 if( replacedNestedExpressionIdentifierByLiteral
260 {
261 {
262 ALIB_STRING_RESETTER(normalized);
263 argAst->Assemble( program, allocator, normalized );
264 }
265 normalized << dynamic_cast<ASTLiteral*>(argAst)->Value.Unbox<String>();
266 continue;
267 }
268 }
269 else
270 normalized << SPACE(FunctionSpaceBeforeComma) << ',' << SPACE(FunctionSpaceAfterComma);
271
272 if( no != 2 || !thirdArgumentIsThrowIdentifier )
273 argAst->Assemble( program, allocator, normalized );
274 else
275 normalized << program.compiler.CfgNestedExpressionThrowIdentifier;
276 }
277 normalized << SPACE(FunctionInnerBracketSpace) << ')';
278 }
279 else
280 normalized << (HasBits(format, Normalization::FunctionInnerBracketSpaceIfNoArguments )
281 ? A_CHAR("()") : A_CHAR("( )") );
282
283
284 program.AssembleFunction( functionName, static_cast<int>(qtyArgs), Position, namePos );
285 if( completeIdentifierNames )
286 normalized.ReplaceSubstring<false>( functionName, namePos, nameLen );
287}
288
289
290void ASTUnaryOp::Assemble( Program& program, MonoAllocator& allocator, AString & normalized )
291{
292 auto format= program.compiler.CfgNormalization;
293 String op= Operator;
294
295 bool isVerbalOp= isalpha(op.CharAtStart());
296
297
298 // if a) this is the unary operator used for nested expressions
299 // and b) an identifier terminal follows, we optionally convert the identifier to a string
300 // value.
301 bool replacedNestedExpressionIdentifierByLiteral= false;
303 {
304 String nonVerbalOp;
305 if( !isVerbalOp )
306 nonVerbalOp= op;
307 else
308 {
309 auto it= program.compiler.AlphabeticUnaryOperatorAliases.Find(op);
310 if( it != program.compiler.AlphabeticUnaryOperatorAliases.end() )
311 nonVerbalOp= it.Mapped();
312 else
313 nonVerbalOp= EmptyString();
314 }
315
316 if( program.compiler.CfgNestedExpressionOperator == nonVerbalOp
317 && Argument->NodeType == Types::Identifier )
318 {
319 ASTIdentifier* astIdentifier= dynamic_cast<ASTIdentifier*>( Argument );
320 ASTLiteral* astLiteral = allocator.Emplace<ASTLiteral>( astIdentifier->Name, astIdentifier->Position );
321 Argument= astLiteral;
322 replacedNestedExpressionIdentifierByLiteral= true;
323 }
324 }
325
326 //--------- normal unary operators -------
328
329 auto opIdx= normalized.Length();
330 normalized << op;
331 auto opLen= normalized.Length() - opIdx;
332
333 // args in brackets if its a binary or ternary expression (-> if it has lower precedence)
334 bool brackets= HasBits(format, Normalization::RedundantUnaryOpBrackets)
335 || ( Argument->NodeType == Types::UnaryOp
337 || Argument->NodeType == Types::BinaryOp
338 || Argument->NodeType == Types::TernaryOp;
339
340 bool opSpaceIfNotVerbal= !brackets
341 && ( Argument->NodeType == Types::UnaryOp ? HasBits(format, Normalization::UnaryOpSpaceIfUnaryFollows)
342 : HasBits(format, Normalization::UnaryOpSpace ) );
343 normalized << ( brackets
344 ? normBracketOpen[ HasBits(format, Normalization::UnaryOpInnerBracketSpace )
345 + HasBits(format, Normalization::UnaryOpSpaceIfBracketFollows) * 2]
346 : String( (opSpaceIfNotVerbal || isVerbalOp ) ? A_CHAR(" ") : A_CHAR("") )
347 );
348
349 // recursion
350 integer lenBeforeArgument= normalized.Length();
351 Argument->Assemble( program, allocator, normalized );
352
353 // optionally remove quotes if we previously converted an identifier to string type
354 if( replacedNestedExpressionIdentifierByLiteral
356 {
357 normalized.ShortenTo( lenBeforeArgument );
358 normalized << dynamic_cast<ASTLiteral*>( Argument )->Value.Unbox<String>();
359 }
360
361 if( brackets )
362 normalized << normBracketClose[HasBits(format, Normalization::UnaryOpInnerBracketSpace )];
364
365
366 // check plugins
367 program.AssembleUnaryOp( op, Position, opIdx );
368
369 // did the compiler plug-in replace the operator (was given an alias operator)?
370 if( op != Operator || isVerbalOp )
371 {
372 if( isVerbalOp )
373 {
374 // replace in any case: class program would have changed the op only if the corresponding
375 // flags had been set:
376 normalized.ReplaceSubstring<false>( op, opIdx, opLen );
377 opLen= op.Length();
378
379 // we have to check only two of four format flags here, the rest was is (was) done in program
383 for( integer i= opIdx ; i < opIdx + opLen ; ++i )
387
388 // remove space that was inserted for non-verbal op, if op is now symbolic
389 if( !opSpaceIfNotVerbal && !isalpha(op.CharAtStart() ) )
390 normalized.Delete( opIdx + opLen, 1 );
391
392 }
393
394 else if( HasBits(format, Normalization::ReplaceAliasOperators ) )
395 {
396 normalized.ReplaceSubstring<false>( op, opIdx, opLen );
397 opLen= op.Length();
398 }
399 }
400
401
402 // check if a forbidden string occurred due to writing operator with no spaces/brackets and
403 // the subsequent writing of probably nested unary operators, negative literals, etc.
404 checkForbiddenStrings( program.compiler, normalized, opIdx, opLen );
405}
406
407
408void ASTBinaryOp::Assemble( Program& program, MonoAllocator& allocator, AString & normalized )
409{
410 auto format= program.compiler.CfgNormalization;
411 String op= Operator;
412
413 //----------- Special treatment for subscript operator (needs different normalization) ---------
414 if( op == A_CHAR("[]") )
415 {
416 // LHS recursion
417 Lhs->Assemble( program, allocator, normalized );
418
419 COND_SPACE(SubscriptSpaceBeforeBrackets, false);
420 normalized << '[';
421
422
423 // RHS recursion
424 COND_SPACE(SubscriptInnerBracketSpace, false );
425 auto opIdx= normalized.Length();
426 Rhs->Assemble( program, allocator, normalized );
427 COND_SPACE(SubscriptInnerBracketSpace, false );
428 normalized << ']';
429
430 // check plugins
431 program.AssembleBinaryOp( op, Position, opIdx );
432
433 return;
434 }
435
436 // Add brackets for LHS, if one of the two is true for it:
437 // - it is a ternary op (always has lower precedence)
438 // - it is a binary op with lower precedence
439 // In the case that operators precedences are equal, we do not need brackets, as the
440 // left-hand side is parsed first.
441 int precedence= program.compiler.GetBinaryOperatorPrecedence( Operator );
442 int lhsBinaryPrecedence= Lhs->NodeType == Types::BinaryOp
443 ? program.compiler.GetBinaryOperatorPrecedence(dynamic_cast<ASTBinaryOp*>( Lhs )->Operator)
444 : 0;
445 int rhsBinaryPrecedence= Rhs->NodeType == Types::BinaryOp
446 ? program.compiler.GetBinaryOperatorPrecedence(dynamic_cast<ASTBinaryOp*>( Rhs )->Operator)
447 : 0;
448
449
450 bool lhsBrackets= Lhs->NodeType == Types::TernaryOp
451 || ( lhsBinaryPrecedence
452 && ( HasBits(format, Normalization::RedundantBinaryOpBrackets )
453 || precedence > lhsBinaryPrecedence
455 && rhsBinaryPrecedence )
456 )
457 );
458
459 int bracketStringIdx= (HasBits(format, Normalization::InnerBracketSpace ) +
460 HasBits(format, Normalization::OuterBracketSpace ) *2 );
461
462 // LHS recursion
463 if( lhsBrackets ) normalized << normBracketOpen[bracketStringIdx];
464 Lhs->Assemble( program, allocator, normalized );
465 if( lhsBrackets ) normalized << normBracketClose[bracketStringIdx];
466
467 bool isVerbalOp= isalpha(op.CharAtStart());
468
469 COND_SPACE( BinaryOpSpaces, isVerbalOp );
470 auto opIdx= normalized.Length();
471 normalized << op;
472 auto opLen= normalized.Length() - opIdx;
473 COND_SPACE( BinaryOpSpaces, isVerbalOp );
474
475 // Add brackets for RHS, if one of the two is true for it:
476 // - it is a ternary op (always has lower precedence)
477 // - it is a binary op with lower or equal precedence
478 // In fact, there are more situations where brackets can be removed, for example in:
479 // 1 + (2 + 3)
480 // but this is kept. The reason, why we don't remove, if operators are equal is:
481 // 1 - (2 - 3)
482 // Here, we must not remove the brackets. This generally means, we do not have enough
483 // information about the algebraic rules of our operators to remove the brackets in all
484 // cases!
485
486 bool rhsBrackets= Rhs->NodeType == Types::TernaryOp
487 || ( rhsBinaryPrecedence
488 && ( HasBits(format, Normalization::RedundantBinaryOpBrackets )
489 || ( precedence >= rhsBinaryPrecedence )
491 && precedence < rhsBinaryPrecedence )
493 && lhsBinaryPrecedence )
494 )
495 );
496
497
498 // RHS recursion
499 if( rhsBrackets ) normalized << normBracketOpen[bracketStringIdx];
500 Rhs->Assemble( program, allocator, normalized );
501 if( rhsBrackets ) normalized << normBracketClose[bracketStringIdx];
502
503 // check plugins
504 program.AssembleBinaryOp( op, Position, opIdx );
505
506 // did the compiler plug-in replace the operator (was given an alias operator)?
507 if( op != Operator || isVerbalOp )
508 {
509 if( isVerbalOp )
510 {
511 // replace in any case: class program would have changed the op only if the corresponding
512 // flags had been set:
513 normalized.ReplaceSubstring<false>( op, opIdx, opLen );
514 opLen= op.Length();
515
516 // we have to check only two of four format flags here, the rest was is (was) done in program
520 for( integer i= opIdx ; i < opIdx + opLen ; ++i )
524
525 // remove operator spaces if they were inserted for non-verbal op, if op is now symbolic
526 if( !HasBits(format, Normalization::BinaryOpSpaces) && !isalpha(op.CharAtStart() ) )
527 {
528 normalized.Delete( opIdx + opLen, 1 );
529 normalized.Delete( opIdx - 1 , 1 );
530 }
531
532 }
533
534 else if( HasBits(format, Normalization::ReplaceAliasOperators ) )
535 {
536 normalized.ReplaceSubstring<false>( op, opIdx, opLen );
537 opLen= op.Length();
538 }
539 }
540
541 // check if a forbidden string occurred due to writing operator with no spaces/brackets and
542 // the subsequent writing of probably nested unary operators, negative literals, etc.
543 checkForbiddenStrings( program.compiler, normalized, opIdx, opLen );
544}
545
546
547void ASTConditional::Assemble( Program& program, MonoAllocator& allocator, AString & normalized )
548{
549 auto format= program.compiler.CfgNormalization;
550
551 int bracketStringIdx= (HasBits(format, Normalization::InnerBracketSpace ) +
552 HasBits(format, Normalization::OuterBracketSpace ) *2 );
553
554
555 // Q
556 Q->Assemble( program, allocator, normalized );
557 normalized << SPACE(ConditionalOpSpaceBeforeQM);
558 program.AssembleCondFinalize_Q( Position, normalized.Length() );
559 normalized << A_CHAR("?") << SPACE(ConditionalOpSpaceAfterQM);
560
561 // T
562 integer idxInNormalized= normalized.Length();
563
564 bool brackets= T->NodeType == Types::TernaryOp
566
567 if( brackets ) normalized << normBracketOpen[bracketStringIdx];
568 T->Assemble( program, allocator, normalized );
569 if( brackets ) normalized << normBracketClose[bracketStringIdx];
570
571 // :
572 normalized << SPACE(ConditionalOpSpaceBeforeColon);
573
574 program.AssembleCondFinalize_T( ColonPosition, normalized.Length() );
575
576 normalized << ":" << SPACE(ConditionalOpSpaceAfterColon);
577
578
579 // F
580 brackets= F->NodeType == Types::TernaryOp
582
583 if( brackets ) normalized << normBracketOpen[bracketStringIdx];
584 F->Assemble( program, allocator, normalized );
585 if( brackets ) normalized << normBracketClose[bracketStringIdx];
586
587 program.AssembleCondFinalize_F( Position, idxInNormalized );
588}
589
590}}} // namespace [alib::expressions::detail]
decltype(std::declval< typename TFDecl::Signature >()(std::declval< Box & >(), std::declval< TArgs >()...)) CallDirect(typename TFDecl::Signature function, TArgs &&... args) const
Definition box.inl:1161
TFDecl::Signature GetFunction(Reach searchScope, bool isInvocation=false) const
bool IsType() const
const TUnboxable Unbox() const
HashMap< String, String, alib::hash_string_ignore_case< character >, alib::equal_to_string_ignore_case< character > > AlphabeticUnaryOperatorAliases
Definition compiler.hpp:154
int GetBinaryOperatorPrecedence(const String &symbol)
Definition compiler.hpp:222
strings::util::Token CfgNestedExpressionFunction
Definition compiler.hpp:304
Normalization CfgNormalization
Definition compiler.hpp:323
ALIB_API void AssembleCondFinalize_T(integer idxInOriginal, integer idxInNormalized)
Definition program.cpp:898
ALIB_API void AssembleCondFinalize_F(integer idxInOriginal, integer idxInNormalized)
Definition program.cpp:920
ALIB_API void AssembleUnaryOp(String &op, integer idxInOriginal, integer idxInNormalized)
Definition program.cpp:476
ALIB_API void AssembleFunction(AString &functionName, integer qtyArgsOrNoParentheses, integer idxInOriginal, integer idxInNormalized)
Definition program.cpp:284
ALIB_API void AssembleConstant(Box &value, integer idxInOriginal, integer idxInNormalized)
Definition program.cpp:270
ALIB_API void AssembleCondFinalize_Q(integer idxInOriginal, integer idxInNormalized)
Definition program.cpp:867
ALIB_API void AssembleBinaryOp(String &op, integer idxInOriginal, integer idxInNormalized)
Definition program.cpp:660
ALIB_FORCE_INLINE T * Emplace(TArgs &&... args)
TAString & ShortenTo(integer newLength)
Definition astring.hpp:908
TAString & Delete(integer regionStart, integer regionLength=MAX_LEN)
Definition astring.hpp:1490
TAString & ReplaceSubstring(const TString< TChar > &src, integer regionStart, integer regionLength)
Definition astring.hpp:1708
void DbgDisableBufferReplacementWarning()
Definition astring.hpp:353
constexpr integer Length() const
Definition string.hpp:357
TChar CharAtStart() const
Definition string.hpp:459
bool Equals(const TString< TChar > &rhs) const
Definition string.hpp:573
ALIB_API bool Match(const String &needle)
Definition token.cpp:284
#define ALIB_CALLER_NULLED
Definition alib.hpp:846
#define A_CHAR(STR)
#define ALIB_STRING_RESETTER(astring)
Definition astring.hpp:2126
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:644
@ On
Switch it on, switched on, etc.
@ Local
Denotes local reach.
Definition alib.cpp:57
lang::Exception Exception
Type alias in namespace alib.
constexpr CString EmptyString()
Definition cstring.hpp:502
strings::TFormat< character > Format
Type alias in namespace alib.
strings::TAString< character > AString
Type alias in namespace alib.
strings::TString< character > String
Type alias in namespace alib.
expressions::Compiler Compiler
Type alias in namespace alib.
Definition compiler.hpp:596
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:286
static TChar ToLower(TChar c)
static TChar ToUpper(TChar c)
String Operator
The operator symbol.
Definition ast.hpp:291
virtual AST * Optimize(Normalization normalization) override
Definition ast.cpp:72
virtual void Assemble(Program &program, MonoAllocator &allocator, AString &normalized) override
Definition ast.cpp:408
AST * Rhs
The right-hand-side expression node.
Definition ast.hpp:293
AST * Lhs
The left-hand-side expression node.
Definition ast.hpp:292
integer ColonPosition
The index of the colon in the expression string.
Definition ast.hpp:337
virtual AST * Optimize(Normalization normalization) override
Definition ast.cpp:79
virtual void Assemble(Program &program, MonoAllocator &allocator, AString &normalized) override
Definition ast.cpp:547
String Name
The function name as parsed.
Definition ast.hpp:204
virtual void Assemble(Program &program, MonoAllocator &allocator, AString &normalized) override
Definition ast.cpp:192
List< AST * > Arguments
The argument nodes.
Definition ast.hpp:205
String Name
The name of the identifier as parsed from the expression string.
Definition ast.hpp:169
virtual AST * Optimize(Normalization normalization) override
Definition ast.cpp:64
virtual void Assemble(Program &program, MonoAllocator &allocator, AString &normalized) override
Definition ast.cpp:177
Box Value
The value of the literal.
Definition ast.hpp:105
@ Scientific
Float was given in scientific format.
@ Hexadecimal
Integral value was given in hexadecimal format.
@ Binary
Integral value was given in binary format.
@ Octal
Integral value was given in octal format.
NFHint Format
The value of the literal.
Definition ast.hpp:106
virtual void Assemble(Program &program, MonoAllocator &allocator, AString &normalized) override
Definition ast.cpp:126
String Operator
The operator symbol.
Definition ast.hpp:249
AST * Argument
The argument node.
Definition ast.hpp:250
virtual AST * Optimize(Normalization normalization) override
Definition ast.cpp:89
virtual void Assemble(Program &program, MonoAllocator &allocator, AString &normalized) override
Definition ast.cpp:290
virtual AST * Optimize(Normalization normalization)=0
virtual void Assemble(Program &program, MonoAllocator &allocator, AString &normalized)=0
TCString< TChar > BinLiteralPrefix
TCString< TChar > OctLiteralPrefix
TCString< TChar > HexLiteralPrefix