source: src/Parser/ExpressionNode.cpp@ 20c2ade

Last change on this file since 20c2ade was 20c2ade, checked in by Andrew Beach <ajbeach@…>, 15 months ago

Parse string literals to get their length, taking into account escape sequences. Getting this from the lexer would avoid redundent work, but that is not set up. This corrects some typeof evaluations which lead to incorrect sizeof expressions.

  • Property mode set to 100644
File size: 30.9 KB
RevLine 
[b87a5ed]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
[c92bdcc]7// ExpressionNode.cpp --
[0caaa6a]8//
[f43df73]9// Author : Peter A. Buhr
[b87a5ed]10// Created On : Sat May 16 13:17:07 2015
[45ee172]11// Last Modified By : Andrew Beach
12// Last Modified On : Fri Aug 23 10:22:00 2024
13// Update Count : 1088
[0caaa6a]14//
[b87a5ed]15
[c92bdcc]16#include "ExpressionNode.hpp"
[c468150]17
[ea6332d]18#include <cassert> // for assert
[d180746]19#include <stdio.h> // for sscanf, size_t
20#include <climits> // for LLONG_MAX, LONG_MAX, INT_MAX, UINT...
21#include <list> // for list
22#include <sstream> // for basic_istream::operator>>, basic_i...
23#include <string> // for string, operator+, operator==
[51b73452]24
[7a780ad]25#include "AST/BasicKind.hpp" // for BasicKind
[bb7422a]26#include "AST/Expr.hpp" // for NameExpr
[7a780ad]27#include "AST/Type.hpp" // for Type, LengthFlag, DimentionFlag
[c92bdcc]28#include "Common/SemanticError.hpp"// for SemanticError
29#include "Common/Utility.hpp" // for maybeMoveBuild, maybeBuild, CodeLo...
30#include "DeclarationNode.hpp" // for DeclarationNode
31#include "InitializerNode.hpp" // for InitializerNode
32#include "TypeData.hpp" // for addType, build_basic_type, build_c...
33#include "ParserUtility.hpp" // for notZeroExpr
[d180746]34
[51b73452]35using namespace std;
36
[cd623a4]37//##############################################################################
38
[7bf7fb9]39// Difficult to separate extra parts of constants during lexing because actions are not allow in the middle of patterns:
40//
41// prefix action constant action suffix
42//
43// Alternatively, breaking a pattern using BEGIN does not work if the following pattern can be empty:
44//
45// constant BEGIN CONT ...
46// <CONT>(...)? BEGIN 0 ... // possible empty suffix
47//
48// because the CONT rule is NOT triggered if the pattern is empty. Hence, constants are reparsed here to determine their
49// type.
50
[ba01b14]51// static inline bool checkH( char c ) { return c == 'h' || c == 'H'; }
52// static inline bool checkZ( char c ) { return c == 'z' || c == 'Z'; }
53// static inline bool checkU( char c ) { return c == 'u' || c == 'U'; }
[7bf7fb9]54static inline bool checkF( char c ) { return c == 'f' || c == 'F'; }
55static inline bool checkD( char c ) { return c == 'd' || c == 'D'; }
[ba01b14]56static inline bool checkF80( char c ) { return c == 'w' || c == 'W'; }
57static inline bool checkF128( char c ) { return c == 'q' || c == 'Q'; }
[f56c32e]58static inline bool checkL( char c ) { return c == 'l' || c == 'L'; }
[7bf7fb9]59static inline bool checkI( char c ) { return c == 'i' || c == 'I'; }
[0a2168f]60static inline bool checkB( char c ) { return c == 'b' || c == 'B'; }
[7bf7fb9]61static inline bool checkX( char c ) { return c == 'x' || c == 'X'; }
[3d8d7a7]62// static inline bool checkN( char c ) { return c == 'n' || c == 'N'; }
[f56c32e]63
64void lnthSuffix( string & str, int & type, int & ltype ) {
[c5b55c4]65 // 'u' can appear before or after length suffix
[f56c32e]66 string::size_type posn = str.find_last_of( "lL" );
[0a616e0]67
68 if ( posn == string::npos ) return; // no suffix
[c5b55c4]69 size_t end = str.length() - 1;
70 if ( posn == end ) { type = 3; return; } // no length after 'l' => long
[702e826]71
[0a616e0]72 string::size_type next = posn + 1; // advance to length
73 if ( str[next] == '3' ) { // 32
74 type = ltype = 2;
75 } else if ( str[next] == '6' ) { // 64
76 type = ltype = 3;
77 } else if ( str[next] == '8' ) { // 8
78 type = ltype = 1;
79 } else if ( str[next] == '1' ) {
80 if ( str[next + 1] == '6' ) { // 16
81 type = ltype = 0;
82 } else { // 128
83 type = 5; ltype = 6;
[f56c32e]84 } // if
85 } // if
[c5b55c4]86
87 char fix = '\0';
88 if ( str[end] == 'u' || str[end] == 'U' ) fix = str[end]; // ends with 'uU' ?
89 str.erase( posn ); // remove length suffix and possibly uU
90 if ( type == 5 ) { // L128 does not need uU
91 end = str.length() - 1;
92 if ( str[end] == 'u' || str[end] == 'U' ) str.erase( end ); // ends with 'uU' ? remove
93 } else if ( fix != '\0' ) str += fix; // put 'uU' back if removed
[f56c32e]94} // lnthSuffix
[7bf7fb9]95
[0a616e0]96void valueToType( unsigned long long int & v, bool dec, int & type, bool & Unsigned ) {
97 // use value to determine type
98 if ( v <= INT_MAX ) { // signed int
99 type = 2;
100 } else if ( v <= UINT_MAX && ! dec ) { // unsigned int
101 type = 2;
102 Unsigned = true; // unsigned
103 } else if ( v <= LONG_MAX ) { // signed long int
104 type = 3;
105 } else if ( v <= ULONG_MAX && ( ! dec || LONG_MAX == LLONG_MAX ) ) { // signed long int
106 type = 3;
107 Unsigned = true; // unsigned long int
108 } else if ( v <= LLONG_MAX ) { // signed long long int
109 type = 4;
110 } else { // unsigned long long int
111 type = 4;
112 Unsigned = true; // unsigned long long int
113 } // if
114} // valueToType
115
[f6582252]116static void scanbin( string & str, unsigned long long int & v ) {
117 v = 0;
118 size_t last = str.length() - 1; // last subscript of constant
119 for ( unsigned int i = 2;; ) { // ignore prefix
120 if ( str[i] == '1' ) v |= 1;
121 i += 1;
[0d0931d]122 if ( i == last - 1 || (str[i] != '0' && str[i] != '1') ) break;
[f6582252]123 v <<= 1;
124 } // for
125} // scanbin
126
[bb7422a]127ast::Expr * build_constantInteger(
128 const CodeLocation & location, string & str ) {
[7a780ad]129 static const ast::BasicKind kind[2][6] = {
[ba01b14]130 // short (h) must be before char (hh) because shorter type has the longer suffix
[7a780ad]131 { ast::BasicKind::ShortSignedInt, ast::BasicKind::SignedChar, ast::BasicKind::SignedInt, ast::BasicKind::LongSignedInt, ast::BasicKind::LongLongSignedInt, /* BasicKind::SignedInt128 */ ast::BasicKind::LongLongSignedInt, },
132 { ast::BasicKind::ShortUnsignedInt, ast::BasicKind::UnsignedChar, ast::BasicKind::UnsignedInt, ast::BasicKind::LongUnsignedInt, ast::BasicKind::LongLongUnsignedInt, /* BasicKind::UnsignedInt128 */ ast::BasicKind::LongLongUnsignedInt, },
[7bf7fb9]133 };
[76c62b2]134
[0a616e0]135 static const char * lnthsInt[2][6] = {
136 { "int16_t", "int8_t", "int32_t", "int64_t", "size_t", "uintptr_t", },
137 { "uint16_t", "uint8_t", "uint32_t", "uint64_t", "size_t", "uintptr_t", },
[ba01b14]138 }; // lnthsInt
139
[f6582252]140 string str2( "0x0" );
141 unsigned long long int v, v2 = 0; // converted integral value
[bb7422a]142 ast::Expr * ret, * ret2;
[0a616e0]143
144 int type = -1; // 0 => short, 1 => char, 2 => int, 3 => long int, 4 => long long int, 5 => int128
145 int ltype = -1; // 0 => 16 bits, 1 => 8 bits, 2 => 32 bits, 3 => 64 bits, 4 => size_t, 5 => intptr, 6 => pointer
146 bool dec = true, Unsigned = false; // decimal, unsigned constant
[7bf7fb9]147
[6165ce7]148 // special constants
149 if ( str == "0" ) {
[bb7422a]150 ret = new ast::ConstantExpr( location, new ast::ZeroType(), str, 0 );
[6165ce7]151 goto CLEANUP;
152 } // if
153 if ( str == "1" ) {
[bb7422a]154 ret = new ast::ConstantExpr( location, new ast::OneType(), str, 1 );
[6165ce7]155 goto CLEANUP;
156 } // if
[ea6332d]157
[f6582252]158 // 'u' can appear before or after length suffix
159 if ( str.find_last_of( "uU" ) != string::npos ) Unsigned = true;
160
161 if ( isdigit( str[str.length() - 1] ) ) { // no suffix ?
[f56c32e]162 lnthSuffix( str, type, ltype ); // could have length suffix
163 } else {
164 // At least one digit in integer constant, so safe to backup while looking for suffix.
[52a2248]165 // This declaration and the comma expressions in the conditions mimic
166 // the declare and check pattern allowed in later compiler versions.
167 // (Only some early compilers/C++ standards do not support it.)
[15596d7]168 string::size_type posn;
169 // pointer value
[52a2248]170 if ( posn = str.find_last_of( "pP" ), posn != string::npos ) {
[15596d7]171 ltype = 5; str.erase( posn, 1 );
[0d0931d]172 // size_t
[52a2248]173 } else if ( posn = str.find_last_of( "zZ" ), posn != string::npos ) {
[15596d7]174 Unsigned = true; type = 2; ltype = 4; str.erase( posn, 1 );
[0d0931d]175 // signed char
[52a2248]176 } else if ( posn = str.rfind( "hh" ), posn != string::npos ) {
[15596d7]177 type = 1; str.erase( posn, 2 );
[0d0931d]178 // signed char
[52a2248]179 } else if ( posn = str.rfind( "HH" ), posn != string::npos ) {
[15596d7]180 type = 1; str.erase( posn, 2 );
[0d0931d]181 // short
[52a2248]182 } else if ( posn = str.find_last_of( "hH" ), posn != string::npos ) {
[15596d7]183 type = 0; str.erase( posn, 1 );
[0d0931d]184 // int (natural number)
[52a2248]185 } else if ( posn = str.find_last_of( "nN" ), posn != string::npos ) {
[15596d7]186 type = 2; str.erase( posn, 1 );
187 } else if ( str.rfind( "ll" ) != string::npos || str.rfind( "LL" ) != string::npos ) {
188 type = 4;
189 } else {
190 lnthSuffix( str, type, ltype );
191 } // if
[7bf7fb9]192 } // if
193
[f6582252]194 // Cannot be just "0"/"1"; sscanf stops at the suffix, if any; value goes over the wall => always generate
[dbe8e31c]195
[cf5af9c]196#if ! defined(__SIZEOF_INT128__)
[ca9d65e]197 if ( type == 5 ) SemanticError( yylloc, "int128 constant is not supported on this target \"%s\"", str.c_str() );
[cf5af9c]198#endif // ! __SIZEOF_INT128__
[702e826]199
[f6582252]200 if ( str[0] == '0' ) { // radix character ?
201 dec = false;
202 if ( checkX( str[1] ) ) { // hex constant ?
203 if ( type < 5 ) { // not L128 ?
204 sscanf( (char *)str.c_str(), "%llx", &v );
[c5b55c4]205#if defined(__SIZEOF_INT128__)
[f6582252]206 } else { // hex int128 constant
207 unsigned int len = str.length();
[ca9d65e]208 if ( len > (2 + 16 + 16) ) SemanticError( yylloc, "128-bit hexadecimal constant to large \"%s\"", str.c_str() );
[702e826]209 // hex digits < 2^64
210 if ( len > (2 + 16) ) {
211 str2 = "0x" + str.substr( len - 16 );
212 sscanf( (char *)str2.c_str(), "%llx", &v2 );
213 str = str.substr( 0, len - 16 );
[15596d7]214 } // if
[f6582252]215 sscanf( (char *)str.c_str(), "%llx", &v );
[c5b55c4]216#endif // __SIZEOF_INT128__
[f6582252]217 } // if
218 //printf( "%llx %llu\n", v, v );
219 } else if ( checkB( str[1] ) ) { // binary constant ?
[c5b55c4]220#if defined(__SIZEOF_INT128__)
[013b028]221 unsigned int len = str.length();
[f6582252]222 if ( type == 5 && len > 2 + 64 ) {
[ca9d65e]223 if ( len > 2 + 64 + 64 ) SemanticError( yylloc, "128-bit binary constant to large \"%s\".", str.c_str() );
[f6582252]224 str2 = "0b" + str.substr( len - 64 );
225 str = str.substr( 0, len - 64 );
226 scanbin( str2, v2 );
227 } // if
[c5b55c4]228#endif // __SIZEOF_INT128__
[f6582252]229 scanbin( str, v );
230 //printf( "%#llx %llu\n", v, v );
231 } else { // octal constant
232 if ( type < 5 ) { // not L128 ?
233 sscanf( (char *)str.c_str(), "%llo", &v );
[cf5af9c]234#if defined(__SIZEOF_INT128__)
[f6582252]235 } else { // octal int128 constant
236 unsigned int len = str.length();
[ca9d65e]237 if ( len > 1 + 43 || (len == 1 + 43 && str[0] > '3') ) SemanticError( yylloc, "128-bit octal constant to large \"%s\"", str.c_str() );
[c5b55c4]238 char buf[32];
[f6582252]239 if ( len <= 1 + 21 ) { // value < 21 octal digitis
[c5b55c4]240 sscanf( (char *)str.c_str(), "%llo", &v );
[f6582252]241 } else {
242 sscanf( &str[len - 21], "%llo", &v );
[791028a]243 __int128 val = v; // accumulate bits
[f6582252]244 str[len - 21] ='\0'; // shorten string
245 sscanf( &str[len == 43 ? 1 : 0], "%llo", &v );
246 val |= (__int128)v << 63; // store bits
247 if ( len == 1 + 43 ) { // most significant 2 bits ?
248 str[2] = '\0'; // shorten string
249 sscanf( &str[1], "%llo", &v ); // process most significant 2 bits
250 val |= (__int128)v << 126; // store bits
251 } // if
252 v = val >> 64; v2 = (uint64_t)val; // replace octal constant with 2 hex constants
253 sprintf( buf, "%#llx", v2 );
254 str2 = buf;
255 } // if
[c5b55c4]256 sprintf( buf, "%#llx", v );
257 str = buf;
[cf5af9c]258#endif // __SIZEOF_INT128__
[f6582252]259 } // if
260 //printf( "%#llo %llu\n", v, v );
261 } // if
262 } else { // decimal constant ?
263 if ( type < 5 ) { // not L128 ?
264 sscanf( (char *)str.c_str(), "%llu", &v );
[cf5af9c]265#if defined(__SIZEOF_INT128__)
[f6582252]266 } else { // decimal int128 constant
267 #define P10_UINT64 10'000'000'000'000'000'000ULL // 19 zeroes
268 unsigned int len = str.length();
269 if ( str.length() == 39 && str > (Unsigned ? "340282366920938463463374607431768211455" : "170141183460469231731687303715884105727") )
[ca9d65e]270 SemanticError( yylloc, "128-bit decimal constant to large \"%s\".", str.c_str() );
[c5b55c4]271 char buf[32];
[f6582252]272 if ( len <= 19 ) { // value < 19 decimal digitis
[c5b55c4]273 sscanf( (char *)str.c_str(), "%llu", &v );
[f6582252]274 } else {
275 sscanf( &str[len - 19], "%llu", &v );
[791028a]276 __int128 val = v; // accumulate bits
[f6582252]277 str[len - 19] ='\0'; // shorten string
278 sscanf( &str[len == 39 ? 1 : 0], "%llu", &v );
279 val += (__int128)v * (__int128)P10_UINT64; // store bits
280 if ( len == 39 ) { // most significant 2 bits ?
281 str[1] = '\0'; // shorten string
282 sscanf( &str[0], "%llu", &v ); // process most significant 2 bits
283 val += (__int128)v * (__int128)P10_UINT64 * (__int128)P10_UINT64; // store bits
284 } // if
285 v = val >> 64; v2 = (uint64_t)val; // replace decimal constant with 2 hex constants
286 sprintf( buf, "%#llx", v2 );
287 str2 = buf;
288 } // if
[c5b55c4]289 sprintf( buf, "%#llx", v );
290 str = buf;
[cf5af9c]291#endif // __SIZEOF_INT128__
[f6582252]292 } // if
293 //printf( "%llu\n", v );
294 } // if
295
296 if ( type == -1 ) { // no suffix => determine type from value size
297 valueToType( v, dec, type, Unsigned );
298 } // if
299 /* printf( "%s %llo %s %llo\n", str.c_str(), v, str2.c_str(), v2 ); */
300
[0a616e0]301 //if ( !( 0 <= type && type <= 6 ) ) { printf( "%s %lu %d %s\n", fred.c_str(), fred.length(), type, str.c_str() ); }
302 assert( 0 <= type && type <= 6 );
[f56c32e]303
[a6c5d7c]304 // Constant type is correct for overload resolving.
[bb7422a]305 ret = new ast::ConstantExpr( location,
306 new ast::BasicType( kind[Unsigned][type] ), str, v );
[ba01b14]307 if ( Unsigned && type < 2 ) { // hh or h, less than int ?
[201aeb9]308 // int i = -1uh => 65535 not -1, so cast is necessary for unsigned, which unfortunately eliminates warnings for large values.
[bb7422a]309 ret = new ast::CastExpr( location,
310 ret,
311 new ast::BasicType( kind[Unsigned][type] ),
312 ast::ExplicitCast );
[ba01b14]313 } else if ( ltype != -1 ) { // explicit length ?
[0a616e0]314 if ( ltype == 6 ) { // int128, (int128)constant
[bb7422a]315 ret2 = new ast::ConstantExpr( location,
[7a780ad]316 new ast::BasicType( ast::BasicKind::LongLongSignedInt ),
[bb7422a]317 str2,
318 v2 );
319 ret = build_compoundLiteral( location,
[6cef439]320 DeclarationNode::newFromTypeData(
321 addType(
[e048ece]322 build_basic_type( TypeData::Int128 ),
323 build_signedness( TypeData::Unsigned ) ) ),
[bb7422a]324 new InitializerNode(
[6cef439]325 (new InitializerNode( new ExpressionNode( v2 == 0 ? ret2 : ret ) ))->set_last( new InitializerNode( new ExpressionNode( v2 == 0 ? ret : ret2 ) ) ), true )
[bb7422a]326 );
[0a616e0]327 } else { // explicit length, (length_type)constant
[bb7422a]328 ret = new ast::CastExpr( location,
329 ret,
330 new ast::TypeInstType( lnthsInt[Unsigned][ltype], ast::TypeDecl::Dtype ),
331 ast::ExplicitCast );
[3d8d7a7]332 if ( ltype == 5 ) { // pointer, intptr( (uintptr_t)constant )
[bb7422a]333 ret = build_func( location,
334 new ExpressionNode(
335 build_varref( location, new string( "intptr" ) ) ),
336 new ExpressionNode( ret ) );
[0a616e0]337 } // if
[201aeb9]338 } // if
[7b1d5ec]339 } // if
[e8ccca3]340
[f56c32e]341 CLEANUP: ;
[ab57786]342 delete &str; // created by lex
343 return ret;
[7bf7fb9]344} // build_constantInteger
[51b73452]345
[201aeb9]346
[ba01b14]347static inline void checkFnxFloat( string & str, size_t last, bool & explnth, int & type ) {
348 string::size_type posn;
349 // floating-point constant has minimum of 2 characters, 1. or .1, so safe to look ahead
350 if ( str[1] == 'x' ) { // hex ?
351 posn = str.find_last_of( "pP" ); // back for exponent (must have)
352 posn = str.find_first_of( "fF", posn + 1 ); // forward for size (fF allowed in hex constant)
353 } else {
354 posn = str.find_last_of( "fF" ); // back for size (fF not allowed)
355 } // if
[201aeb9]356 if ( posn == string::npos ) return;
[ba01b14]357 explnth = true;
[201aeb9]358 posn += 1; // advance to size
359 if ( str[posn] == '3' ) { // 32
[ba01b14]360 if ( str[last] != 'x' ) type = 6;
361 else type = 7;
[201aeb9]362 } else if ( str[posn] == '6' ) { // 64
[ba01b14]363 if ( str[last] != 'x' ) type = 8;
364 else type = 9;
365 } else if ( str[posn] == '8' ) { // 80
366 type = 3;
367 } else if ( str[posn] == '1' ) { // 16/128
368 if ( str[posn + 1] == '6' ) { // 16
369 type = 5;
370 } else { // 128
371 if ( str[last] != 'x' ) type = 10;
372 else type = 11;
373 } // if
[201aeb9]374 } else {
375 assertf( false, "internal error, bad floating point length %s", str.c_str() );
376 } // if
[ba01b14]377} // checkFnxFloat
[201aeb9]378
379
[bb7422a]380ast::Expr * build_constantFloat(
381 const CodeLocation & location, string & str ) {
[7a780ad]382 static const ast::BasicKind kind[2][12] = {
383 { ast::BasicKind::Float, ast::BasicKind::Double, ast::BasicKind::LongDouble, ast::BasicKind::uuFloat80, ast::BasicKind::uuFloat128, ast::BasicKind::uFloat16, ast::BasicKind::uFloat32, ast::BasicKind::uFloat32x, ast::BasicKind::uFloat64, ast::BasicKind::uFloat64x, ast::BasicKind::uFloat128, ast::BasicKind::uFloat128x },
384 { ast::BasicKind::FloatComplex, ast::BasicKind::DoubleComplex, ast::BasicKind::LongDoubleComplex, ast::BasicKind::NUMBER_OF_BASIC_TYPES, ast::BasicKind::NUMBER_OF_BASIC_TYPES, ast::BasicKind::uFloat16Complex, ast::BasicKind::uFloat32Complex, ast::BasicKind::uFloat32xComplex, ast::BasicKind::uFloat64Complex, ast::BasicKind::uFloat64xComplex, ast::BasicKind::uFloat128Complex, ast::BasicKind::uFloat128xComplex },
[7bf7fb9]385 };
[59c24b6]386
[ba01b14]387 // floating-point constant has minimum of 2 characters 1. or .1
[7bf7fb9]388 size_t last = str.length() - 1;
[d56e5bc]389 double v;
[ba01b14]390 int type; // 0 => float, 1 => double, 3 => long double, ...
391 bool complx = false; // real, complex
392 bool explnth = false; // explicit literal length
[d56e5bc]393
394 sscanf( str.c_str(), "%lg", &v );
[51b73452]395
[7bf7fb9]396 if ( checkI( str[last] ) ) { // imaginary ?
397 complx = true;
398 last -= 1; // backup one character
399 } // if
[0caaa6a]400
[7bf7fb9]401 if ( checkF( str[last] ) ) { // float ?
[ba01b14]402 type = 0;
[7bf7fb9]403 } else if ( checkD( str[last] ) ) { // double ?
[ba01b14]404 type = 1;
[7bf7fb9]405 } else if ( checkL( str[last] ) ) { // long double ?
[ba01b14]406 type = 2;
407 } else if ( checkF80( str[last] ) ) { // __float80 ?
408 type = 3;
409 } else if ( checkF128( str[last] ) ) { // __float128 ?
410 type = 4;
[201aeb9]411 } else {
[ba01b14]412 type = 1; // double (default if no suffix)
413 checkFnxFloat( str, last, explnth, type );
[7bf7fb9]414 } // if
[ba01b14]415
[7bf7fb9]416 if ( ! complx && checkI( str[last - 1] ) ) { // imaginary ?
417 complx = true;
418 } // if
[51b73452]419
[ba01b14]420 assert( 0 <= type && type < 12 );
[bb7422a]421 ast::Expr * ret = new ast::ConstantExpr( location,
422 new ast::BasicType( kind[complx][type] ),
423 str,
424 v );
425 // explicit length ?
426 if ( explnth ) {
427 ret = new ast::CastExpr( location,
428 ret,
429 new ast::BasicType( kind[complx][type] ),
430 ast::ExplicitCast );
[201aeb9]431 } // if
[76c62b2]432
[ab57786]433 delete &str; // created by lex
434 return ret;
[7bf7fb9]435} // build_constantFloat
[51b73452]436
[76c62b2]437static void sepString( string & str, string & units, char delimit ) {
438 string::size_type posn = str.find_last_of( delimit ) + 1;
439 if ( posn != str.length() ) {
[e8ccca3]440 units = "?" + str.substr( posn ); // extract units
[76c62b2]441 str.erase( posn ); // remove units
442 } // if
443} // sepString
444
[bb7422a]445ast::Expr * build_constantChar( const CodeLocation & location, string & str ) {
[76c62b2]446 string units; // units
447 sepString( str, units, '\'' ); // separate constant from units
448
[bb7422a]449 ast::Expr * ret = new ast::ConstantExpr( location,
[7a780ad]450 new ast::BasicType( ast::BasicKind::Char ),
[bb7422a]451 str,
452 (unsigned long long int)(unsigned char)str[1] );
[e8ccca3]453 if ( units.length() != 0 ) {
[bb7422a]454 ret = new ast::UntypedExpr( location,
455 new ast::NameExpr( location, units ),
456 { ret } );
[e8ccca3]457 } // if
[76c62b2]458
[ab57786]459 delete &str; // created by lex
460 return ret;
[7bf7fb9]461} // build_constantChar
[51b73452]462
[20c2ade]463static bool isoctal( char ch ) {
464 return ('0' <= ch && ch <= '7');
465}
466
467static bool ishexadecimal( char ch ) {
468 return (('0' <= ch && ch <= '9')
469 || ('a' <= ch && ch <= 'f')
470 || ('A' <= ch && ch <= 'F'));
471}
472
473// A "sequence" is the series of characters in a character/string literal
474// that becomes a single character value in the runtime value.
475static size_t sequenceLength( const std::string & str, size_t pos ) {
476 // Most "sequences" are just a single character, filter those out:
477 if ( '\\' != str[pos] ) return 1;
478 switch ( str[pos + 1] ) {
479 // Simple Escape Sequence (\_ where _ is one of the following):
480 case '\'': case '\"': case '?': case '\\':
481 case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v':
482 // GCC Escape Sequence (as simple, just some different letters):
483 case 'e':
484 return 2;
485 // Numeric Escape Sequence (\___ where _ is 1-3 octal digits):
486 case '0': case '1': case '2': case '3':
487 case '4': case '5': case '6': case '7':
488 return ( !isoctal( str[pos + 2] ) ) ? 2 :
489 ( !isoctal( str[pos + 3] ) ) ? 3 : 4;
490 // Numeric Escape Sequence (\x_ where _ is 1 or more hexadecimal digits):
491 case 'x': {
492 size_t length = 2;
493 while ( ishexadecimal( str[pos + length] ) ) ++length;
494 return length;
495 }
496 // Uniersal Character Name (\u____ where _ is 4 decimal digits):
497 case 'u':
498 return 6;
499 // Uniersal Character Name (\U________ where _ is 8 decimal digits):
500 case 'U':
501 return 10;
502 default:
503 assertf( false, "Unknown escape sequence (start %c).", str[pos] );
504 return 1;
505 }
506}
507
[bb7422a]508ast::Expr * build_constantStr(
509 const CodeLocation & location,
510 string & str ) {
[6e3eaa57]511 assert( str.length() > 0 );
[76c62b2]512 string units; // units
513 sepString( str, units, '"' ); // separate constant from units
514
[bb7422a]515 ast::Type * strtype;
[513e165]516 switch ( str[0] ) { // str has >= 2 characters, i.e, null string "" => safe to look at subscripts 0/1
[0d0931d]517 case 'u':
[513e165]518 if ( str[1] == '8' ) goto Default; // utf-8 characters => array of char
519 // lookup type of associated typedef
[bb7422a]520 strtype = new ast::TypeInstType( "char16_t", ast::TypeDecl::Dtype );
[e612146c]521 break;
[0d0931d]522 case 'U':
[bb7422a]523 strtype = new ast::TypeInstType( "char32_t", ast::TypeDecl::Dtype );
[e612146c]524 break;
[0d0931d]525 case 'L':
[bb7422a]526 strtype = new ast::TypeInstType( "wchar_t", ast::TypeDecl::Dtype );
[e612146c]527 break;
[0d0931d]528 Default: // char default string type
529 default:
[5a2b0b7]530 strtype = new ast::BasicType( ast::BasicKind::Char );
[e612146c]531 } // switch
[20c2ade]532
533 // The dimension value of the type is equal to the number of "sequences"
534 // not including the openning and closing quotes in the literal plus 1
535 // for the implicit null terminator.
536 size_t dimension = 1;
537 for ( size_t pos = 1 ; pos < str.size() - 1 ;
538 pos += sequenceLength( str, pos ) ) {
539 dimension += 1;
540 }
541
[bb7422a]542 ast::ArrayType * at = new ast::ArrayType(
543 strtype,
[20c2ade]544 ast::ConstantExpr::from_ulong( location, dimension ),
[bb7422a]545 ast::FixedLen,
546 ast::DynamicDim );
547 ast::Expr * ret = new ast::ConstantExpr( location, at, str, std::nullopt );
[e612146c]548 if ( units.length() != 0 ) {
[bb7422a]549 ret = new ast::UntypedExpr( location,
550 new ast::NameExpr( location, units ),
551 { ret } );
[e612146c]552 } // if
[5809461]553
[ab57786]554 delete &str; // created by lex
555 return ret;
[7bf7fb9]556} // build_constantStr
[51b73452]557
[bb7422a]558ast::Expr * build_field_name_FLOATING_FRACTIONconstant(
559 const CodeLocation & location, const string & str ) {
[ca9d65e]560 if ( str.find_first_not_of( "0123456789", 1 ) != string::npos ) SemanticError( yylloc, "invalid tuple index \"%s\".", str.c_str() );
[bb7422a]561 ast::Expr * ret = build_constantInteger( location,
562 *new string( str.substr(1) ) );
[930f69e]563 delete &str;
564 return ret;
565} // build_field_name_FLOATING_FRACTIONconstant
566
[bb7422a]567ast::Expr * build_field_name_FLOATING_DECIMALconstant(
568 const CodeLocation & location, const string & str ) {
[ca9d65e]569 if ( str[str.size() - 1] != '.' ) SemanticError( yylloc, "invalid tuple index \"%s\".", str.c_str() );
[bb7422a]570 ast::Expr * ret = build_constantInteger(
571 location, *new string( str.substr( 0, str.size()-1 ) ) );
[930f69e]572 delete &str;
573 return ret;
574} // build_field_name_FLOATING_DECIMALconstant
575
[bb7422a]576ast::Expr * build_field_name_FLOATINGconstant( const CodeLocation & location,
577 const string & str ) {
[8780e30]578 // str is of the form A.B -> separate at the . and return member expression
579 int a, b;
580 char dot;
[f43df73]581 stringstream ss( str );
[8780e30]582 ss >> a >> dot >> b;
[bb7422a]583 auto ret = new ast::UntypedMemberExpr( location,
584 ast::ConstantExpr::from_int( location, b ),
585 ast::ConstantExpr::from_int( location, a )
586 );
[8780e30]587 delete &str;
588 return ret;
589} // build_field_name_FLOATINGconstant
590
[bb7422a]591ast::Expr * make_field_name_fraction_constants( const CodeLocation & location,
592 ast::Expr * fieldName,
593 ast::Expr * fracts ) {
594 if ( nullptr == fracts ) {
595 return fieldName;
596 } else if ( auto memberExpr = dynamic_cast<ast::UntypedMemberExpr *>( fracts ) ) {
597 memberExpr->member = make_field_name_fraction_constants( location,
598 fieldName,
599 ast::mutate( memberExpr->aggregate.get() ) );
600 return memberExpr;
601 } else {
602 return new ast::UntypedMemberExpr( location, fracts, fieldName );
[f43df73]603 } // if
[8780e30]604} // make_field_name_fraction_constants
605
[bb7422a]606ast::Expr * build_field_name_fraction_constants( const CodeLocation & location,
607 ast::Expr * fieldName,
608 ExpressionNode * fracts ) {
609 return make_field_name_fraction_constants( location, fieldName, maybeMoveBuild( fracts ) );
[8780e30]610} // build_field_name_fraction_constants
611
[bb7422a]612ast::NameExpr * build_varref( const CodeLocation & location,
613 const string * name ) {
614 ast::NameExpr * expr = new ast::NameExpr( location, *name );
[7ecbb7e]615 delete name;
616 return expr;
[a2e0687]617} // build_varref
[51b1202]618
[bb7422a]619ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location,
620 const DeclarationNode * decl_node,
621 const ast::NameExpr * name ) {
622 ast::Decl * newDecl = maybeBuild( decl_node );
623 if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) {
624 if ( const ast::Type * t = newDeclWithType->get_type() ) {
625 if ( auto typeInst = dynamic_cast<const ast::TypeInstType *>( t ) ) {
626 newDecl = new ast::EnumDecl( location, typeInst->name );
[b0d9ff7]627 }
628 }
629 }
[bb7422a]630 return new ast::QualifiedNameExpr( location, newDecl, name->name );
[b0d9ff7]631}
632
[bb7422a]633ast::QualifiedNameExpr * build_qualified_expr( const CodeLocation & location,
634 const ast::EnumDecl * decl,
635 const ast::NameExpr * name ) {
636 return new ast::QualifiedNameExpr( location, decl, name->name );
[4e2befe3]637}
638
[bb7422a]639ast::DimensionExpr * build_dimensionref( const CodeLocation & location,
640 const string * name ) {
641 ast::DimensionExpr * expr = new ast::DimensionExpr( location, *name );
[6e50a6b]642 delete name;
643 return expr;
644} // build_varref
[ea54f1e]645
[5809461]646// TODO: get rid of this and OperKinds and reuse code from OperatorTable
[a2e0687]647static const char * OperName[] = { // must harmonize with OperKinds
[5721a6d]648 // diadic
[e5f2a67]649 "SizeOf", "AlignOf", "OffsetOf", "?+?", "?-?", "?\\?", "?*?", "?/?", "?%?", "||", "&&",
[5721a6d]650 "?|?", "?&?", "?^?", "Cast", "?<<?", "?>>?", "?<?", "?>?", "?<=?", "?>=?", "?==?", "?!=?",
[e5f2a67]651 "?=?", "?@=?", "?\\=?", "?*=?", "?/=?", "?%=?", "?+=?", "?-=?", "?<<=?", "?>>=?", "?&=?", "?^=?", "?|=?",
[d9e2280]652 "?[?]", "...",
[5721a6d]653 // monadic
[5809461]654 "+?", "-?", "AddressOf", "*?", "!?", "~?", "++?", "?++", "--?", "?--",
[a2e0687]655}; // OperName
[5721a6d]656
[bb7422a]657ast::Expr * build_cast( const CodeLocation & location,
658 DeclarationNode * decl_node,
[24d6572]659 ExpressionNode * expr_node,
660 ast::CastExpr::CastKind kind ) {
[bb7422a]661 ast::Type * targetType = maybeMoveBuildType( decl_node );
662 if ( dynamic_cast<ast::VoidType *>( targetType ) ) {
[064e3ff]663 delete targetType;
[bb7422a]664 return new ast::CastExpr( location,
665 maybeMoveBuild( expr_node ),
[24d6572]666 ast::ExplicitCast, kind );
[064e3ff]667 } else {
[bb7422a]668 return new ast::CastExpr( location,
669 maybeMoveBuild( expr_node ),
670 targetType,
[24d6572]671 ast::ExplicitCast, kind );
[064e3ff]672 } // if
[a2e0687]673} // build_cast
[a5f0529]674
[bb7422a]675ast::Expr * build_keyword_cast( const CodeLocation & location,
676 ast::AggregateDecl::Aggregate target,
677 ExpressionNode * expr_node ) {
678 return new ast::KeywordCastExpr( location,
679 maybeMoveBuild( expr_node ),
680 target
681 );
[9a705dc8]682}
683
[bb7422a]684ast::Expr * build_virtual_cast( const CodeLocation & location,
685 DeclarationNode * decl_node,
686 ExpressionNode * expr_node ) {
687 return new ast::VirtualCastExpr( location,
688 maybeMoveBuild( expr_node ),
689 maybeMoveBuildType( decl_node )
690 );
[a2e0687]691} // build_virtual_cast
[064e3ff]692
[bb7422a]693ast::Expr * build_fieldSel( const CodeLocation & location,
694 ExpressionNode * expr_node,
695 ast::Expr * member ) {
696 return new ast::UntypedMemberExpr( location,
697 member,
698 maybeMoveBuild( expr_node )
699 );
[a2e0687]700} // build_fieldSel
[064e3ff]701
[bb7422a]702ast::Expr * build_pfieldSel( const CodeLocation & location,
703 ExpressionNode * expr_node,
704 ast::Expr * member ) {
705 auto deref = new ast::UntypedExpr( location,
706 new ast::NameExpr( location, "*?" )
707 );
[64ac636]708 deref->location = expr_node->location;
[bb7422a]709 deref->args.push_back( maybeMoveBuild( expr_node ) );
710 auto ret = new ast::UntypedMemberExpr( location, member, deref );
[064e3ff]711 return ret;
[a2e0687]712} // build_pfieldSel
[064e3ff]713
[bb7422a]714ast::Expr * build_offsetOf( const CodeLocation & location,
715 DeclarationNode * decl_node,
716 ast::NameExpr * member ) {
717 ast::Expr * ret = new ast::UntypedOffsetofExpr( location,
718 maybeMoveBuildType( decl_node ),
719 member->name
720 );
[7a780ad]721 ret->result = new ast::BasicType( ast::BasicKind::LongUnsignedInt );
[ac71a86]722 delete member;
723 return ret;
[a2e0687]724} // build_offsetOf
[064e3ff]725
[bb7422a]726ast::Expr * build_and_or( const CodeLocation & location,
727 ExpressionNode * expr_node1,
728 ExpressionNode * expr_node2,
729 ast::LogicalFlag flag ) {
730 return new ast::LogicalExpr( location,
[61e362f]731 maybeMoveBuild( expr_node1 ),
732 maybeMoveBuild( expr_node2 ),
[bb7422a]733 flag
734 );
[a2e0687]735} // build_and_or
[51e076e]736
[bb7422a]737ast::Expr * build_unary_val( const CodeLocation & location,
738 OperKinds op,
739 ExpressionNode * expr_node ) {
740 std::vector<ast::ptr<ast::Expr>> args;
[702e826]741 args.push_back( maybeMoveBuild( expr_node ) );
[bb7422a]742 return new ast::UntypedExpr( location,
743 new ast::NameExpr( location, OperName[ (int)op ] ),
744 std::move( args )
745 );
[a2e0687]746} // build_unary_val
747
[bb7422a]748ast::Expr * build_binary_val( const CodeLocation & location,
749 OperKinds op,
750 ExpressionNode * expr_node1,
751 ExpressionNode * expr_node2 ) {
752 std::vector<ast::ptr<ast::Expr>> args;
[702e826]753 args.push_back( maybeMoveBuild( expr_node1 ) );
754 args.push_back( maybeMoveBuild( expr_node2 ) );
[bb7422a]755 return new ast::UntypedExpr( location,
756 new ast::NameExpr( location, OperName[ (int)op ] ),
757 std::move( args )
758 );
[a2e0687]759} // build_binary_val
760
[bb7422a]761ast::Expr * build_cond( const CodeLocation & location,
762 ExpressionNode * expr_node1,
763 ExpressionNode * expr_node2,
764 ExpressionNode * expr_node3 ) {
765 return new ast::ConditionalExpr( location,
[61e362f]766 maybeMoveBuild( expr_node1 ),
[bb7422a]767 maybeMoveBuild( expr_node2 ),
768 maybeMoveBuild( expr_node3 )
769 );
[a2e0687]770} // build_cond
[51e076e]771
[bb7422a]772ast::Expr * build_tuple( const CodeLocation & location,
773 ExpressionNode * expr_node ) {
774 std::vector<ast::ptr<ast::Expr>> exprs;
[907eccb]775 buildMoveList( expr_node, exprs );
[bb7422a]776 return new ast::UntypedTupleExpr( location, std::move( exprs ) );
[a2e0687]777} // build_tuple
[9706554]778
[bb7422a]779ast::Expr * build_func( const CodeLocation & location,
780 ExpressionNode * function,
781 ExpressionNode * expr_node ) {
782 std::vector<ast::ptr<ast::Expr>> args;
[7ecbb7e]783 buildMoveList( expr_node, args );
[bb7422a]784 return new ast::UntypedExpr( location,
785 maybeMoveBuild( function ),
786 std::move( args )
787 );
[a2e0687]788} // build_func
[9706554]789
[bb7422a]790ast::Expr * build_compoundLiteral( const CodeLocation & location,
791 DeclarationNode * decl_node,
792 InitializerNode * kids ) {
793 // compound literal type
794 ast::Decl * newDecl = maybeBuild( decl_node );
795 // non-sue compound-literal type
796 if ( ast::DeclWithType * newDeclWithType = dynamic_cast<ast::DeclWithType *>( newDecl ) ) {
797 return new ast::CompoundLiteralExpr( location,
798 newDeclWithType->get_type(),
799 maybeMoveBuild( kids ) );
[630a82a]800 // these types do not have associated type information
[bb7422a]801 } else if ( auto newDeclStructDecl = dynamic_cast<ast::StructDecl *>( newDecl ) ) {
802 if ( newDeclStructDecl->body ) {
803 return new ast::CompoundLiteralExpr( location,
804 new ast::StructInstType( newDeclStructDecl ),
805 maybeMoveBuild( kids ) );
[fbcde64]806 } else {
[bb7422a]807 return new ast::CompoundLiteralExpr( location,
808 new ast::StructInstType( newDeclStructDecl->name ),
809 maybeMoveBuild( kids ) );
[fbcde64]810 } // if
[bb7422a]811 } else if ( auto newDeclUnionDecl = dynamic_cast<ast::UnionDecl *>( newDecl ) ) {
812 if ( newDeclUnionDecl->body ) {
813 return new ast::CompoundLiteralExpr( location,
814 new ast::UnionInstType( newDeclUnionDecl ),
815 maybeMoveBuild( kids ) );
[fbcde64]816 } else {
[bb7422a]817 return new ast::CompoundLiteralExpr( location,
818 new ast::UnionInstType( newDeclUnionDecl->name ),
819 maybeMoveBuild( kids ) );
[fbcde64]820 } // if
[bb7422a]821 } else if ( auto newDeclEnumDecl = dynamic_cast<ast::EnumDecl *>( newDecl ) ) {
822 if ( newDeclEnumDecl->body ) {
823 return new ast::CompoundLiteralExpr( location,
824 new ast::EnumInstType( newDeclEnumDecl ),
825 maybeMoveBuild( kids ) );
[fbcde64]826 } else {
[bb7422a]827 return new ast::CompoundLiteralExpr( location,
828 new ast::EnumInstType( newDeclEnumDecl->name ),
829 maybeMoveBuild( kids ) );
[fbcde64]830 } // if
[630a82a]831 } else {
832 assert( false );
833 } // if
[a2e0687]834} // build_compoundLiteral
[630a82a]835
[45ee172]836ast::Expr * build_va_arg( const CodeLocation & location,
837 ExpressionNode * function, DeclarationNode * declaration ) {
838 return build_func( location,
839 new ExpressionNode(
840 build_varref( location, new std::string( "__builtin_va_arg" ) ) ),
841 function->set_last( new ExpressionNode( new ast::TypeExpr( location,
842 maybeMoveBuildType( declaration ) ) ) )
843 );
844}
845
[b87a5ed]846// Local Variables: //
847// tab-width: 4 //
848// End: //
Note: See TracBrowser for help on using the repository browser.