30
30
31
31
#include " parser.h"
32
32
#include " libchecktestdata.hpp"
33
+ #include " databuffer.hpp"
33
34
34
35
using namespace std ;
35
36
@@ -42,12 +43,12 @@ class generate_exception {};
42
43
const int display_before_error = 65 ;
43
44
const int display_after_error = 50 ;
44
45
45
- size_t prognr, datanr, linenr, charnr, extra_ws ;
46
+ size_t prognr;
46
47
command currcmd;
47
48
48
49
gmp_randclass gmp_rnd (gmp_randinit_default);
49
50
50
- string data;
51
+ databuffer data;
51
52
vector<command> program;
52
53
53
54
// This stores array-type variables like x[i,j] as string "x" and
@@ -149,7 +150,7 @@ void readtestdata(istream &in)
149
150
exit (exit_failure);
150
151
}
151
152
152
- data = ss.str ();
153
+ data = databuffer ( ss.str () );
153
154
}
154
155
155
156
void error (string msg = string())
@@ -159,17 +160,14 @@ void error(string msg = string())
159
160
throw generate_exception ();
160
161
}
161
162
162
- size_t fr = max (0 ,int (datanr)-display_before_error);
163
- size_t to = min (data.size (),datanr+display_after_error);
164
-
165
- debug (" error at datanr = %d, %d - %d\n " ,(int )datanr,(int )fr,(int )to);
163
+ debug (" error at datanr = %d\n " ,(int )data.pos ());
166
164
167
165
if ( !quiet ) {
168
- cerr << data.substr (fr,datanr-fr ) << endl;
169
- cerr << string (min (charnr ,(size_t )display_before_error),' ' ) << ' ^' ;
170
- cerr << data.substr (datanr,to-datanr ) << endl << endl;
166
+ cerr << data.prev (display_before_error ) << endl;
167
+ cerr << string (min (data. lpos () ,(size_t )display_before_error),' ' ) << ' ^' ;
168
+ cerr << data.next (display_after_error ) << endl << endl;
171
169
172
- cerr << " ERROR: line " << linenr +1 << " character " << charnr +1 ;
170
+ cerr << " ERROR: line " << data. line () +1 << " character " << data. lpos () +1 ;
173
171
cerr << " of testdata doesn't match " << currcmd;
174
172
if ( msg.length ()>0 ) cerr << " : " << msg;
175
173
cerr << endl << endl;
@@ -589,12 +587,12 @@ bool dotest(const test& t)
589
587
case ' E' : if ( gendata ) {
590
588
return (random () % 10 < 3 );
591
589
} else {
592
- return datanr>= data.size ();
590
+ return data.eof ();
593
591
}
594
592
case ' M' : if ( gendata ) {
595
593
return (random () % 2 == 0 );
596
594
} else {
597
- return datanr< data.size () && t.args [0 ].val .find (data[datanr] )!=string::npos;
595
+ return ! data.eof () && t.args [0 ].val .find (data. next () )!=string::npos;
598
596
}
599
597
case ' U' : return unique (t.args );
600
598
case ' A' : return inarray (t.args [0 ],t.args [1 ]);
@@ -605,46 +603,30 @@ bool dotest(const test& t)
605
603
}
606
604
}
607
605
608
- int isspace_notnewline (char c) { return isspace (c) && c!=' \n ' ; }
609
-
610
- void readwhitespace ()
611
- {
612
- while ( datanr<data.size () && isspace_notnewline (data[datanr]) ) {
613
- datanr++;
614
- charnr++;
615
- extra_ws++;
616
- }
617
- }
618
-
619
606
void checkspace ()
620
607
{
621
- if ( datanr>= data.size () ) error (" end of file" );
608
+ if ( data.eof () ) error (" end of file" );
622
609
623
610
if ( whitespace_ok ) {
624
611
// First check at least one space-like character
625
- if ( !isspace_notnewline (data[datanr++]) ) error ();
626
- charnr++;
612
+ if ( !isspace_notnewline (data.readchar ()) ) error ();
627
613
// Then greedily read non-newline whitespace
628
- readwhitespace ();
614
+ data. readwhitespace ();
629
615
} else {
630
- if ( data[datanr++]!=' ' ) error ();
631
- charnr++;
616
+ if ( data.readchar ()!=' ' ) error ();
632
617
}
633
618
}
634
619
635
620
void checknewline ()
636
621
{
637
622
// Trailing whitespace before newline
638
- if ( whitespace_ok ) readwhitespace ();
623
+ if ( whitespace_ok ) data. readwhitespace ();
639
624
640
- if ( datanr>=data.size () ) error (" end of file" );
641
- if ( data[datanr++]!=' \n ' ) error ();
642
- linenr++;
643
- charnr=0 ;
625
+ if ( data.eof () ) error (" end of file" );
626
+ if ( data.readchar ()!=' \n ' ) error ();
644
627
645
628
// Leading whitespace after newline
646
- if ( whitespace_ok ) readwhitespace ();
647
-
629
+ if ( whitespace_ok ) data.readwhitespace ();
648
630
}
649
631
650
632
#define MAX_MULT 10
@@ -834,8 +816,7 @@ void getdecrange(const command& cmd, int *decrange)
834
816
void gentoken (command cmd, ostream &datastream)
835
817
{
836
818
currcmd = cmd;
837
- debug (" generating token %s at %lu,%lu" ,
838
- cmd.name ().c_str (),(unsigned long )linenr,(unsigned long )charnr);
819
+ debug (" generating token %s" , cmd.name ().c_str ());
839
820
840
821
if ( cmd.name ()==" SPACE" ) datastream << ' ' ;
841
822
@@ -942,7 +923,7 @@ void checktoken(const command& cmd)
942
923
{
943
924
currcmd = cmd;
944
925
debug (" checking token %s at %lu,%lu" ,
945
- cmd.name ().c_str (),( unsigned long )linenr,( unsigned long )charnr );
926
+ cmd.name ().c_str (),data. line (),data. lpos () );
946
927
947
928
if ( cmd.name ()==" SPACE" ) checkspace ();
948
929
@@ -952,12 +933,8 @@ void checktoken(const command& cmd)
952
933
// Accepts format (0|-?[1-9][0-9]*), i.e. no leading zero's
953
934
// and no '-0' accepted.
954
935
string num;
955
- size_t len = 0 ;
956
- while ( datanr<data.size () &&
957
- (isdigit (data[datanr+len]) ||
958
- (num.size ()==0 && data[datanr+len]==' -' )) ) {
959
- num += data[datanr+len];
960
- len++;
936
+ while ( isdigit (data.peek ()) || (num.empty () && data.peek ()==' -' ) ) {
937
+ num += data.readchar ();
961
938
}
962
939
963
940
mpz_class lo = eval (cmd.args [0 ]);
@@ -977,9 +954,6 @@ void checktoken(const command& cmd)
977
954
978
955
if ( x<lo || x>hi ) error (" value out of range" );
979
956
if ( cmd.nargs ()>=3 ) setvar (cmd.args [2 ],value_t (x));
980
-
981
- datanr += len;
982
- charnr += len;
983
957
}
984
958
985
959
else if ( cmd.name ()==" FLOAT" || cmd.name ()==" FLOATP" ) {
@@ -1005,45 +979,33 @@ void checktoken(const command& cmd)
1005
979
}
1006
980
}
1007
981
1008
- size_t start = datanr ;
982
+ size_t start = data. pos () ;
1009
983
// Match optional minus sign:
1010
- if ( datanr< data.size () && data[datanr] ==' -' ) { datanr++; charnr++; }
984
+ if ( data.peek () ==' -' ) data. readchar ();
1011
985
// Match base with optional decimal dot:
1012
- if ( datanr>=data.size () || !isdigit (data[datanr]) ) error (" digit expected" );
1013
- size_t digitpos = datanr, dotpos = string::npos;
1014
- while ( datanr<data.size () &&
1015
- (isdigit (data[datanr]) ||
1016
- (dotpos==string::npos && digitpos!=datanr && data[datanr]==' .' )) ) {
1017
- if ( data[datanr]==' .' ) dotpos = datanr;
1018
- datanr++;
1019
- charnr++;
986
+ if ( !isdigit (data.peek ()) ) error (" digit expected" );
987
+ size_t digitpos = data.pos (), dotpos = string::npos;
988
+ char first_digit = data.peek ();
989
+ while ( (isdigit (data.peek ()) ||
990
+ (dotpos==string::npos && digitpos!=data.pos () && data.peek ()==' .' )) ) {
991
+ if ( data.readchar ()==' .' ) dotpos = data.pos ()-1 ;
1020
992
}
1021
993
// Check that any dot is followed by digit:
1022
- if ( !isdigit (data[datanr- 1 ] ) ) error (" digit expected" );
994
+ if ( !isdigit (data. peek (- 1 ) ) ) error (" digit expected" );
1023
995
1024
- size_t exppos = datanr ;
996
+ size_t exppos = data. pos () ;
1025
997
bool has_exp = false ;
1026
998
// Match exponent:
1027
- if ( opt==1 || (opt==0 && datanr<data.size () && toupper (data[datanr])==' E' ) ) {
1028
- if ( datanr>=data.size () || toupper (data[datanr])!=' E' ) {
1029
- error (" exponent 'E' expected" );
1030
- }
999
+ if ( opt==1 || (opt==0 && toupper (data.peek ())==' E' ) ) {
1000
+ if ( toupper (data.readchar ())!=' E' ) error (" exponent 'E' expected" );
1031
1001
has_exp = true ;
1032
- datanr++;
1033
- charnr++;
1034
- if ( datanr<data.size () && (data[datanr]==' -' || data[datanr]==' +' ) ) {
1035
- datanr++;
1036
- charnr++;
1037
- }
1038
- while ( datanr<data.size () && isdigit (data[datanr]) ) {
1039
- datanr++;
1040
- charnr++;
1041
- }
1042
- if ( !isdigit (data[datanr-1 ]) ) error (" digit expected" );
1002
+ if ( data.peek ()==' -' || data.peek ()==' +' ) data.readchar ();
1003
+ while ( isdigit (data.peek ()) ) data.readchar ();
1004
+ if ( !isdigit (data.peek (-1 )) ) error (" digit expected" );
1043
1005
}
1044
1006
1045
1007
if ( cmd.name ()==" FLOATP" ) {
1046
- if ( has_exp && (data[digitpos] ==' 0' || dotpos!=digitpos+1 ) ) {
1008
+ if ( has_exp && (first_digit ==' 0' || dotpos!=digitpos+1 ) ) {
1047
1009
error (" exactly one non-zero before the decimal dot expected" );
1048
1010
}
1049
1011
int ndecimals = (dotpos==string::npos ? 0 : exppos - dotpos - 1 );
@@ -1054,7 +1016,7 @@ void checktoken(const command& cmd)
1054
1016
}
1055
1017
}
1056
1018
1057
- string matchstr = data.substr (start,datanr -start);
1019
+ string matchstr = data.prev (data. pos () -start);
1058
1020
1059
1021
debug (" parsing float '%s', exponent = %d" ,matchstr.c_str (),has_exp);
1060
1022
@@ -1070,10 +1032,8 @@ void checktoken(const command& cmd)
1070
1032
else if ( cmd.name ()==" STRING" ) {
1071
1033
string str = eval (cmd.args [0 ]).getstr ();
1072
1034
for (size_t i=0 ; i<str.size (); i++) {
1073
- if ( datanr>=data.size () ) error (" premature end of file" );
1074
- if ( data[datanr++]!=str[i] ) error ();
1075
- charnr++;
1076
- if ( str[i]==' \n ' ) linenr++, charnr=0 ;
1035
+ if ( data.eof () ) error (" premature end of file" );
1036
+ if ( data.readchar ()!=str[i] ) error ();
1077
1037
}
1078
1038
1079
1039
debug (" '%s' = '%s'" ,str.c_str (),cmd.args [0 ].c_str ());
@@ -1082,19 +1042,17 @@ void checktoken(const command& cmd)
1082
1042
else if ( cmd.name ()==" REGEX" ) {
1083
1043
string str = eval (cmd.args [0 ]).getstr ();
1084
1044
regex regexstr (str,regex::extended);
1085
- match_results<string::const_iterator> res;
1045
+ smatch res;
1086
1046
string matchstr;
1087
1047
1088
- if ( ! regex_search ( data.cbegin ()+datanr, data.cend (),
1089
- res,regexstr,regex_constants::match_continuous) ) {
1048
+ string searchstr = data.next ( data.size ());
1049
+ if ( ! regex_search (searchstr, res,regexstr,regex_constants::match_continuous) ) {
1090
1050
error ();
1091
1051
} else {
1092
- size_t matchend = size_t (res[0 ].second -data.begin ());
1093
- matchstr = string (data.begin ()+datanr,data.begin ()+matchend);
1094
- for (; datanr<matchend; datanr++) {
1095
- charnr++;
1096
- if ( data[datanr]==' \n ' ) linenr++, charnr=0 ;
1097
- }
1052
+ size_t match_len = res[0 ].second - res[0 ].first ;
1053
+ size_t match_end = data.pos () + match_len;
1054
+ matchstr = data.next (match_len);
1055
+ while ( data.pos ()<match_end ) data.readchar ();
1098
1056
}
1099
1057
debug (" '%s' = '%s'" ,matchstr.c_str (),str.c_str ());
1100
1058
@@ -1136,7 +1094,7 @@ void checktestdata(ostream &datastream)
1136
1094
return ;
1137
1095
} else {
1138
1096
debug (" checking EOF" );
1139
- if ( datanr++!= data.size () ) error ();
1097
+ if ( ! data.eof () ) error ();
1140
1098
throw eof_found_exception ();
1141
1099
}
1142
1100
}
@@ -1282,10 +1240,8 @@ void init_checktestdata(std::istream &progstream, int opt_mask)
1282
1240
srandom (seed.get_ui ());
1283
1241
gmp_rnd.seed (seed);
1284
1242
1285
- // Initialize current position in program and data.
1286
- linenr = charnr = 0 ;
1287
- datanr = prognr = 0 ;
1288
- extra_ws = 0 ;
1243
+ // Initialize current position in program.
1244
+ prognr = 0 ;
1289
1245
}
1290
1246
1291
1247
bool gentestdata (ostream &datastream)
@@ -1311,7 +1267,7 @@ bool checksyntax(istream &datastream)
1311
1267
1312
1268
// If we ignore whitespace, skip leading whitespace on first line
1313
1269
// as a special case; other lines are handled by checknewline().
1314
- if ( whitespace_ok ) readwhitespace ();
1270
+ if ( whitespace_ok ) data. readwhitespace ();
1315
1271
1316
1272
try {
1317
1273
checktestdata (dummy);
0 commit comments