mirror of
https://github.com/verilator/verilator.git
synced 2025-07-31 07:56:10 +00:00
Support triple-quote blocks.
This commit is contained in:
parent
cd8528e83b
commit
749aab0a56
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
|
@ -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(); }
|
||||
|
5
test_regress/t/t_display_qqq.out
Normal file
5
test_regress/t/t_display_qqq.out
Normal file
@ -0,0 +1,5 @@
|
||||
First "quoted"
|
||||
second
|
||||
third
|
||||
fourth
|
||||
*-* All Finished *-*
|
23
test_regress/t/t_display_qqq.pl
Executable file
23
test_regress/t/t_display_qqq.pl
Executable 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;
|
17
test_regress/t/t_display_qqq.v
Normal file
17
test_regress/t/t_display_qqq.v
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
2
test_regress/t/t_preproc_eof6_bad.out
Normal file
2
test_regress/t/t_preproc_eof6_bad.out
Normal file
@ -0,0 +1,2 @@
|
||||
%Error: t/t_preproc_eof6_bad.v:10:1: EOF in unterminated """ string
|
||||
%Error: Exiting due to
|
19
test_regress/t/t_preproc_eof6_bad.pl
Executable file
19
test_regress/t/t_preproc_eof6_bad.pl
Executable 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;
|
7
test_regress/t/t_preproc_eof6_bad.v
Normal file
7
test_regress/t/t_preproc_eof6_bad.v
Normal 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
|
Loading…
Reference in New Issue
Block a user