1717#include < cstring>
1818
1919
20+
2021#include " ../dispatchkit/boxed_value.hpp"
2122#include " chaiscript_common.hpp"
2223
24+
25+ #if defined(CHAISCRIPT_MSVC) && defined(max) && defined(min)
26+ #pragma push_macro("max") // Why Microsoft? why? This is worse than bad
27+ #undef max
28+ #pragma push_macro("min")
29+ #undef min
30+ #endif
31+
32+
2333namespace chaiscript
2434{
2535 // / \brief Classes and functions used during the parsing process.
@@ -621,8 +631,7 @@ namespace chaiscript
621631
622632
623633
624- template <typename IntType>
625- static Boxed_Value buildInt (const IntType &t_type, const std::string &t_val)
634+ static Boxed_Value buildInt (const int base, const std::string &t_val, const bool prefixed)
626635 {
627636 bool unsigned_ = false ;
628637 bool long_ = false ;
@@ -649,94 +658,47 @@ namespace chaiscript
649658 }
650659 }
651660
652- std::stringstream ss (t_val.substr (0 , i));
653- ss >> t_type;
654-
655- std::stringstream testu (t_val.substr (0 , i));
656- uint64_t u;
657- testu >> t_type >> u;
658-
659- bool unsignedrequired = false ;
660-
661- if ((u >> (sizeof (int ) * 8 )) > 0 )
662- {
663- // requires something bigger than int
664- long_ = true ;
665- }
666-
667- static_assert (sizeof (long ) == sizeof (uint64_t ) || sizeof (long ) * 2 == sizeof (uint64_t ), " Unexpected sizing of integer types" );
661+ const auto val = prefixed?std::string (t_val.begin ()+2 ,t_val.end ()):t_val;
668662
669- if ((sizeof (long ) < sizeof (uint64_t ))
670- && (u >> ((sizeof (uint64_t ) - sizeof (long )) * 8 )) > 0 )
671- {
672- // requires something bigger than long
673- longlong_ = true ;
674- }
663+ try {
664+ auto u = std::stoll (val,nullptr ,base);
675665
666+ #ifdef __GNUC__
667+ #pragma GCC diagnostic push
668+ #pragma GCC diagnostic ignored "-Wsign-compare"
669+ #endif
676670
677- const size_t size = [&]()->size_t {
678- if (longlong_)
679- {
680- return sizeof (int64_t ) * 8 ;
681- } else if (long_) {
682- return sizeof (long ) * 8 ;
671+ if (!unsigned_ && !long_ && u >= std::numeric_limits<int >::min () && u <= std::numeric_limits<int >::max ()) {
672+ return const_var (static_cast <int >(u));
673+ } else if ((unsigned_ || base != 10 ) && !long_ && u >= std::numeric_limits<unsigned int >::min () && u <= std::numeric_limits<unsigned int >::max ()) {
674+ return const_var (static_cast <unsigned int >(u));
675+ } else if (!unsigned_ && !longlong_ && u >= std::numeric_limits<long >::min () && u <= std::numeric_limits<long >::max ()) {
676+ return const_var (static_cast <long >(u));
677+ } else if ((unsigned_ || base != 10 ) && !longlong_ && u >= std::numeric_limits<unsigned long >::min () && u <= std::numeric_limits<unsigned long >::max ()) {
678+ return const_var (static_cast <unsigned long >(u));
679+ } else if (!unsigned_ && u >= std::numeric_limits<long long >::min () && u <= std::numeric_limits<long long >::max ()) {
680+ return const_var (static_cast <long long >(u));
683681 } else {
684- return sizeof ( int ) * 8 ;
682+ return const_var ( static_cast < unsigned long long >(u)) ;
685683 }
686- }();
687684
688- if ( (u >> (size - 1 )) > 0 )
689- {
690- unsignedrequired = true ;
691- }
685+ #ifdef __GNUC__
686+ #pragma GCC diagnostic pop
687+ #endif
692688
693- if (unsignedrequired && !unsigned_)
694- {
695- if (t_type == &std::hex || t_type == &std::oct)
696- {
697- // with hex and octal we are happy to just make it unsigned
698- unsigned_ = true ;
699- } else {
700- // with decimal we must bump it up to the next size
701- if (long_)
702- {
703- longlong_ = true ;
704- } else if (!long_ && !longlong_) {
705- long_ = true ;
706- }
707- }
708- }
689+ } catch (const std::out_of_range &) {
690+ // too big to be signed
691+ try {
692+ auto u = std::stoull (val,nullptr ,base);
709693
710- if (unsigned_)
711- {
712- if (longlong_)
713- {
714- uint64_t val;
715- ss >> val;
716- return const_var (val);
717- } else if (long_) {
718- unsigned long val;
719- ss >> val;
720- return const_var (val);
721- } else {
722- unsigned int val;
723- ss >> val;
724- return const_var (val);
725- }
726- } else {
727- if (longlong_)
728- {
729- int64_t val;
730- ss >> val;
731- return const_var (val);
732- } else if (long_) {
733- long val;
734- ss >> val;
735- return const_var (val);
736- } else {
737- int val;
738- ss >> val;
739- return const_var (val);
694+ if (u >= std::numeric_limits<unsigned long >::min () && u <= std::numeric_limits<unsigned long >::max ()) {
695+ return const_var (static_cast <unsigned long >(u));
696+ } else {
697+ return const_var (static_cast <unsigned long long >(u));
698+ }
699+ } catch (const std::out_of_range &) {
700+ // it's just simply too big
701+ return const_var (std::numeric_limits<long long >::max ());
740702 }
741703 }
742704 }
@@ -756,59 +718,44 @@ namespace chaiscript
756718 } else {
757719 const auto start = m_position;
758720 if (m_position.has_more () && char_in_alphabet (*m_position, detail::float_alphabet) ) {
759- if (Hex_ ()) {
760- auto match = Position::str (start, m_position);
761- auto bv = buildInt (std::hex, match);
762- m_match_stack.emplace_back (make_node<eval::Int_AST_Node>(std::move (match), start.line , start.col , std::move (bv)));
763- return true ;
764- }
765-
766- if (Binary_ ()) {
767- auto match = Position::str (start, m_position);
768- int64_t temp_int = 0 ;
769- size_t pos = 0 ;
770- const auto end = match.length ();
771-
772- while ((pos < end) && (pos < (2 + sizeof (int ) * 8 ))) {
773- temp_int <<= 1 ;
774- if (match[pos] == ' 1' ) {
775- temp_int += 1 ;
776- }
777- ++pos;
721+ try {
722+ if (Hex_ ()) {
723+ auto match = Position::str (start, m_position);
724+ auto bv = buildInt (16 , match, true );
725+ m_match_stack.emplace_back (make_node<eval::Int_AST_Node>(std::move (match), start.line , start.col , std::move (bv)));
726+ return true ;
778727 }
779728
780- Boxed_Value i = [&]()->Boxed_Value {
781- if (match.length () <= sizeof (int ) * 8 )
782- {
783- return const_var (static_cast <int >(temp_int));
784- } else {
785- return const_var (temp_int);
786- }
787- }();
788-
789- m_match_stack.push_back (make_node<eval::Int_AST_Node>(std::move (match), start.line , start.col , std::move (i)));
790- return true ;
791- }
792- if (Float_ ()) {
793- auto match = Position::str (start, m_position);
794- auto bv = buildFloat (match);
795- m_match_stack.push_back (make_node<eval::Float_AST_Node>(std::move (match), start.line , start.col , std::move (bv)));
796- return true ;
797- }
798- else {
799- IntSuffix_ ();
800- auto match = Position::str (start, m_position);
801- if (!match.empty () && (match[0 ] == ' 0' )) {
802- auto bv = buildInt (std::oct, match);
729+ if (Binary_ ()) {
730+ auto match = Position::str (start, m_position);
731+ auto bv = buildInt (2 , match, true );
803732 m_match_stack.push_back (make_node<eval::Int_AST_Node>(std::move (match), start.line , start.col , std::move (bv)));
733+ return true ;
804734 }
805- else if (!match. empty ()) {
806- auto bv = buildInt (std::dec, match );
807- m_match_stack. push_back (make_node<eval::Int_AST_Node>( std::move (match), start. line , start. col , std::move (bv)) );
808- } else {
809- return false ;
735+ if (Float_ ()) {
736+ auto match = Position::str (start, m_position );
737+ auto bv = buildFloat (match );
738+ m_match_stack. push_back (make_node<eval::Float_AST_Node>( std::move (match), start. line , start. col , std::move (bv)));
739+ return true ;
810740 }
811- return true ;
741+ else {
742+ IntSuffix_ ();
743+ auto match = Position::str (start, m_position);
744+ if (!match.empty () && (match[0 ] == ' 0' )) {
745+ auto bv = buildInt (8 , match, false );
746+ m_match_stack.push_back (make_node<eval::Int_AST_Node>(std::move (match), start.line , start.col , std::move (bv)));
747+ }
748+ else if (!match.empty ()) {
749+ auto bv = buildInt (10 , match, false );
750+ m_match_stack.push_back (make_node<eval::Int_AST_Node>(std::move (match), start.line , start.col , std::move (bv)));
751+ } else {
752+ return false ;
753+ }
754+ return true ;
755+ }
756+ } catch (const std::invalid_argument &) {
757+ // error parsing number passed in to buildFloat/buildInt
758+ return false ;
812759 }
813760 }
814761 else {
@@ -975,6 +922,8 @@ namespace chaiscript
975922 {
976923 }
977924
925+ Char_Parser &operator =(const Char_Parser &) = delete ;
926+
978927 ~Char_Parser (){
979928 if (is_octal) {
980929 process_octal ();
@@ -2456,5 +2405,12 @@ namespace chaiscript
24562405 }
24572406}
24582407
2408+
2409+ #ifdef CHAISCRIPT_MSVC
2410+ #pragma pop_macro("min")
2411+ #pragma pop_macro("max")
2412+ #endif
2413+
2414+
24592415#endif /* CHAISCRIPT_PARSER_HPP_ */
24602416
0 commit comments