From 748e3668a8baee4c1b20c8e65b719f8bb886cf4f Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Mon, 20 Apr 2020 19:47:28 +0200 Subject: [PATCH] Support block comments --- src/sfizz/parser/Parser.cpp | 69 ++++++++++++++++++++++++++++++------- src/sfizz/parser/Parser.h | 4 +-- tests/DemoParser.cpp | 11 ++++++ 3 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/sfizz/parser/Parser.cpp b/src/sfizz/parser/Parser.cpp index eb3c496d..800d0379 100644 --- a/src/sfizz/parser/Parser.cpp +++ b/src/sfizz/parser/Parser.cpp @@ -113,7 +113,7 @@ void Parser::processTopLevel() while (!_included.empty()) { Reader& reader = *_included.back(); - while (reader.skipChars(" \t\r\n") || skipComment(reader)); + while (reader.skipChars(" \t\r\n") || skipComment()); switch (reader.peekChar()) { case Reader::kEof: @@ -348,32 +348,70 @@ void Parser::flushCurrentHeader() _currentOpcodes.clear(); } -bool Parser::hasComment(Reader& reader) +int Parser::hasComment(Reader& reader) { if (reader.peekChar() != '/') return false; reader.getChar(); - if (reader.peekChar() != '/') { - reader.putBackChar('/'); - return false; + + int ret = 0; + + switch (reader.peekChar()) { + case '/': + ret = 1; + break; + case '*': + ret = 2; + break; } - return true; + reader.putBackChar('/'); + return ret; } -size_t Parser::skipComment(Reader& reader) +size_t Parser::skipComment() { - if (!hasComment(reader)) + Reader& reader = *_included.back(); + + int commentType = hasComment(reader); + if (!commentType) return 0; + SourceLocation start = reader.location(); + size_t count = 2; reader.getChar(); reader.getChar(); - int c; - while ((c = reader.getChar()) != Reader::kEof && c != '\r' && c != '\n') - ++count; + bool terminated = false; + + switch (commentType) { + case 1: // line comment + { + int c; + while ((c = reader.getChar()) != Reader::kEof && c != '\r' && c != '\n') + ++count; + terminated = true; + } + break; + case 2: // block comment + { + int c1 = 0; + int c2 = reader.getChar(); + while (!terminated && c2 != Reader::kEof) { + c1 = c2; + c2 = reader.getChar(); + terminated = c1 == '*' && c2 == '/'; + } + } + break; + } + + if (!terminated) { + SourceLocation end = reader.location(); + emitError({ start, end }, "Unterminated block comment."); + } return count; } @@ -387,7 +425,14 @@ void Parser::trimRight(std::string& text) size_t Parser::extractToEol(Reader& reader, std::string* dst) { return reader.extractWhile(dst, [&reader](char c) { - return c != '\r' && c != '\n' && !(c == '/' && reader.peekChar() == '/'); + if (c == '\r' || c == '\n') + return false; + if (c == '/') { + int c2 = reader.peekChar(); + if (c2 == '/' || c2 == '*') // stop at comment + return false; + } + return true; }); } diff --git a/src/sfizz/parser/Parser.h b/src/sfizz/parser/Parser.h index 4f6a071d..88424d1d 100644 --- a/src/sfizz/parser/Parser.h +++ b/src/sfizz/parser/Parser.h @@ -84,8 +84,8 @@ private: void flushCurrentHeader(); // helpers - static bool hasComment(Reader& reader); - static size_t skipComment(Reader& reader); + static int hasComment(Reader& reader); // 0=None 1=Line 2=Block + size_t skipComment(); static void trimRight(std::string& text); static size_t extractToEol(Reader& reader, std::string* dst); // ignores comment std::string expandDollarVars(const SourceRange& range, absl::string_view src); diff --git a/tests/DemoParser.cpp b/tests/DemoParser.cpp index f7931694..424dccee 100644 --- a/tests/DemoParser.cpp +++ b/tests/DemoParser.cpp @@ -38,6 +38,11 @@ static const char defaultSfzText[] = R"SFZ( // This is a SFZ test file with many problems. // //----------------------------------------------------------------------------// +/* + * This is a block comment. Not all the SFZ players accept it. + * It can span over multiple lines. +*/ + // opcode without header not_in_header=on // warning @@ -75,6 +80,12 @@ abcdef=$tata // opcode name which expands to invalid identifier $titi=1 + +volume=10 /* +block comments at the end of line +*/ + +/* unterminated block comment )SFZ"; void Application::init()