Support triple-quote blocks.

This commit is contained in:
Wilson Snyder 2022-11-17 20:37:51 -05:00
parent cd8528e83b
commit 749aab0a56
13 changed files with 167 additions and 13 deletions

View File

@ -25,6 +25,12 @@ or "`ifdef`"'s may break other tools.
This will report an error when encountered, like C++'s #error.
.. option:: """ [string] """
A triple-quoted block specifies a string which may include newlines and
single quotes. This extension is experimental and may be removed
without deprecation.
.. option:: $c([string], ...);
The string will be embedded directly in the output C++ code at the point

View File

@ -298,7 +298,7 @@ string V3ParseGrammar::deQuote(FileLine* fileline, string text) {
} else if (*cp == '\\') {
quoted = true;
octal_digits = 0;
} else if (*cp != '"') {
} else {
newtext += *cp;
}
}

View File

@ -65,23 +65,24 @@ static void appendDefValue(const char* t, size_t l) { LEXP->appendDefValue(t, l)
/**********************************************************************/
%}
%x CMTONEM
%x ARGMODE
%x CMTBEGM
%x CMTMODE
%x STRMODE
%x DEFFPAR
%x DEFFORM
%x DEFVAL
%x CMTONEM
%x DEFCMT
%x STRIFY
%x ARGMODE
%x DEFFORM
%x DEFFPAR
%x DEFVAL
%x ENCBASE64
%x INCMODE
%x PRTMODE
%x PRAGMA
%x PRAGMAERR
%x PRAGMAPRT
%x PRAGMAPRTERR
%x ENCBASE64
%x PRTMODE
%x QQQMODE
%x STRIFY
%x STRMODE
/* drop: Drop Ctrl-Z - can't pass thru or may EOF the output too soon */
@ -262,6 +263,23 @@ bom [\357\273\277]
yyleng=0; FL_BRK;
} else return VP_STRING; }
/* Pass-through quote-quote-quote */
<INITIAL>{quote}{quote}{quote} { yy_push_state(QQQMODE); yymore(); }
<QQQMODE><<EOF>> { FL_FWDC; linenoInc(); yyerrorf("EOF in unterminated \"\"\" string");
yyleng=0; return VP_EOF_ERROR; }
<QQQMODE>{crnl} { FL_FWDC; linenoInc(); yymore(); }
<QQQMODE>{word} { yymore(); }
<QQQMODE>[^\"\\] { yymore(); }
<QQQMODE>[\\]{crnl} { linenoInc(); yymore(); }
<QQQMODE>[\\]{wsn}+{crnl} { LEXP->warnBackslashSpace(); yyless(1); }
<QQQMODE>[\\]. { yymore(); }
<QQQMODE>. { yymore(); }
<QQQMODE>{quote}{quote}{quote} { FL_FWDC; yy_pop_state();
if (LEXP->m_parenLevel || LEXP->m_defQuote) {
LEXP->m_defQuote=false; appendDefValue(yytext, yyleng);
yyleng=0; FL_BRK;
} else return VP_STRING; }
/* Stringification */
<INITIAL>{tickquote} { FL_FWDC; yy_push_state(STRIFY); return VP_STRIFY; }
<STRIFY><<EOF>> { FL_FWDC; linenoInc(); yyerrorf("EOF in unterminated '\"");
@ -319,6 +337,7 @@ bom [\357\273\277]
<DEFFORM>[\\]{wsn}+{crnl} { LEXP->warnBackslashSpace(); yyless(1); }
<DEFFORM>[\\]{crnl} { FL_FWDC; linenoInc(); appendDefValue((char*)"\\\n", 2); FL_BRK; } /* Include return so can maintain output line count */
<DEFFORM>{quote} { LEXP->m_defQuote=true; yy_push_state(STRMODE); yymore(); } /* Legal only in default values */
<DEFFORM>{quote}{quote}{quote} { LEXP->m_defQuote=true; yy_push_state(QQQMODE); yymore(); } /* Legal only in default values */
<DEFFORM>"`\\`\"" { FL_FWDC; appendDefValue(yytext, yyleng); FL_BRK; } /* Maybe illegal, otherwise in default value */
<DEFFORM>{tickquote} { FL_FWDC; appendDefValue(yytext, yyleng); FL_BRK; } /* Maybe illegal, otherwise in default value */
<DEFFORM>[{\[] { FL_FWDC; LEXP->m_formalLevel++; appendDefValue(yytext, yyleng); FL_BRK; }
@ -337,6 +356,7 @@ bom [\357\273\277]
<DEFVAL>[\\]{wsn}+{crnl} { LEXP->warnBackslashSpace(); yyless(1); }
<DEFVAL>[\\]{crnl} { FL_FWDC; linenoInc(); appendDefValue((char*)"\\\n", 2); FL_BRK; } /* Return, AND \ is part of define value */
<DEFVAL>{quote} { LEXP->m_defQuote = true; yy_push_state(STRMODE); yymore(); }
<DEFVAL>{quote}{quote}{quote} { LEXP->m_defQuote = true; yy_push_state(QQQMODE); yymore(); }
<DEFVAL>[^\/\*\n\r\\\"]+ |
<DEFVAL>[\\][^\n\r] |
<DEFVAL>. { FL_FWDC; appendDefValue(yytext, yyleng); FL_BRK; }
@ -364,6 +384,7 @@ bom [\357\273\277]
yyleng = 0; return VP_EOF_ERROR; }
<ARGMODE>{crnl} { FL_FWDC; linenoInc(); yytext=(char*)"\n"; yyleng=1; return VP_WHITE; }
<ARGMODE>{quote} { yy_push_state(STRMODE); yymore(); }
<ARGMODE>{quote}{quote}{quote} { yy_push_state(QQQMODE); yymore(); }
<ARGMODE>"`\\`\"" { FL_FWDC; appendDefValue(yytext, yyleng); FL_BRK; } /* Literal text */
<ARGMODE>{tickquote} { FL_FWDC; yy_push_state(STRIFY); return VP_STRIFY; }
<ARGMODE>[{\[] { FL_FWDC; LEXP->m_parenLevel++; appendDefValue(yytext, yyleng); FL_BRK; }

View File

@ -79,7 +79,7 @@ static double lexParseDouble(FileLine* fl, const char* textp, size_t length) {
%o 25000
%s V95 V01NC V01C V05 S05 S09 S12 S17
%s STRING ATTRMODE TABLE
%s ATTRMODE QQQ STRING TABLE
%s VA5 SAX VLT
%s SYSCHDR SYSCINT SYSCIMP SYSCIMPH SYSCCTOR SYSCDTOR
%s IGNORE
@ -886,6 +886,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
return yaSTRING;
}
\" { yy_push_state(STRING); yymore(); }
\"\"\" { yy_push_state(QQQ); yymore(); }
{vnum} {
/* "# 1'b0" is a delay value so must lex as "#" "1" "'b0" */
if (PARSEP->lexPrevToken()=='#') {
@ -940,6 +941,19 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
<STRING>{word} { yymore(); }
<STRING>. { yymore(); }
/************************************************************************/
/* """ */
<QQQ><<EOF>> { FL; yylval.fl->v3error("EOF in unterminated \"\"\" string");
yyleng = 0; yy_pop_state(); FL_BRK; yyterminate(); }
<QQQ>\\. { yymore(); }
<QQQ>\n { yymore(); }
<QQQ>\"\"\" { yy_pop_state();
FL; yylval.strp = PARSEP->newString(yytext + 3, yyleng - 6);
return yaSTRING; }
<QQQ>\" { yymore(); }
<QQQ>{word} { yymore(); }
<QQQ>. { yymore(); }
/************************************************************************/
/* Attributes */
<ATTRMODE>{crnl} { yymore(); }

View File

@ -0,0 +1,5 @@
First "quoted"
second
third
fourth
*-* All Finished *-*

23
test_regress/t/t_display_qqq.pl Executable file
View File

@ -0,0 +1,23 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
compile(
);
execute(
check_finished => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,17 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2022 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t;
initial begin
$display("""First "quoted"\nsecond\
third
fourth""");
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -1005,6 +1005,20 @@ endmodule
`line 695 "t/t_preproc.v" 0
"""First line with "quoted"\nSecond line\
Third line"""
"""First line
Second line"""
`line 702 "t/t_preproc.v" 0
"""QQQ defform"""
"""QQQ defval"""
`line 707 "t/t_preproc.v" 0
predef 0 0
@ -1026,4 +1040,4 @@ predef 2 2
`line 717 "t/t_preproc.v" 2
`line 729 "t/t_preproc.v" 2

View File

@ -692,6 +692,18 @@ endmodule
`define stringify(text) `"text`"
`stringify(`NOT_DEFINED_STR)
//======================================================================
"""First line with "quoted"\nSecond line\
Third line"""
"""First line
Second line"""
`define QQQ """QQQ defform"""
`define QQQS(x) x
`QQQ
`QQQS("""QQQ defval""")
//======================================================================
// IEEE mandated predefines
`undefineall // undefineall should have no effect on these

View File

@ -1010,6 +1010,20 @@ endmodule
`line 695 "t/t_preproc.v" 0
//======================================================================
"""First line with "quoted"\nSecond line\
Third line"""
"""First line
Second line"""
`line 702 "t/t_preproc.v" 0
"""QQQ defform"""
"""QQQ defval"""
`line 707 "t/t_preproc.v" 0
//======================================================================
// IEEE mandated predefines
// undefineall should have no effect on these
predef 0 0
@ -1031,4 +1045,4 @@ predef 2 2
// After `undefineall above, for testing --dump-defines
`line 717 "t/t_preproc.v" 2
`line 729 "t/t_preproc.v" 2

View File

@ -0,0 +1,2 @@
%Error: t/t_preproc_eof6_bad.v:10:1: EOF in unterminated """ string
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(linter => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,7 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2019 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
"""str