Need to improve syntax error diagnostic message for Spirit grammar
"Mccall, Kurt E. \(MSFC-EV41\) via Spirit-general" <[email protected]> Fri, 18 Sep 2020 12:37:23 +0000
| Newsgroups | gmane.comp.parsers.spirit.general |
|---|---|
| Message-ID | <SA9PR09MB58084B95914B581044CAFB64C63F0@SA9PR09MB5808.namprd09.prod.outlook.com> |
--===============5593575874508214048==
Content-Language: en-US
Content-Type: multipart/alternative;
boundary="_000_SA9PR09MB58084B95914B581044CAFB64C63F0SA9PR09MB5808namp_"
--_000_SA9PR09MB58084B95914B581044CAFB64C63F0SA9PR09MB5808namp_
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
For a particular syntax error in my input string, Spirit is pointing to a l=
ocation in the string well
before the actual location of the error. The input string is
std::string input("events : \n \
liftoff =3D \"time > 0.25\", \n \
liftoff2 =3D \"time > 0.35; \n"); // this line is missing the sec=
ond double quote (after 0.35)
The error message that is produced is
Error: line 2: invalid syntax: missing semicolon in:
events : \n liftoff =3D "time > 0.25", \n liftoff2 =3D "=
time > 0.35; \n
--------------------------------------------------^
--------------------------------------------------------------------------^=
Here is where I wish the error message
would point, at the location of the quoted string that is missing the trail=
ing double quote.
Here is the relevant section of my grammar. The diagnostics<N> objects d1=
, d2 and d3, which produce
the error message are based on code at http://boost-spirit.com/home/2011/02=
/28/dispatching-on-expectation-point-failures/
They use the "where" parameter " _3" that points to the location of the err=
or.
The rule that contains the quoted string parser "quoted_str" is named "even=
t". I hope I have included enough
information for someone to suggest how I could rewrite the rules to produce=
an improved error message. I am
using Boost 1.70.
// ************************************************************************=
*
template <typename Iterator, typename Skipper>
class Grammar3 : boost::spirit::qi::grammar<Iterator, Skipper>
{
public:
typedef boost::spirit::qi::rule<Iterator, Skipper> rule_nil_T;
typedef boost::spirit::qi::rule<Iterator, string()> rule_str_T;
diagnostics<20> d1, d2, d3;
boost::phoenix::function<error_handler_impl> error_handler;
rule_str_T ident, quoted_str;
rule_nil_T comma, colon, semi, equals, keyword_events;
rule_nil_T start, event_list, event;
Grammar3(void) : Grammar3::base_type{start}
{
ident %=3D lexeme [ qi::raw [ (qi::alpha | '_') >> *(qi::alnum | '=
_') ] ];
quoted_str %=3D lexeme [ '"' >> +(char_ - '"') >> '"' ];
comma =3D lit(','); comma.name(",");
colon =3D lit(':'); colon.name(":");
semi =3D lit(';'); semi.name(";");
equals =3D lit('=3D'); equals.name("=3D");
keyword_events =3D lit("events"); keyword_events.name("events");
start
=3D eps
> keyword_events
> colon
> event_list
> semi
;
d1.add("keyword_events", "events keyword");
d1.add(":", "colon");
d1.add("event_list", "event list");
d1.add(";", "semicolon");
on_error<fail>(start,
error_handler(ref(d1), _1, _2, _3, _4));
start.name("start");
event_list
=3D eps
> event % comma
;
d2.add("event", "event definition");
d2.add(",", "comma in event list");
on_error<fail>(event_list,
error_handler(ref(d2), _1, _2, _3, _4));
event_list.name("event_list");
event
=3D eps
> ident
> equals
> quoted_str
;
d3.add("ident", "identifier");
d3.add("=3D", "equals sign");
d3.add("quoted_str", "quoted C-expression string");
on_error<fail>(event,
error_handler(ref(d3), _1, _2, _3, _4));
event.name("event");
}
// ************************************************************************=
*****
Just for good measure, here is the calling code:
/**************************************************************************=
****
int main(int argc, char **argv)
{
boost::locale::generator gen;
std::locale loc =3D gen("en_US.UTF-8");
cout.imbue(loc);
typedef boost::spirit::line_pos_iterator<std::string::iterator> Positio=
n_Itr_T;
Grammar3<Position_Itr_T, boost::spirit::ascii::space_type> g;
string input("events : \n \
liftoff =3D \"time > 0.25\", \n \
liftoff2 =3D \"time > 0.35; \n"); // SYNTAX ERROR: this line is m=
issing the second double quote
Position_Itr_T begin(input.begin());
Position_Itr_T end(input.end());
g.parseInputFile(begin, end);
return 0;
};
// ************************************************************************=
****
--_000_SA9PR09MB58084B95914B581044CAFB64C63F0SA9PR09MB5808namp_
Content-Type: text/html; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
<html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas-micr=
osoft-com:office:office" xmlns:w=3D"urn:schemas-microsoft-com:office:word" =
xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml" xmlns=3D"http:=
//www.w3.org/TR/REC-html40">
<head>
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dus-ascii"=
>
<meta name=3D"Generator" content=3D"Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:#0563C1;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:#954F72;
text-decoration:underline;}
span.EmailStyle17
{mso-style-type:personal-compose;
font-family:"Calibri",sans-serif;
color:windowtext;}
.MsoChpDefault
{mso-style-type:export-only;
font-family:"Calibri",sans-serif;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext=3D"edit">
<o:idmap v:ext=3D"edit" data=3D"1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang=3D"EN-US" link=3D"#0563C1" vlink=3D"#954F72">
<div class=3D"WordSection1">
<p class=3D"MsoNormal">For a particular syntax error in my input string, Sp=
irit is pointing to a location in the string well<o:p></o:p></p>
<p class=3D"MsoNormal">before the actual location of the error. =
The input string is
<o:p></o:p></p>
<p class=3D"MsoNormal"><o:p> </o:p></p>
<p class=3D"MsoNormal">std::string input("events : \n \<o:p></o:p></p>
<p class=3D"MsoNormal"> liftoff&n=
bsp; =3D \"time > 0.25\", \n \<o:p></o:p></p>
<p class=3D"MsoNormal"> liftoff2&=
nbsp; =3D \"time > 0.35; \n"); // this line is missing t=
he second double quote (after 0.35)<o:p></o:p></p>
<p class=3D"MsoNormal"><o:p> </o:p></p>
<p class=3D"MsoNormal">The error message that is produced is<o:p></o:p></p>
<p class=3D"MsoNormal"><o:p> </o:p></p>
<p class=3D"MsoNormal">Error: line 2: invalid syntax: missing <b>semicolon<=
/b> in:<o:p></o:p></p>
<p class=3D"MsoNormal">events : \n  =
; liftoff =3D "time > 0.25", \n &=
nbsp; liftoff2 =3D "time > 0.35=
; \n<o:p></o:p></p>
<p class=3D"MsoNormal">--------------------------------------------------^<=
o:p></o:p></p>
<p class=3D"MsoNormal"><o:p> </o:p></p>
<p class=3D"MsoNormal">----------------------------------------------------=
----------------------^ Here is where I wish the error message
<o:p></o:p></p>
<p class=3D"MsoNormal">would point, at the location of the quoted string th=
at is missing the trailing double quote.<o:p></o:p></p>
<p class=3D"MsoNormal"><o:p> </o:p></p>
<p class=3D"MsoNormal">Here is the relevant section of my grammar. &nb=
sp; The diagnostics<N> objects d1, d2 and d3, which produce
<o:p></o:p></p>
<p class=3D"MsoNormal">the error message are based on code at <a href=3D"ht=
tp://boost-spirit.com/home/2011/02/28/dispatching-on-expectation-point-fail=
ures/">
http://boost-spirit.com/home/2011/02/28/dispatching-on-expectation-point-fa=
ilures/</a><o:p></o:p></p>
<p class=3D"MsoNormal">They use the “where” parameter “ _=
3” that points to the location of the error.<o:p></o:p></p>
<p class=3D"MsoNormal"><o:p> </o:p></p>
<p class=3D"MsoNormal">The rule that contains the quoted string parser R=
20;quoted_str” is named “event”. I hope I hav=
e included enough<o:p></o:p></p>
<p class=3D"MsoNormal">information for someone to suggest how I could rewri=
te the rules to produce an improved error message. I am
<o:p></o:p></p>
<p class=3D"MsoNormal">using Boost 1.70.<o:p></o:p></p>
<p class=3D"MsoNormal"><o:p> </o:p></p>
<p class=3D"MsoNormal"><b>// **********************************************=
***************************<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b>template <typename Iterator, typename Skipper&=
gt;<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> class Grammar3 : boost::spirit=
::qi::grammar<Iterator, Skipper><o:p></o:p></b></p>
<p class=3D"MsoNormal"><b>{<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> public:<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> typedef boost::spirit::qi::rul=
e<Iterator, Skipper> rule_nil_T;<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> typedef boost::spirit::qi::rul=
e<Iterator, string()> rule_str_T;<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> diagnostics<20> d1, d2, =
d3;<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> boost::phoenix::function<err=
or_handler_impl> error_handler;<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> rule_str_T ident, quoted_str;<=
o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> rule_nil_T comma, colon, semi,=
equals, keyword_events;<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> rule_nil_T start, event_list, =
event;<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> Grammar3(void) : Grammar3::bas=
e_type{start}<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> {<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> ident&=
nbsp; %=3D lexeme [ qi::raw [ (qi::alpha | '_') >> *(qi::alnum | '_')=
] ];<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> quoted=
_str %=3D lexeme [ '"' >> +(char_ - '&qu=
ot;') >> '"' ];<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> comma =
=3D lit(','); comma.name(",");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> colon =
=3D lit(':'); colon.name(":");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> semi =
=3D lit(';'); semi.name(";");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> equals=
=3D lit('=3D'); equals.name("=3D");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> keywor=
d_events =3D lit("events"); keyword_events.name=
("events");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> start<=
o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; =3D eps<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; > keyword_events<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; > colon<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; > event_list<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; > semi<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> ;<o:p>=
</o:p></b></p>
<p class=3D"MsoNormal"><b> d1.add=
("keyword_events", "events keyword");<o:p></o:p></b></p=
>
<p class=3D"MsoNormal"><b> d1.add=
(":", "colon");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> d1.add=
("event_list", "event list");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> d1.add=
(";", "semicolon");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> on_err=
or<fail>(start,<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; error_handler(ref(d1), _1, _2, _3, _4));<o:p></o:p></b></=
p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> start.=
name("start");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> event_=
list<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; =3D eps<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; > event % comma<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; ;<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> d2.add=
("event", "event definition");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> d2.add=
(",", "comma in event list");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> on_err=
or<fail>(event_list,<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; error_handler(ref(d2), _1, _2, _3, _4));<o:p></o:p></b></=
p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> event_=
list.name("event_list");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> event<=
o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; =3D eps<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; > ident<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; > equals<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; > quoted_str <o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; ;<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> d3.add=
("ident", "identifier");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> d3.add=
("=3D", "equals sign");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> d3.add=
("quoted_str", "quoted C-expression string");<o:p></o:p=
></b></p>
<p class=3D"MsoNormal"><b> on_err=
or<fail>(event,<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> &=
nbsp; error_handler(ref(d3), _1, _2, _3, _4));<o:p></o:p></b></=
p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> event.=
name("event");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> }<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b>// **********************************************=
*******************************<o:p></o:p></b></p>
<p class=3D"MsoNormal"><o:p> </o:p></p>
<p class=3D"MsoNormal">Just for good measure, here is the calling code:<o:p=
></o:p></p>
<p class=3D"MsoNormal"><o:p> </o:p></p>
<p class=3D"MsoNormal"><o:p> </o:p></p>
<p class=3D"MsoNormal"><o:p> </o:p></p>
<p class=3D"MsoNormal"><b>/************************************************=
******************************<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b>int main(int argc, char **argv)<o:p></o:p></b></p=
>
<p class=3D"MsoNormal"><b>{<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> boost::locale::generator gen;<=
o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> std::locale loc =3D gen("=
en_US.UTF-8");<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> cout.imbue(loc);<o:p></o:p></b=
></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> typedef boost::spirit::line_po=
s_iterator<std::string::iterator> Position_Itr_T;<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> Grammar3<Position_Itr_T, bo=
ost::spirit::ascii::space_type> g;<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> string input("events : \n=
\<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> liftof=
f =3D \"time > 0.25\", \n \<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> liftof=
f2 =3D \"time > 0.35; \n"); // SYNTAX ERROR: this =
line is missing the second double quote<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> Position_Itr_T begin(input.beg=
in());<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b> Position_Itr_T end(input.end()=
);<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> g.parseInputFile(begin, end);<=
o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b> return 0;<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b>};<o:p></o:p></b></p>
<p class=3D"MsoNormal"><b><o:p> </o:p></b></p>
<p class=3D"MsoNormal"><b>// **********************************************=
******************************<o:p></o:p></b></p>
<p class=3D"MsoNormal"><o:p> </o:p></p>
</div>
</body>
</html>
--_000_SA9PR09MB58084B95914B581044CAFB64C63F0SA9PR09MB5808namp_--
--===============5593575874508214048==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
--===============5593575874508214048==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
Spirit-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/spirit-general
--===============5593575874508214048==--