88#include < vector>
99
1010
11- #ifdef _DEBUG
11+ #if defined( _DEBUG) || defined(__DEBUG)
1212 #include < iostream>
1313
1414 #define DEBUG_ENTER (x ) std::cerr << " ENTER " << row_count << " :" << col_count << " " << #x << std::endl
@@ -255,33 +255,59 @@ namespace dotenv
255255 inline void SINGLE_UNQUOTED_STRING ()
256256 {
257257 DEBUG_ENTER (SINGLE_UNQUOTED_STRING );
258- while (not token_is (SQ_C )) { next (); }
258+ while (not token_is (SQ_C ))
259+ {
260+ if (token_is (BS_C ))
261+ {
262+ possible_escaped_sequence ();
263+ }
264+ else
265+ {
266+ next ();
267+ }
268+ }
259269 DEBUG_EXIT (SINGLE_UNQUOTED_STRING );
260270 }
261271
262272 inline void DOUBLE_UNQUOTED_STRING ()
263273 {
264274 DEBUG_ENTER (DOUBLE_UNQUOTED_STRING );
265- while (not token_is (DQ_C )) { next (); }
275+ while (not token_is (DQ_C ))
276+ {
277+ if (token_is (BS_C ))
278+ {
279+ possible_escaped_sequence ();
280+ }
281+ else
282+ {
283+ next ();
284+ }
285+ }
266286 DEBUG_EXIT (DOUBLE_UNQUOTED_STRING );
267287 }
268288
269289 inline void UNQUOTED_KEY ()
270290 {
291+ DEBUG_ENTER (UNQUOTED_KEY );
271292 match (UNQUOTED_KEY_CHAR );
272293 while (token_is (UNQUOTED_KEY_CHAR )) { match (UNQUOTED_KEY_CHAR ); }
294+ DEBUG_EXIT (UNQUOTED_KEY );
273295 }
274296
275297 inline void UNQUOTED_VALUE ()
276298 {
299+ DEBUG_ENTER (UNQUOTED_VALUE );
277300 match (UNQUOTED_VALUE_CHAR );
278301 while (token_is (UNQUOTED_VALUE_CHAR )) { match (UNQUOTED_VALUE_CHAR ); }
302+ DEBUG_EXIT (UNQUOTED_VALUE );
279303 }
280304
281305 inline void UNQUOTED_COMMENT ()
282306 {
307+ DEBUG_ENTER (UNQUOTED_COMMENT );
283308 match (UNQUOTED_COMMENT_CHAR );
284309 while (token_is (UNQUOTED_COMMENT_CHAR )) { match (UNQUOTED_COMMENT_CHAR ); }
310+ DEBUG_EXIT (UNQUOTED_COMMENT );
285311 }
286312
287313 inline void NL ()
@@ -290,6 +316,24 @@ namespace dotenv
290316 match (NL_C );
291317 }
292318
319+ inline void possible_escaped_sequence ()
320+ {
321+ match (BS_C );
322+ for (auto & equivalence: ESCAPED_EQUIVALENCES )
323+ {
324+ if (equivalence.first == token)
325+ {
326+ if (bond and binded != nullptr ) { binded -> pop_back (); }
327+ else if (bond and binded == nullptr ) { throw std::runtime_error (" something weird happened to this pointer" ); }
328+
329+ token = equivalence.second ;
330+ next ();
331+
332+ break ;
333+ }
334+ }
335+ }
336+
293337 inline void eof ()
294338 {
295339 if (not is.eof ()) { syntax_err (); }
@@ -382,18 +426,20 @@ namespace dotenv
382426
383427 private:
384428
385- static const char CS_C = ' #' ;
386- static const char EQ_C = ' =' ;
387- static const char SP_C = ' ' ;
388- static const char SQ_C = ' \' ' ;
389- static const char DQ_C = ' \" ' ;
390- static const char TB_C = ' \t ' ;
391- static const char NL_C = ' \n ' ;
392- static const char CR_C = ' \r ' ;
429+ static const char CS_C = ' #' ; // Comment (sharp)
430+ static const char EQ_C = ' =' ; // Equal sign
431+ static const char SP_C = ' ' ; // Space
432+ static const char SQ_C = ' \' ' ; // Single quote
433+ static const char DQ_C = ' \" ' ; // Double quote
434+ static const char TB_C = ' \t ' ; // Tabulator
435+ static const char NL_C = ' \n ' ; // Newline
436+ static const char CR_C = ' \r ' ; // Carriage return
437+ static const char BS_C = ' \\ ' ; // Backslash
393438 static const container SP ;
394439 static const container UNQUOTED_KEY_CHAR ;
395440 static const container UNQUOTED_VALUE_CHAR ;
396441 static const container UNQUOTED_COMMENT_CHAR ;
442+ static const std::vector<std::pair<char , char >> ESCAPED_EQUIVALENCES ;
397443
398444 };
399445
@@ -440,6 +486,21 @@ namespace dotenv
440486 CR_C
441487 };
442488
489+ const std::vector<std::pair<char , char >> parser::ESCAPED_EQUIVALENCES
490+ {
491+ { ' ?' , ' ?' },
492+ { ' \' ' , ' \' ' },
493+ { ' "' , ' "' },
494+ { ' \\ ' , ' \\ ' },
495+ { ' a' , ' \a ' },
496+ { ' b' , ' \b ' },
497+ { ' f' , ' \f ' },
498+ { ' n' , ' \n ' },
499+ { ' r' , ' \r ' },
500+ { ' t' , ' \t ' },
501+ { ' v' , ' \v ' }
502+ };
503+
443504 class dotenv
444505 {
445506 private:
0 commit comments