From 950300005baf8db466cfd464d19a51af960f4ac3 Mon Sep 17 00:00:00 2001
From: Ben Cumming <bcumming@cscs.ch>
Date: Tue, 16 Feb 2021 09:21:03 +0100
Subject: [PATCH] Support windows new line in s-expression strings #1382

* add support for windows new line in s-expression parser
* make small optimization that reduces time to read large strings by 20%
* fix another small bug with handling error states.

Fixes #1381
---
 arbor/s_expr.cpp | 32 +++++++++++++++++++++-----------
 arbor/s_expr.hpp |  2 +-
 2 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/arbor/s_expr.cpp b/arbor/s_expr.cpp
index b5c9073e..b16b730b 100644
--- a/arbor/s_expr.cpp
+++ b/arbor/s_expr.cpp
@@ -127,10 +127,13 @@ private:
 
         while (!empty()) {
             switch (*stream_) {
-                // end of file
-                case 0      :       // end of string
-                    token_ = {loc(), tok::eof, "eof"s};
-                    return;
+                // white space
+                case ' '    :
+                case '\t'   :
+                case '\v'   :
+                case '\f'   :
+                    ++stream_;
+                    continue;   // skip to next character
 
                 // new line
                 case '\n'   :
@@ -139,13 +142,19 @@ private:
                     line_start_ = stream_;
                     continue;
 
-                // white space
-                case ' '    :
-                case '\t'   :
-                case '\v'   :
-                case '\f'   :
-                    character();
-                    continue;   // skip to next character
+                // carriage return (windows new line)
+                case '\r'   :
+                    ++stream_;
+                    if(*stream_ != '\n') {
+                        token_ = {loc(), tok::error, "expected new line after cariage return (bad line ending)"};
+                        return;
+                    }
+                    continue; // catch the new line on the next pass
+
+                // end of file
+                case 0      :
+                    token_ = {loc(), tok::eof, "eof"s};
+                    return;
 
                 case ';':
                     eat_comment();
@@ -172,6 +181,7 @@ private:
                     {
                         if (empty()) {
                             token_ = {loc(), tok::error, "Unexpected end of input."};
+                            return;
                         }
                         char c = stream_.peek(1);
                         if (std::isdigit(c) or c=='.') {
diff --git a/arbor/s_expr.hpp b/arbor/s_expr.hpp
index edd1a7fa..6e93aee9 100644
--- a/arbor/s_expr.hpp
+++ b/arbor/s_expr.hpp
@@ -350,7 +350,7 @@ src_location location(const s_expr& l);
 
 s_expr parse_s_expr(const std::string& line);
 s_expr parse_s_expr(transmogrifier begin);
-std::vector<s_expr> parse_multi(transmogrifier begin);
+std::vector<s_expr> parse_multi_s_expr(transmogrifier begin);
 
 } // namespace arb
 
-- 
GitLab