# Rust skeleton for Bison -*- autoconf -*-
# Copyright (C) 2007-2015, 2018-2020 Free Software Foundation, Inc.
# 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, see .
m4_include(b4_skeletonsdir/[rust.m4])
b4_defines_if([b4_complain([%defines does not make sense in Rust])])
m4_define([b4_symbol_no_destructor_assert],
[b4_symbol_if([$1], [has_destructor],
[b4_complain_at(m4_unquote(b4_symbol([$1], [destructor_loc])),
[%destructor does not make sense in Rust])])])
b4_symbol_foreach([b4_symbol_no_destructor_assert])
# Define a macro to encapsulate the parse state variables.
m4_define([b4_define_state],[[
/* Lookahead token kind. */
let mut yychar: i32 = Self::YYEMPTY_;
/* Lookahead symbol kind. */
let mut yytoken = &DYMMY_SYMBOL_KIND;
/* State. */
let mut yyn: i32 = 0;
let mut yylen: usize = 0;
let mut yystate: i32 = 0;
let mut yystack = YYStack::new();
let mut label: i32 = Self::YYNEWSTATE;
/* The location where the error started. */
let mut yyerrloc: YYLoc = YYLoc { begin: 0, end: 0 };
/* Location. */
let mut yylloc: YYLoc = YYLoc { begin: 0, end: 0 };
/* Semantic value of the lookahead. */
let mut yylval: YYValue = YYValue::new_uninitialized();
]])[
]b4_output_begin([b4_parser_file_name])[
]b4_copyright([Skeleton implementation for Bison LALR(1) parsers in Rust],
[2007-2015, 2018-2020])[
]b4_disclaimer[
]b4_percent_define_ifdef([api.package], [package b4_percent_define_get([api.package]);[
]])[
]b4_user_pre_prologue[
]b4_user_post_prologue[
use std::convert::TryInto;
]
b4_percent_code_get([[use]])[
/// A Bison parser, automatically generated from ]m4_bpatsubst(b4_file_name, [^"\(.*\)"$], [\1])[.
#@{derive(Debug)@}
pub struct ]b4_parser_struct[]b4_parser_generic[ {
/// Lexer that is used to get tokens
pub yylexer: Lexer,
// true if verbose error messages are enabled.
#@{allow(dead_code)@}
yy_error_verbose: bool,
// number of errors so far
yynerrs: i32,
yyerrstatus_: i32,
]b4_percent_code_get([[parser_fields]])[
}
#[inline]
fn i32_to_usize(v: i32) -> usize {
v as usize
}
/// Maps token ID into human-readable name
pub fn token_name(id: i32) -> &'static str { /* ' */
let first_token = Lexer::YYerror;
if id > first_token + 1 {
let pos: usize = (id - first_token + 1)
.try_into()
.expect("failed to cast token id into usize, is it negative?");
Lexer::TOKEN_NAMES@{pos@}
} else if id == 0 {
"EOF"
} else {
panic!("token_name fails, {} (first token = {})", id, first_token)
}
}
/// Local alias
type YYLoc = Loc;
impl]b4_parser_generic[ ]b4_parser_struct[]b4_parser_generic[ {]
b4_identification[]
[}]
[
fn make_yylloc(rhs: &YYStack, n: usize) -> YYLoc {
if 0 < n {
YYLoc {
begin: rhs.location_at(n - 1).begin,
end: rhs.location_at(0).end
}
} else {
YYLoc {
begin: rhs.location_at(0).end,
end: rhs.location_at(0).end
}
}
}
]b4_declare_symbol_enum[
const DYMMY_SYMBOL_KIND: SymbolKind = SymbolKind { value: 0 };
impl Lexer {
]b4_token_enums[
// Deprecated, use ]b4_symbol(0, id)[ instead.
#@{allow(dead_code)@}
const EOF: i32 = Self::]b4_symbol(0, id)[;
// Token values
#@{allow(dead_code)@}
pub(crate) const TOKEN_NAMES: &'static @{&'static str@} = &]b4_token_values[;
}
]
[impl]b4_parser_generic[ ]b4_parser_struct[]b4_parser_generic[ {
fn yycdebug(&self, s: &str) {
if ]b4_parser_check_debug[ {
eprintln!("{}", s);
}
}][
}
/// Local alias
type YYValue = ]b4_yystype[;
#[derive(Debug)]
struct YYStackItem {
state: i32,
value: YYValue,
loc: YYLoc,
}
#[derive(Debug)]
pub struct YYStack {
stack: Vec,
}
impl YYStack {
pub(crate) fn new() -> Self {
Self {
stack: Vec::with_capacity(20),
}
}
pub(crate) fn push(&mut self, state: i32, value: YYValue, loc: YYLoc) {
self.stack.push(YYStackItem { state, value, loc });
}
pub(crate) fn pop(&mut self) {
self.stack.pop();
}
pub(crate) fn pop_n(&mut self, num: usize) {
let len = self.stack.len() - num;
self.stack.truncate(len);
}
pub(crate) fn state_at(&self, i: usize) -> i32 {
self.stack[self.len() - 1 - i].state
}
pub(crate) fn location_at(&self, i: usize) -> &YYLoc {
&self.stack[self.len() - 1 - i].loc
}
pub(crate) fn borrow_value_at(&self, i: usize) -> &YYValue {
&self.stack[self.len() - 1 - i].value
}
pub(crate) fn owned_value_at(&mut self, i: usize) -> YYValue {
let len = self.len();
std::mem::take(&mut self.stack[len - 1 - i].value)
}
pub(crate) fn len(&self) -> usize {
self.stack.len()
}
}
impl std::fmt::Display for YYStack {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let states = self.stack.iter().map(|e| e.state.to_string()).collect::>().join(" ");
let values = self.stack.iter().map(|e| format!("{:?}", e.value)).collect::>().join(" ");
f.write_fmt(format_args!("Stack now states = {} / values = {:?} ", states, values))
}
}
impl]b4_parser_generic[ ]b4_parser_struct[]b4_parser_generic[ {
/// Returned by a Bison action in order to stop the parsing process and
/// return success (true).
pub(crate) const YYACCEPT: i32 = 0;
/// Returned by a Bison action in order to stop the parsing process and
/// return failure (false).
pub(crate) const YYABORT: i32 = 1;
/// Returned by a Bison action in order to start error recovery without
/// printing an error message.
pub(crate) const YYERROR: i32 = 2;
/// Internal return codes that are not supported for user semantic
/// actions.
pub(crate) const YYERRLAB: i32 = 3;
pub(crate) const YYNEWSTATE: i32 = 4;
pub(crate) const YYDEFAULT: i32 = 5;
pub(crate) const YYREDUCE: i32 = 6;
pub(crate) const YYERRLAB1: i32 = 7;
#@{allow(dead_code)@}
pub(crate) const YYRETURN: i32 = 8;
/// Whether error recovery is being done. In this state, the parser
/// reads token until it reaches a known state, and then restarts normal
/// operation.
#@{allow(dead_code)@}
pub(crate) fn recovering(&self) -> bool {
self.yyerrstatus_ == 0
}
// Compute post-reduction state.
// yystate: the current state
// yysym: the nonterminal to push on the stack
fn yy_lr_goto_state(&self, yystate: i32, yysym: i32) -> i32 {
let idx = i32_to_usize(yysym - Self::YYNTOKENS_);
let yyr = Self::yypgoto_[idx] + yystate;
if (0..=Self::YYLAST_).contains(&yyr) {
let yyr = i32_to_usize(yyr);
if Self::yycheck_[yyr] == yystate {
return Self::yytable_[yyr];
}
}
Self::yydefgoto_[idx]
}
fn yyaction(&mut self, yyn: i32, yystack: &mut YYStack, yylen: &mut usize) -> Result {
// If YYLEN is nonzero, implement the default value of the action:
// '$$ = $1'. Otherwise, use the top of the stack.
//
// Otherwise, the following line sets YYVAL to garbage.
// This behavior is undocumented and Bison
// users should not rely upon it.
#@{allow(unused_assignments)@}
let mut yyval: YYValue = YYValue::new_uninitialized();
let yyloc: YYLoc = make_yylloc(yystack, *yylen);
self.yy_reduce_print(yyn, yystack);
match yyn {
]b4_user_actions[
_ => {}
}
assert!(
!yyval.is_uninitialized(),
"yyval is Uninitialized in rule at line {}",
Self::yyrline_[i32_to_usize(yyn)],
);
self.yy_symbol_print("-> $$ =", SymbolKind::get(Self::yyr1_[i32_to_usize(yyn)]), &yyval, &yyloc);
yystack.pop_n(*yylen);
*yylen = 0;
/* Shift the result of the reduction. */
let yystate = self.yy_lr_goto_state(yystack.state_at(0), Self::yyr1_[i32_to_usize(yyn)]);
yystack.push(yystate, yyval, yyloc);
Ok(Self::YYNEWSTATE)
}
// Print this symbol on YYOUTPUT.
fn yy_symbol_print(&self, s: &str, yykind: &SymbolKind, yyvalue: &YYValue, yylocation: &YYLoc) {
if ]b4_parser_check_debug[ {
self.yycdebug(
&format!("{}{} {:?} ( {:?}: {:?} )", // " fix highlighting
s,
if yykind.code() < Self::YYNTOKENS_ { " token " } else { " nterm " },
yykind.name(),
yylocation,
yyvalue
)
)
}
}
/// Parses given input. Returns true if the parsing was successful.
#[allow(clippy::manual_range_contains)]
pub fn parse(&mut self) -> bool {
/* @@$. */
let mut yyloc: YYLoc;
]b4_define_state[
self.yycdebug("Starting parse");
self.yyerrstatus_ = 0;
self.yynerrs = 0;
/* Initialize the stack. */
yystack.push(yystate, yylval.clone(), yylloc);
loop {
match label {
// New state. Unlike in the C/C++ skeletons, the state is already
// pushed when we come here.
Self::YYNEWSTATE => {
if ]b4_parser_check_debug[ {
self.yycdebug(&format!("Entering state {}", yystate));
eprintln!("{}", yystack);
}
/* Accept? */
if yystate == Self::YYFINAL_ {
return true;
}
/* Take a decision. First try without lookahead. */
yyn = Self::yypact_[i32_to_usize(yystate)];
if yy_pact_value_is_default(yyn) {
label = Self::YYDEFAULT;
continue;
}
/* Read a lookahead token. */
if yychar == Self::YYEMPTY_ {
self.yycdebug("Reading a token");
let token = self.next_token();
yychar = token.token_type;
yylloc = token.loc;
yylval = YYValue::from_token(token);
}
/* Convert token to internal form. */
yytoken = Self::yytranslate_(yychar);
self.yy_symbol_print("Next token is", yytoken, &yylval, &yylloc);
if yytoken == SymbolKind::get(1) {
// The scanner already issued an error message, process directly
// to error recovery. But do not keep the error token as
// lookahead, it is too special and may lead us to an endless
// loop in error recovery. */
yychar = Lexer::]b4_symbol(2, id)[;
yytoken = SymbolKind::get(2);
yyerrloc = yylloc;
label = Self::YYERRLAB1;
} else {
// If the proper action on seeing token YYTOKEN is to reduce or to
// detect an error, take that action.
yyn += yytoken.code();
if yyn < 0 || Self::YYLAST_ < yyn || Self::yycheck_[i32_to_usize(yyn)] != yytoken.code() {
label = Self::YYDEFAULT;
}
/* <= 0 means reduce or error. */
else {
yyn = Self::yytable_[i32_to_usize(yyn)];
if yyn <= 0 {
if yy_table_value_is_error(yyn) {
label = Self::YYERRLAB;
} else {
yyn = -yyn;
label = Self::YYREDUCE;
}
} else {
/* Shift the lookahead token. */
self.yy_symbol_print("Shifting", yytoken, &yylval, &yylloc);
/* Discard the token being shifted. */
yychar = Self::YYEMPTY_;
/* Count tokens shifted since error; after three, turn off error status. */
if self.yyerrstatus_ > 0 {
self.yyerrstatus_ -= 1;
}
yystate = yyn;
yystack.push(yystate, std::mem::take(&mut yylval), std::mem::take(&mut yylloc));
label = Self::YYNEWSTATE;
}
}
}
continue;
}, // YYNEWSTATE
// yydefault -- do the default action for the current state.
Self::YYDEFAULT => {
yyn = Self::yydefact_[i32_to_usize(yystate)];
if yyn == 0 {
label = Self::YYERRLAB;
} else {
label = Self::YYREDUCE;
}
continue;
} // YYDEFAULT
// yyreduce -- Do a reduction.
Self::YYREDUCE => {
yylen = i32_to_usize(Self::yyr2_[i32_to_usize(yyn)]);
label = match self.yyaction(yyn, &mut yystack, &mut yylen) {
Ok(label) => label,
Err(_) => Self::YYERROR
};
yystate = yystack.state_at(0);
continue;
}, // YYREDUCE
// yyerrlab -- here on detecting error
Self::YYERRLAB => {
/* If not already recovering from an error, report this error. */
if self.yyerrstatus_ == 0 {
self.yynerrs += 1;
if yychar == Self::YYEMPTY_ {
yytoken = &DYMMY_SYMBOL_KIND;
}
self.report_syntax_error(&yystack, yytoken, yylloc);
}
yyerrloc = yylloc;
if self.yyerrstatus_ == 3 {
// If just tried and failed to reuse lookahead token after an error, discard it.
if yychar <= Lexer::]b4_symbol(0, id)[ {
/* Return failure if at end of input. */
if yychar == Lexer::]b4_symbol(0, id)[ {
return false;
}
}
else {
yychar = Self::YYEMPTY_;
}
}
// Else will try to reuse lookahead token after shifting the error token.
label = Self::YYERRLAB1;
continue;
}, // YYERRLAB
// errorlab -- error raised explicitly by YYERROR.
Self::YYERROR => {
/* Do not reclaim the symbols of the rule which action triggered
this YYERROR. */
yystack.pop_n(yylen);
yylen = 0;
yystate = yystack.state_at(0);
label = Self::YYERRLAB1;
continue;
}, // YYERROR
// yyerrlab1 -- common code for both syntax error and YYERROR.
Self::YYERRLAB1 => {
self.yyerrstatus_ = 3; /* Each real token shifted decrements this. */
// Pop stack until we find a state that shifts the error token.
loop {
yyn = Self::yypact_[i32_to_usize(yystate)];
if !yy_pact_value_is_default(yyn) {
yyn += SymbolKind { value: SymbolKind::S_YYerror }.code();
if (0..=Self::YYLAST_).contains(&yyn) {
let yyn_usize = i32_to_usize(yyn);
if Self::yycheck_[yyn_usize] == SymbolKind::S_YYerror {
yyn = Self::yytable_[yyn_usize];
if 0 < yyn {
break;
}
}
}
}
// Pop the current state because it cannot handle the error token.
if yystack.len() == 1 {
return false;
}
yyerrloc = *yystack.location_at(0);
yystack.pop();
yystate = yystack.state_at(0);
if ]b4_parser_check_debug[ {
eprintln!("{}", yystack);
}
}
if label == Self::YYABORT {
/* Leave the switch. */
continue;
}
/* Muck with the stack to setup for yylloc. */
yystack.push(0, YYValue::new_uninitialized(), yylloc);
yystack.push(0, YYValue::new_uninitialized(), yyerrloc);
yyloc = make_yylloc(&yystack, 2);
yystack.pop_n(2);
/* Shift the error token. */
self.yy_symbol_print("Shifting", SymbolKind::get(Self::yystos_[i32_to_usize(yyn)]), &yylval, &yyloc);
yystate = yyn;
yystack.push(yyn, yylval.clone(), yyloc);
label = Self::YYNEWSTATE;
continue;
}, // YYERRLAB1
// Accept
Self::YYACCEPT => {
return true;
}
// Abort.
Self::YYABORT => {
return false;
},
_ => {
panic!("internal bison error: unknown label {}", label);
}
}
}
}
}
// Whether the given `yypact_` value indicates a defaulted state.
fn yy_pact_value_is_default(yyvalue: i32) -> bool {
yyvalue == YYPACT_NINF_
}
// Whether the given `yytable_`
// value indicates a syntax error.
// yyvalue: the value to check
fn yy_table_value_is_error(yyvalue: i32) -> bool {
yyvalue == YYTABLE_NINF_
}
const YYPACT_NINF_: ]b4_int_type_for([b4_pact])[ = ]b4_pact_ninf[;
const YYTABLE_NINF_: ]b4_int_type_for([b4_table])[ = ]b4_table_ninf[;
impl]b4_parser_generic[ ]b4_parser_struct[]b4_parser_generic[ {
]b4_parser_tables_define[
]b4_integral_parser_table_define([rline], [b4_rline],
[[YYRLINE[YYN] -- Source line where rule number YYN was defined.]])[
][
// Report on the debug stream that the rule yyrule is going to be reduced.
fn yy_reduce_print(&self, yyrule: i32, yystack: &YYStack) {
if !(]b4_parser_check_debug[) {
return;
}
let yylno = Self::yyrline_[i32_to_usize(yyrule)];
let yynrhs = Self::yyr2_[i32_to_usize(yyrule)];
// Print the symbols being reduced, and their result.
self.yycdebug(&format!("Reducing stack by rule {} (line {}):", /* " fix */ yyrule - 1, yylno));
// The symbols being reduced.
for yyi in 0..yynrhs {
let state: usize = i32_to_usize(yystack.state_at(i32_to_usize(yynrhs - (yyi + 1))));
self.yy_symbol_print(
&format!(" ${} =", yyi + 1),
SymbolKind::get(Self::yystos_[state]),
yystack.borrow_value_at(i32_to_usize(yynrhs - (yyi + 1))),
yystack.location_at(i32_to_usize(yynrhs - (yyi + 1)))
);
}
}][
/* YYTRANSLATE_(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM
as returned by yylex, with out-of-bounds checking. */
fn yytranslate_(t: i32) -> &'static SymbolKind
]b4_api_token_raw_if(dnl
[[ {
return SymbolKind::get(t);
}
]],
[[ {
// Last valid token kind.
let code_max: i32 = ]b4_code_max[;
if t <= 0 {
SymbolKind::get(0)
} else if t <= code_max {
let t = i32_to_usize(t);
SymbolKind::get(Self::yytranslate_table_[t])
} else {
SymbolKind::get(2)
}
}
]b4_integral_parser_table_define([translate_table], [b4_translate])[
]])[
const YYLAST_: i32 = ]b4_last[;
const YYEMPTY_: i32 = -2;
const YYFINAL_: i32 = ]b4_final_state_number[;
const YYNTOKENS_: i32 = ]b4_tokens_number[;
]b4_locations_if([])[
]b4_parse_trace_if([])[
}
]b4_percent_code_get[
]b4_percent_code_get([[epilogue]])[]dnl
b4_epilogue[]dnl
b4_output_end