/* * This program source code file is part of KiCad, a free EDA CAD application. * * Copyright (C) 2022 Mikolaj Wielgus * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 3 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, you may find one here: * https://www.gnu.org/licenses/gpl-3.0.html * or you may search the http://www.gnu.org website for the version 3 license, * or you may write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifndef SPICE_GRAMMAR_H #define SPICE_GRAMMAR_H #include namespace SPICE_GRAMMAR { using namespace SIM_VALUE_GRAMMAR; struct garbage : plus> {}; struct leaders : plus> {}; struct trailers : plus> {}; // NOTE: In Ngspice, a '$' opening a comment must be preceded by ' ', ',', or '\t'. We don't // implement that here - this may cause problems in the future. // Ngspice supports '//' for comments. struct eolfCommentStart : sor, string<'/', '/'>> {}; struct eolfComment : seq> {}; struct commentLine : seq, one<'*'>, until> {}; struct newline : seq, not_at>> {}; struct backslashContinuation : seq, opt, eolf> {}; struct commentBackslashContinuation : seq, not_at, opt, eolf>, any>, string<'\\', '\\'>, opt, eolf>> {}; struct plusContinuation : seq, star, opt, one<'+'>> {}; struct continuation : seq, sor, opt> {}; struct sep : sor, garbage> {}; struct modelName : plus, any> {}; struct dotModelType : plus {}; // Ngspice has some heuristic logic to allow + and - in tokens. We replicate that here. struct tokenStart : seq>, opt>>, one<'e', 'E'>, opt>>>> {}; struct token : seq, not_at, not_one<' ', '\t', '=', '(', ')', ',', '+', '-', '*', '/', '^', ';'>>> {}; struct param : token {}; struct paramValue : token {}; struct paramValuePair : seq {}; struct paramValuePairs : list {}; struct dotModel : seq, if_must, opt, newline>> {}; struct dotSubcktPinName : seq, plus, any>> {}; struct dotSubcktPinSequence : list {}; struct dotSubcktParams : seq {}; struct dotSubcktEnd : seq> {}; struct spiceUnit; struct dotSubckt : seq, if_must, opt, opt, newline, until>> {}; struct modelUnit : sor {}; // Intentionally no if_must<>. struct dotControl : seq, TAO_PEGTL_ISTRING( ".control" ), until, until> {}; struct dotTitleTitle : star, any> {}; // Intentionally no if_must<>. struct dotTitle : seq, TAO_PEGTL_ISTRING( ".title" ), sep, dotTitleTitle, newline> {}; struct dotIncludePathWithoutQuotes : star> {}; struct dotIncludePathWithoutApostrophes : star> {}; struct dotIncludePath : star, any> {}; // Intentionally no if_must<>. struct dotInclude : seq, TAO_PEGTL_ISTRING( ".include" ), sep, sor, dotIncludePathWithoutQuotes, one<'\"'>>, seq, dotIncludePathWithoutApostrophes, one<'\''>>, dotIncludePath>, opt, newline> {}; // Intentionally no if_must<>. struct dotLine : seq, one<'.'>, until> {}; // Intentionally no if_must<>. struct kLine : seq, one<'K'>, until, one<'L'>, until, one<'L'>, until, until> {}; struct unknownLine : seq, any>, until> {}; struct spiceUnit : sor {}; struct spiceUnitGrammar : spiceUnit {}; struct spiceSource : star {}; struct spiceSourceNothrow : star> {}; struct spiceSourceGrammar : spiceSource {}; template inline constexpr const char* errorMessage = nullptr; template <> inline constexpr auto errorMessage = "expected newline not followed by a line continuation"; template <> inline constexpr auto errorMessage = "expected token separator (typ. one or more whitespace, parenthesis, '=', ',', line continuation)"; template <> inline constexpr auto errorMessage> = ""; template <> inline constexpr auto errorMessage = "expected model name"; template <> inline constexpr auto errorMessage = "expected model type"; template <> inline constexpr auto errorMessage> = ""; template <> inline constexpr auto errorMessage> = ""; template <> inline constexpr auto errorMessage> = ""; template <> inline constexpr auto errorMessage> = "expected a (possibly empty) sequence of Spice lines followed by an .ends line"; // We create a custom PEGTL control to modify the parser error messages. struct error { template static constexpr bool raise_on_failure = false; template static constexpr auto message = errorMessage; }; template using control = must_if::control; } #endif // SPICE_GRAMMAR_H