Skip to main content

lemon_mint/
lib.rs

1//! # lemon-mint
2//!
3//! A pure-Rust port of the famous [Lemon parser generator](https://www.hwaci.com/sw/lemon/),
4//! packaged as a **library with an API** instead of a command-line tool.
5//!
6//! You describe an LALR(1) grammar — either as a Lemon-style `.y` grammar string/file, or by
7//! calling builder methods — and lemon-mint emits a self-contained Rust source file containing the
8//! parser's state-machine tables and a small driver. The generated parser is plain Rust with **no
9//! runtime dependency on this crate**, so you can commit it to your repository or generate it from a
10//! `build.rs` build script.
11//!
12//! Unlike a hand-written recursive-descent parser, the output is a table-driven bottom-up
13//! (shift/reduce) LALR(1) parser: compact, fast, and able to report grammar conflicts at generation
14//! time rather than surprising you at run time.
15//!
16//! ## The three steps
17//!
18//! 1. Build a grammar with [`LemonMintBuilder`]. Either feed it a whole grammar with
19//!    [`load_y`](LemonMintBuilder::load_y) / [`load_y_file`](LemonMintBuilder::load_y_file), or
20//!    assemble it piece by piece with [`set_start_symbol`](LemonMintBuilder::set_start_symbol),
21//!    [`set_token_type`](LemonMintBuilder::set_token_type), [`add_type`](LemonMintBuilder::add_type),
22//!    [`add_rule`](LemonMintBuilder::add_rule), and friends. The two styles can be mixed freely.
23//! 2. Compile the grammar into the parser tables with
24//!    [`try_into_lemon`](LemonMintBuilder::try_into_lemon), which returns a [`LemonMint`]. Grammar
25//!    errors and unresolved parser conflicts are reported here as an [`Err`].
26//! 3. Emit Rust source with [`gen_rust`](LemonMint::gen_rust). Optionally write a human-readable
27//!    report of the state machine with [`gen_log`](LemonMint::gen_log) (the classic Lemon
28//!    `y.output`), or a normalized copy of the grammar with [`gen_y`](LemonMint::gen_y).
29//!
30//! ## Example: a calculator
31//!
32//! This generates a parser for newline-separated arithmetic expressions, then runs it on
33//! `15 / 5` to get `3.0`:
34//!
35//! ```
36//! use std::sync::Arc;
37//! use lemon_mint::LemonMintBuilder;
38//!
39//! let builder = LemonMintBuilder::new().load_y
40//! (	&Arc::new("source.y".to_string()), // fake source name, that will appear in error messages
41//! 	"	%trace {>> }
42//! 		%extra_argument {()}
43//! 		%left PLUS MINUS.
44//! 		%left TIMES DIVIDE.
45//! 		%token_type {f64}
46//! 		%type Expr {super::Expr}
47//! 		%type Exprs {Vec<super::Expr>}
48//! 		%type Program {Vec<super::Expr>}
49//!
50//! 		Program ::= Exprs(exprs). exprs
51//! 		Program ::= Exprs(exprs) NEW_LINE. exprs
52//!
53//! 		Exprs ::= Expr(item).                       vec![item]
54//! 		Exprs ::= Exprs(items) NEW_LINE Expr(item). let mut items = items; items.push(item); items
55//!
56//! 		Expr ::= NUM(value). super::Expr {value}
57//! 		Expr ::= PAR_OPEN Expr(a) PAR_CLOSE. a
58//! 		Expr ::= PLUS Expr(a). a
59//! 		Expr ::= MINUS Expr(a). let mut a = a; a.value = -a.value; a
60//! 		Expr ::= Expr(a) PLUS Expr(b). super::Expr{value: a.value + b.value}
61//! 		Expr ::= Expr(a) MINUS Expr(b). super::Expr{value: a.value - b.value}
62//! 		Expr ::= Expr(a) TIMES Expr(b). super::Expr{value: a.value * b.value}
63//! 		Expr ::= Expr(a) DIVIDE Expr(b). super::Expr{value: a.value / b.value}
64//!
65//! 		%code {
66//! 			use code::{Parser, Token};
67//!
68//!             #[derive(Debug, PartialEq)]
69//! 			pub struct Expr {value: f64}
70//!
71//! 			fn main()
72//! 			{	let mut parser = Parser::new(()); // () is our extra argument, accessible in actions and through parser.extra
73//!
74//! 				parser.add_token(Token::NUM, 15.0).unwrap();
75//! 				parser.add_token(Token::DIVIDE, 0.0).unwrap();
76//! 				parser.add_token(Token::NUM, 5.0).unwrap();
77//! 				parser.add_token(Token::NEW_LINE, 0.0).unwrap();
78//!
79//! 				let result = parser.end().unwrap(); // type is %type of the start symbol Program
80//!                 assert_eq!(result, vec![Expr {value: 3.0}]);
81//!                 println!(\"Result: {:?}\", result);
82//! 			}
83//! 		}
84//! 	".as_bytes()
85//! ).unwrap();
86//!
87//! let lemon = builder.try_into_lemon().unwrap();
88//!
89//! // Emit the parser. Here we write to in-memory buffers; in practice you would write `parser.rs`
90//! // (e.g. to `OUT_DIR` from a build script) and `include!` it.
91//! let mut out_rust: Vec<u8> = Vec::new();
92//! let mut out_log: Vec<u8> = Vec::new();
93//! lemon.gen_rust(&mut out_rust).unwrap();
94//! lemon.gen_log(&mut out_log, false, false).unwrap();
95//! ```
96//!
97//! ## Using the generated parser
98//!
99//! [`gen_rust`](LemonMint::gen_rust) wraps everything in a `code` module. The two items you use from
100//! it are `Token` (an enum with one variant per terminal symbol) and `Parser`:
101//!
102//! ```ignore
103//! use code::{Parser, Token};
104//!
105//! let mut parser = Parser::new(extra);           // `extra` is the initial %extra_argument value
106//! parser.add_token(Token::NUM, 15.0)?;           // feed terminals in input order, with their values
107//! parser.add_token(Token::DIVIDE, 0.0)?;
108//! parser.add_token(Token::NUM, 5.0)?;
109//! let result = parser.end()?;                    // finish; result has the start symbol's %type
110//! ```
111//!
112//! `add_token` returns `Err(())` on a syntax error, and `end` returns `Err(())` if the input is not a
113//! complete sentence of the grammar. The whole driver lives in `code`; a second `rules` module holds
114//! the action code and is not used directly. Items from your crate are reachable from actions and
115//! `%code` as `super::…` or `crate::…` (e.g. `super::Expr`).
116//!
117//! ### Soft keywords with `try_add_token`
118//!
119//! `Parser::try_add_token` is a non-committal variant of `add_token`: it returns `Ok(true)` if the
120//! token is accepted in the current state, or `Ok(false)` if it is not — **without** raising a syntax
121//! error. This lets a tokenizer treat a word as a keyword where the grammar expects one and fall back
122//! to feeding it as an identifier elsewhere ("soft" / non-reserved keywords):
123//!
124//! ```ignore
125//! match parser.try_add_token(Token::DAY, value) {
126//!     Ok(true)  => {}                                   // consumed as the DAY keyword
127//!     Ok(false) => parser.add_token(Token::IDENT, ident)?, // not valid here — re-feed as identifier
128//!     Err(())   => return Err(SyntaxError),
129//! }
130//! ```
131//!
132//! ## Y-grammar reference
133//!
134//! lemon-mint accepts a grammar syntax close to [classic Lemon](https://www.hwaci.com/sw/lemon/).
135//! Line (`//`) and block (`/* … */`) C-style comments are allowed anywhere.
136//!
137//! ### Rules and actions
138//!
139//! A rule is `Lhs ::= Rhs.` optionally followed by an action — Rust code producing the semantic value
140//! of the left-hand side:
141//!
142//! ```text
143//! Expr ::= Expr(a) PLUS Expr(b). super::Expr{value: a.value + b.value}
144//! ```
145//!
146//! The `.` ends the right-hand side; everything after it (up to the next rule or directive) is the
147//! action. A rule with no action produces `()`. Parenthesized names like `(a)` are **aliases** that
148//! bind the semantic value of that symbol to a variable usable in the action. The action also has
149//! `&mut extra` in scope (the `%extra_argument`).
150//!
151//! ### Terminals vs nonterminals
152//!
153//! A symbol whose name contains at least one lowercase letter is a **nonterminal**; an all-uppercase
154//! name is a **terminal** (a `Token`). (Classic Lemon decides this from the first letter only.)
155//!
156//! ### Types
157//!
158//! Every symbol carries a semantic value. Terminals all share the `%token_type`. Each nonterminal's
159//! type is set with `%type Name {Type}`, or defaults to `%default_type`. The start symbol's type is
160//! what the generated `Parser::end` returns.
161//!
162//! ### Precedence and associativity
163//!
164//! `%left`, `%right`, and `%nonassoc` declare terminal precedence to resolve shift/reduce conflicts.
165//! Each successive declaration binds more tightly than the previous one:
166//!
167//! ```text
168//! %left PLUS MINUS.    // lower precedence
169//! %left TIMES DIVIDE.  // higher precedence
170//! ```
171//!
172//! ### Supported directives
173//!
174//! | Directive | Purpose |
175//! |---|---|
176//! | `%token_type {T}` | Type of every terminal's semantic value |
177//! | `%type Name {T}` | Type of one nonterminal's semantic value |
178//! | `%default_type {T}` | Default type for nonterminals without a `%type` |
179//! | `%start_symbol Name` | The grammar's start symbol |
180//! | `%extra_argument {T}` | Type of the user value threaded through the parser (name is always `extra`, default `()`) |
181//! | `%left` / `%right` / `%nonassoc` | Terminal precedence and associativity |
182//! | `%fallback FB A B C.` | Tokens `A B C` fall back to `FB` when they have no action in the current state |
183//! | `%trace {prompt}` | Enable tracing to stderr, prefixing each message with `prompt` |
184//! | `%code` / `%include` | Verbatim Rust code appended to the generated file (synonyms) |
185//!
186//! Directive syntax is permissive — braces, a trailing `.`, or a bare token all work, and a braced
187//! value may span multiple lines up to its matching closing brace:
188//!
189//! ```text
190//! %start_symbol {Unit}
191//! %start_symbol Unit.
192//! %start_symbol Unit
193//! ```
194//!
195//! ## Differences from classic Lemon
196//!
197//! * A symbol is a nonterminal if its name contains any lowercase letter (classic Lemon looks only at
198//!   the first letter).
199//! * Tracing is enabled by the `%trace` directive rather than a `ParseTrace()` call.
200//! * No `%name` directive — each generated file is its own Rust module.
201//! * No destructors — Rust's ownership and `Drop` handle cleanup.
202
203
204mod lempar;
205
206use lempar::LemparReader;
207
208use std::mem;
209use std::cmp;
210use std::cmp::Ordering;
211use std::collections::HashMap;
212use std::cell::RefCell;
213use std::io::{self, BufRead, BufReader};
214use std::fmt;
215use std::hash::{Hash, Hasher};
216use std::collections::hash_map::DefaultHasher;
217use std::error::Error;
218use std::iter::Take;
219use std::slice::Iter;
220use std::convert::TryFrom;
221use std::rc::Rc;
222use std::sync::Arc;
223use std::fs::File;
224use std::borrow::Cow;
225
226fn typename_to_string(value: String) -> String
227{	let value_trimmed = value.trim();
228	if value_trimmed.is_empty() || value.starts_with('(') && value.ends_with(')') && value[1 .. value.len()-1].trim().is_empty()
229	{	String::new()
230	}
231	else
232	{	if value.len() == value_trimmed.len() {value} else {value_trimmed.to_string()}
233	}
234}
235
236fn is_terminal_name(s: &str) -> bool
237{	s.find(|c: char| c.is_ascii_lowercase()).is_none()
238}
239
240#[derive(Debug)]
241pub struct LemonMintError
242{	pub filename: Arc<String>,
243	pub n_line: usize,
244	pub message: String,
245}
246impl LemonMintError
247{	pub fn new(filename: &Arc<String>, n_line: usize, message: String) -> Self
248	{	Self {filename: Arc::clone(filename), n_line, message}
249	}
250}
251impl fmt::Display for LemonMintError
252{	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
253	{	let message: &str = if self.message.is_empty() {"Unspecified error"} else {&self.message};
254		if self.filename.is_empty()
255		{	write!(f, "{}", message)
256		}
257		else
258		{	write!(f, "{}({}): {}", self.filename, self.n_line, message)
259		}
260	}
261}
262impl Error for LemonMintError {}
263
264type ParserResult<T> = Result<T, LemonMintError>;
265
266#[derive(Copy, Clone, Eq, PartialEq, Debug)]
267enum Directive
268{	Rule,
269	TokenType,
270	Type,
271	DefaultType,
272	StartSymbol,
273	Trace,
274	ExtraArgument,
275	Left,
276	Right,
277	Nonassoc,
278	Fallback,
279	Code,
280}
281
282#[derive(Copy, Clone, Eq, PartialEq, Debug)]
283enum SymbolType
284{	TERMINAL,
285	NONTERMINAL
286}
287
288#[derive(Copy, Clone, Eq, PartialEq, Debug)]
289enum Associativity
290{	LEFT,
291	RIGHT,
292	NONASSOC,
293	UNKNOWN
294}
295
296#[derive(Debug)]
297struct Set
298{	data: Vec<bool>,
299}
300impl Set
301{	pub fn new(size: usize) -> Self
302	{	let mut this = Self {data: Vec::new()};
303		if size > 0
304		{	this.set_size(size);
305		}
306		this
307	}
308
309	pub fn len(&self) -> usize
310	{	self.data.len()
311	}
312
313	pub fn set_size(&mut self, size: usize)
314	{	self.data.clear();
315		self.data.resize(size, false);
316	}
317
318	pub fn contains(&self, element: usize) -> bool
319	{	*self.data.get(element).unwrap_or(&false)
320	}
321
322	pub fn add(&mut self, element: usize) -> bool
323	{	let rv = self.contains(element);
324		if let Some(v) = self.data.get_mut(element)
325		{	*v = true;
326		}
327		!rv
328	}
329
330	pub fn intersect(&mut self, other: &Set) -> bool
331	{	let mut changed = false;
332		for (i, v) in &mut self.data.iter_mut().enumerate()
333		{	if !*v && other.contains(i)
334			{	changed = true;
335				*v = true;
336			}
337		}
338		return changed;
339	}
340}
341
342/// Terminal or nonterminal symbol from the grammar.
343#[derive(Debug)]
344struct Symbol
345{	name: Arc<String>,             // Name of the symbol
346	index: usize,                  // Index number for this symbol
347	typ: SymbolType,               // Symbols are all either TERMINALS or NTs
348	sym_rules_arr: Vec<usize>,     // Array of rules of this (if an NT) (indices in rules array)
349	fallback_index: usize,         // fallback token in case this token doesn't parse
350	prec: i32,                     // Precedence if defined (-1 otherwise)
351	assoc: Associativity,          // Associativity if precedence is defined
352	firstset: Set,                 // First-set for all rules of this symbol
353	lambda: bool,                  // True if NT and can generate an empty string
354	data_type: String,             // The data type of information held by this object. Only used if type==NONTERMINAL
355	dtnum: usize,                  // The data type number. In the parser, the value stack is a union. The .Symbol%d element of this union is the correct data type for this object
356}
357impl Symbol
358{	fn new(name: &str, index: usize) -> Self
359	{	let typ = if is_terminal_name(name) || name=="$" {SymbolType::TERMINAL} else {SymbolType::NONTERMINAL};
360		Self
361		{	name: Arc::new(String::new()),
362			index,
363			typ,
364			sym_rules_arr: Vec::new(),
365			fallback_index: std::usize::MAX,
366			prec: -1,
367			assoc: Associativity::UNKNOWN,
368			firstset: Set::new(0),
369			lambda: false,
370			data_type: String::new(),
371			dtnum: 0,
372		}
373	}
374}
375impl PartialEq for Symbol
376{	fn eq(&self, other: &Self) -> bool
377	{	self.index == other.index
378	}
379}
380
381#[derive(Debug)]
382struct Rhs
383{	name: Arc<String>,
384	index: usize,
385	alias: String,
386}
387
388/// Each production rule in the grammar is stored in this structure.
389#[derive(Debug)]
390struct Rule
391{	rule_filename: Arc<String>,
392	rule_n_line: usize,            // Line number for the rule
393	lhs: Arc<String>,              // Left-hand side of the rule
394	lhs_index: usize,              // Left-hand side of the rule (index in symbols)
395	lhs_start: bool,               // True if left-hand side is the start symbol
396	rhs: Vec<Rhs>,                 // The RHS symbols
397	code: String,                  // The code executed when this rule is reduced
398	precsym_index: usize,          // Precedence symbol for this rule (index in symbols)
399	index: usize,                  // An index number for this rule
400	can_reduce: bool,              // True if this rule is ever reduced
401	does_reduce: bool,             // Reduce actions occur after optimization
402}
403impl Rule
404{	fn new(rule_filename: &Arc<String>, rule_n_line: usize, lhs: &Arc<String>, lhs_index: usize, index: usize, code: String) -> Self
405	{	Self
406		{	rule_filename: Arc::clone(rule_filename),
407			rule_n_line,
408			lhs: Arc::clone(lhs),
409			lhs_index,
410			lhs_start: false,
411			rhs: Vec::new(),
412			code,
413			precsym_index: std::usize::MAX,
414			index,
415			can_reduce: false,
416			does_reduce: false,
417		}
418	}
419}
420impl fmt::Display for Rule
421{	/// Write text on "out" that describes the rule
422	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
423	{	write!(f, "{} ::=", self.lhs)?;
424		for sp in &self.rhs
425		{	write!(f, " {}", sp.name)?;
426		}
427		Ok(())
428	}
429}
430
431#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
432struct ConfigKey
433{	n_rule: usize,
434	dot: usize,
435}
436impl ConfigKey
437{	fn new(config: &Config) -> Self
438	{	Self
439		{	n_rule: config.n_rule,
440			dot: config.dot,
441		}
442	}
443}
444impl cmp::Ord for ConfigKey
445{	fn cmp(&self, other: &Self) -> cmp::Ordering
446	{	let mut res = self.n_rule.cmp(&other.n_rule);
447		if res == Ordering::Equal
448		{	res = self.dot.cmp(&other.dot);
449		}
450		res
451	}
452}
453impl cmp::PartialOrd for ConfigKey
454{	fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>
455	{	Some(self.cmp(other))
456	}
457}
458
459/// A configuration is a production rule of the grammar together with
460/// a mark (dot) showing how much of that rule has been processed so far.
461/// Configurations also contain a follow-set which is a list of terminal
462/// symbols which are allowed to immediately follow the end of the rule.
463/// Every configuration is recorded as an instance of this structure.
464#[derive(Debug)]
465struct Config
466{	n_rule: usize,                  // The rule upon which the configuration is based
467	dot: usize,                     // The parse point
468	fws: Set,                       // Follow-set for this configuration only
469	fplp: Vec<Rc<RefCell<Config>>>, // Follow-set forward propagation links
470	bplp: Vec<Rc<RefCell<Config>>>, // Follow-set backwards propagation links
471	n_state: usize,                 // Pointer to state which contains this
472	status_is_complete: bool,       // used during followset and shift computations
473}
474impl Config
475{	pub fn new(n_rule: usize, dot: usize, fws_size: usize) -> Self
476	{	Self
477		{	n_rule,
478			dot,
479			fws: Set::new(fws_size),
480			fplp: Vec::new(),
481			bplp: Vec::new(),
482			n_state: std::usize::MAX,
483			status_is_complete: false,
484		}
485	}
486}
487impl cmp::Ord for Config
488{	fn cmp(&self, other: &Self) -> cmp::Ordering
489	{	ConfigKey::new(self).cmp(&ConfigKey::new(other))
490	}
491}
492impl cmp::PartialOrd for Config
493{	fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>
494	{	Some(self.cmp(other))
495	}
496}
497impl cmp::PartialEq for Config
498{	fn eq(&self, other: &Self) -> bool
499	{	ConfigKey::new(self).eq(&ConfigKey::new(other))
500	}
501}
502impl Eq for Config {}
503
504#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
505enum ActionType
506{	Shift,
507	Accept,
508	Reduce,
509	Error,
510	SsConflict,  // A shift/shift conflict
511	SrConflict,  // Was a reduce, but part of a conflict
512	RrConflict,  // Was a reduce, but part of a conflict
513	ShResolved, // Was a shift.  Precedence resolved conflict
514	RdResolved, // Was reduce.  Precedence resolved conflict
515	NotUsed,    // Deleted by compression
516	ShiftReduce // Shift first, then reduce
517}
518
519#[derive(Debug, PartialEq, Copy, Clone)]
520enum StateOrRule
521{	State(usize), // n_state: usize - The new state, if a shift
522	Rule(usize),  // The rule, if a reduce
523	EmptyRule     // Empty reduce rule for "accepting" token
524}
525
526/// Every shift or reduce operation is stored as one of this structure.
527#[derive(Debug)]
528struct Action
529{	id: i32,
530	symbol_index: usize,     // The look-ahead symbol
531	typ: ActionType,
532	x: StateOrRule,
533	symbol_index_opt: usize, // ActionType::ShiftReduce optimization to this symbol
534}
535impl Action
536{	fn new_state(id: i32, symbol_index: usize, n_state: usize) -> Action
537	{	Action
538		{	id,
539			symbol_index,
540			typ: ActionType::Shift,
541			x: StateOrRule::State(n_state),
542			symbol_index_opt: std::usize::MAX,
543		}
544	}
545
546	fn new_rule(id: i32, symbol_index: usize, typ: ActionType, n_rule: usize) -> Action
547	{	Action
548		{	id,
549			symbol_index,
550			typ,
551			x: StateOrRule::Rule(n_rule),
552			symbol_index_opt: std::usize::MAX,
553		}
554	}
555
556	fn new_empty_rule(id: i32, symbol_index: usize, typ: ActionType) -> Action
557	{	Action
558		{	id,
559			symbol_index,
560			typ,
561			x: StateOrRule::EmptyRule,
562			symbol_index_opt: std::usize::MAX,
563		}
564	}
565}
566impl cmp::Ord for Action
567{	fn cmp(&self, other: &Self) -> cmp::Ordering
568	{	let index = self.symbol_index;
569		let other_index = other.symbol_index;
570		let mut res = index.cmp(&other_index);
571		if res == Ordering::Equal
572		{	res = self.typ.cmp(&other.typ);
573			if res == Ordering::Equal
574			{	if self.typ==ActionType::Reduce || self.typ==ActionType::ShiftReduce
575				{	if let StateOrRule::Rule(n_rule) = self.x
576					{	if let StateOrRule::Rule(other_n_rule) = other.x
577						{	if n_rule < other_n_rule
578							{	return Ordering::Less;
579							}
580							if n_rule > other_n_rule
581							{	return Ordering::Greater;
582							}
583						}
584					}
585				}
586				res = self.id.cmp(&other.id);
587			}
588		}
589		res
590	}
591}
592impl cmp::PartialOrd for Action
593{	fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>
594	{	Some(self.cmp(other))
595	}
596}
597impl cmp::PartialEq for Action
598{	fn eq(&self, other: &Self) -> bool
599	{	self.cmp(other) == Ordering::Equal
600	}
601}
602impl Eq for Action {}
603
604/// Each state of the generated parser's finite state machine is encoded as an instance of this structure.
605#[derive(Debug)]
606struct State
607{	basis: Vec<Rc<RefCell<Config>>>,          // The basis configurations for this state
608	configurations: Vec<Rc<RefCell<Config>>>, // All configurations in this set
609	n_state: usize,                    // Sequential number for this state
610	actions: Vec<Rc<RefCell<Action>>>, // Array of actions for this state
611	n_token_act: usize,
612	n_nt_act: usize,                   // Number of actions on terminals and nonterminals
613	token_offset: isize,
614	nt_offset: isize,                  // yy_action[] offset for terminals and nonterms
615	default_reduce_action: usize,      // Default action is to REDUCE by this rule
616	default_reduce_rule: usize,        // The default REDUCE rule
617	auto_reduce: bool,
618}
619impl State
620{	pub fn new(n_state: usize, basis: Vec<Rc<RefCell<Config>>>, configurations: Vec<Rc<RefCell<Config>>>) -> Self
621	{	Self
622		{	basis,
623			configurations,
624			n_state,
625			actions: Vec::new(),
626			n_token_act: 0,
627			n_nt_act: 0,
628			token_offset: 0,
629			nt_offset: 0,
630			default_reduce_action: 0,
631			default_reduce_rule: std::usize::MAX,
632			auto_reduce: false,
633		}
634	}
635}
636
637/// Each state contains a set of token transaction and a set of
638/// nonterminal transactions.  Each of these sets makes an instance
639/// of the following structure.  An array of these structures is used
640/// to order the creation of entries in the `yy_action[]` table.
641#[derive(Debug)]
642struct AxSet
643{	n_state: usize, // Index in sorted states array
644	is_tkn: bool,    // True to use tokens.  False for non-terminals
645	n_action: usize,   // Number of actions
646	i_order: usize,    // Original order of action sets
647}
648impl AxSet
649{	fn new(n_state: usize, is_tkn: bool, n_action: usize, i_order: usize) -> Self
650	{	Self
651		{	n_state,
652			is_tkn,
653			n_action,
654			i_order,
655		}
656	}
657}
658impl cmp::Ord for AxSet
659{	fn cmp(&self, other: &Self) -> cmp::Ordering
660	{	let mut res = other.n_action.cmp(&self.n_action); // descending order
661		if res == Ordering::Equal
662		{	res = self.i_order.cmp(&other.i_order);
663		}
664		res
665	}
666}
667impl cmp::PartialOrd for AxSet
668{	fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>
669	{	Some(self.cmp(other))
670	}
671}
672impl cmp::PartialEq for AxSet
673{	fn eq(&self, other: &Self) -> bool
674	{	self.cmp(other) == Ordering::Equal
675	}
676}
677impl Eq for AxSet {}
678
679/// The state of the yy_action table under construction is an instance of
680/// the following structure.
681///
682/// The yy_action table maps the pair (state_number, lookahead) into an
683/// action_number.  The table is an array of integers pairs.  The state_number
684/// determines an initial offset into the yy_action array.  The lookahead
685/// value is then added to this initial offset to get an index X into the
686/// yy_action array. If the `aAction[X]`.lookahead equals the value of the
687/// of the lookahead input, then the value of the action_number output is
688/// `aAction[X].action`.  If the lookaheads do not match then the
689/// default action for the state_number is returned.
690///
691/// All actions associated with a single state_number are first entered
692/// into `aLookahead[]` using multiple calls to acttab_action().  Then the
693/// actions for that single state_number are placed into the `aAction[]`
694/// array with a single call to acttab_insert().  The acttab_insert() call
695/// also resets the `aLookahead[]` array in preparation for the next
696/// state number.
697#[derive(Copy, Clone, Eq, PartialEq, Debug)]
698struct LookaheadAction
699{	lookahead: usize, // Value of the lookahead token
700	action: usize,    // Action to take on the given lookahead
701}
702impl LookaheadAction
703{	fn new(lookahead: usize, action: usize) -> Self
704	{	Self
705		{	lookahead,
706			action,
707		}
708	}
709}
710
711#[derive(Debug)]
712struct ActTab
713{	n_action: usize,                   // Number of used slots in aAction[]
714	a_action: Vec<LookaheadAction>,    // The yy_action[] table under construction
715	a_lookahead: Vec<LookaheadAction>, // A single new transaction set
716	min_lookahead: usize,              // Minimum aLookahead[].lookahead
717	max_lookahead: usize,              // Maximum aLookahead[].lookahead
718	min_action: usize,                 // Action associated with mnLookahead
719
720	n_terminals: usize,                // Number of terminal symbols
721	n_symbols: usize,                  // Total number of symbols
722
723	min_token_offset: isize,
724	max_token_offset: isize,
725	min_nt_offset: isize,
726	max_nt_offset: isize,
727
728	n_fallbacks: usize,
729	n_shift_offset: usize,
730	reduce_count: usize,
731}
732impl ActTab
733{	fn new(n_terminals: usize, n_symbols: usize) -> Self
734	{	Self
735		{	n_action: 0,
736			a_action: Vec::new(),
737			a_lookahead: Vec::new(),
738			min_lookahead: 0,
739			max_lookahead: 0,
740			min_action: 0,
741
742			n_terminals,
743			n_symbols,
744
745			min_token_offset: 0,
746			max_token_offset: 0,
747			min_nt_offset: 0,
748			max_nt_offset: 0,
749
750			n_fallbacks: 0,
751			n_shift_offset: 0,
752			reduce_count: 0,
753		}
754	}
755
756	fn get_n_lookahead(&self) -> usize
757	{	self.n_action
758	}
759
760	fn get_n_actions(&self) -> usize
761	{	let mut n_action = self.n_action;
762		for rec in  self.a_action.iter().take(n_action).rev()
763		{	if rec.lookahead == std::usize::MAX
764			{	n_action -= 1;
765			}
766			else
767			{	break;
768			}
769		}
770		n_action
771	}
772
773	fn iter(&self) -> Take<Iter<'_, LookaheadAction>>
774	{	self.a_action.iter().take(self.n_action)
775	}
776
777	/// Add a new action to the current transaction set.
778	/// This routine is called once for each lookahead for a particular state.
779	fn acttab_action(&mut self, lookahead: usize, action: usize)
780	{	if self.a_lookahead.len() == 0
781		{	self.max_lookahead = lookahead;
782			self.min_lookahead = lookahead;
783			self.min_action = action;
784		}
785		else
786		{	if self.max_lookahead < lookahead
787			{	self.max_lookahead = lookahead;
788			}
789			if self.min_lookahead > lookahead
790			{	self.min_lookahead = lookahead;
791				self.min_action = action;
792			}
793		}
794		self.a_lookahead.push(LookaheadAction::new(lookahead, action));
795	}
796
797	/// Add the transaction set built up with prior calls to acttab_action() into the current action table.
798	/// Then reset the transaction set back to an empty set in preparation for a new round of acttab_action() calls.
799	///
800	/// Return the offset into the action table of the new transaction.
801	fn acttab_insert(&mut self, make_it_safe: bool) -> isize
802	{	assert!(self.a_lookahead.len() > 0);
803
804		// Make sure we have enough space to hold the expanded action table in the worst case.  The worst case occurs if the transaction set
805		// must be appended to the current action table
806		if self.n_action + self.n_symbols + 1 >= self.a_action.len()
807		{	self.a_action.resize(self.n_action + self.n_symbols + self.a_action.len() + 21, LookaheadAction::new(std::usize::MAX, std::usize::MAX));
808		}
809
810		// Scan the existing action table looking for an offset that is a duplicate of the current transaction set.  Fall out of the loop
811		// if and when the duplicate is found.
812		//
813		// i is the index in aAction[] where mnLookahead is inserted.
814		let mut found_offset = std::usize::MAX;
815		let end = if make_it_safe {self.min_lookahead} else {0};
816'l:		for i in (end .. self.n_action).rev()
817		{	if self.a_action[i].lookahead == self.min_lookahead
818			{	// All lookaheads and actions in the aLookahead[] transaction must match against the candidate aAction[i] entry.
819				if self.a_action[i].action == self.min_action
820				{	for j in 0..self.a_lookahead.len()
821					{	let k = self.a_lookahead[j].lookahead + i - self.min_lookahead;
822						if k>=self.n_action || self.a_lookahead[j].lookahead != self.a_action[k].lookahead || self.a_lookahead[j].action != self.a_action[k].action
823						{	continue 'l;
824						}
825					}
826					// No possible lookahead value that is not in the aLookahead[] transaction is allowed to match aAction[i]
827					let mut n = 0;
828					for j in 0..self.n_action
829					{	if self.a_action[j].lookahead != std::usize::MAX
830						{	if self.a_action[j].lookahead == (j + self.min_lookahead).wrapping_sub(i)
831							{	n += 1;
832							}
833						}
834					}
835					if n == self.a_lookahead.len()
836					{	found_offset = i;  // An exact match is found at offset i
837						break;
838					}
839				}
840			}
841		}
842
843		// If no existing offsets exactly match the current transaction, find an an empty offset in the aAction[] table in which we can add the aLookahead[] transaction.
844		if found_offset == std::usize::MAX
845		{	// Look for holes in the aAction[] table that fit the current aLookahead[] transaction.  Leave found_offset set to the offset of the hole.
846			// If no holes are found, found_offset is left at nAction, which means the transaction will be appended.
847			found_offset = if make_it_safe {self.min_lookahead} else {0};
848'm:			for i in found_offset .. self.a_action.len() - self.max_lookahead
849			{	if self.a_action[i].lookahead == std::usize::MAX
850				{	for j in 0 .. self.a_lookahead.len()
851					{	let k = self.a_lookahead[j].lookahead + i - self.min_lookahead;
852						if k >= self.a_action.len() || self.a_action[k].lookahead != std::usize::MAX
853						{	continue 'm;
854						}
855					}
856					for j in 0 .. self.n_action
857					{	if self.a_action[j].lookahead == (j + self.min_lookahead).wrapping_sub(i)
858						{	continue 'm;
859						}
860					}
861					found_offset = i; // Fits in empty slots
862					break;
863				}
864			}
865		}
866
867		// Insert transaction set at index found_offset
868		for j in 0 .. self.a_lookahead.len()
869		{	let k = self.a_lookahead[j].lookahead - self.min_lookahead + found_offset;
870			self.a_action[k] = self.a_lookahead[j];
871			if k >= self.n_action
872			{	self.n_action = k + 1;
873			}
874		}
875		if make_it_safe && found_offset+self.n_terminals >= self.n_action
876		{	self.n_action = found_offset+self.n_terminals+1;
877		}
878		self.a_lookahead.clear();
879
880		// Return the offset that is added to the lookahead in order to get the index into yy_action of the action
881		return found_offset as isize - self.min_lookahead as isize;
882	}
883}
884
885#[derive(Debug)]
886struct SymbolsBuilder
887{	symbols_map: HashMap<Arc<String>, Symbol>,
888	n_terminals: usize,
889	n_nonterminals: usize,
890}
891impl SymbolsBuilder
892{	pub fn new(empty: bool) -> Self
893	{	let mut this = Self
894		{	symbols_map: HashMap::new(),
895			n_terminals: 0,
896			n_nonterminals: 0,
897		};
898		if !empty
899		{	this.add(&Arc::new("$".to_string()));
900		}
901		this
902	}
903
904	/// Return a pointer to the (terminal or nonterminal) symbol "symbol_name". Create a new symbol if this is the first time "x" has been seen.
905	pub fn add(&mut self, symbol_name: &Arc<String>) -> usize
906	{	if let Some(symbol) = self.symbols_map.get(symbol_name)
907		{	symbol.index
908		}
909		else
910		{	let index = if is_terminal_name(symbol_name.as_ref()) || symbol_name.as_ref()=="$"
911			{	self.n_terminals += 1;
912				self.n_terminals - 1
913			}
914			else
915			{	self.n_nonterminals += 1;
916				self.n_nonterminals - 1
917			};
918			let symbol = Symbol::new(symbol_name, index); // need to set the name later in into_symbols()
919			self.symbols_map.insert(Arc::clone(symbol_name), symbol);
920			index
921		}
922	}
923
924	pub fn get(&self, symbol_name: &Arc<String>) -> &Symbol
925	{	&self.symbols_map[symbol_name]
926	}
927
928	pub fn get_mut(&mut self, symbol_name: &Arc<String>) -> &mut Symbol
929	{	self.symbols_map.get_mut(symbol_name).unwrap()
930	}
931
932	pub fn into_symbols(mut self, start_name: &String, nonterminal_types: HashMap<String, StringInFile>, precedence: HashMap<String, PrecedenceInFile>, rules: &mut Vec<Rule>) -> ParserResult<Symbols>
933	{	// nonterminal_types
934		for (symbol_name, symbol_type) in nonterminal_types
935		{	if let Some(symbol) = self.symbols_map.get_mut(&symbol_name)
936			{	symbol.data_type = symbol_type.string;
937			}
938			else
939			{	return Err(LemonMintError::new(&symbol_type.filename, symbol_type.n_line, format!("No such nonterminal symbol when defining symbol type: \"{}\"", symbol_name)));
940			}
941		}
942		// precedence
943		for (symbol_name, precedence) in precedence
944		{	if let Some(symbol) = self.symbols_map.get_mut(&symbol_name)
945			{	symbol.prec = precedence.precedence;
946				symbol.assoc = precedence.assoc;
947			}
948			else
949			{	return Err(LemonMintError::new(&precedence.filename, precedence.n_line, format!("No such terminal symbol \"{}\" when defining precedence", symbol_name)));
950			}
951		}
952		// convert rules
953		for rule in rules
954		{	rule.lhs_index += self.n_terminals;
955			for rhs in rule.rhs.iter_mut()
956			{	if self.symbols_map[&rhs.name].typ == SymbolType::NONTERMINAL
957				{	rhs.index += self.n_terminals;
958				}
959			}
960		}
961		// into Symbols
962		let n_symbols = self.symbols_map.len();
963		let default_symbol = self.add(&Arc::new("{default}".to_string()));
964		let default_symbol_index = default_symbol + self.n_terminals;
965		let mut start_symbol_index = std::usize::MAX;
966		let mut error_symbol_index = std::usize::MAX;
967		let mut array = Vec::with_capacity(self.symbols_map.len());
968		for (symbol_name, mut symbol) in self.symbols_map
969		{	if symbol.typ == SymbolType::NONTERMINAL
970			{	symbol.index += self.n_terminals;
971				if symbol_name.as_ref() == start_name
972				{	start_symbol_index = symbol.index;
973				}
974				else if symbol_name.as_ref() == "error"
975				{	error_symbol_index = symbol.index;
976				}
977			}
978			else if symbol.index == 0
979			{	symbol.typ = SymbolType::NONTERMINAL; // like in lemon
980			}
981			symbol.name = Arc::clone(&symbol_name);
982			array.push(symbol);
983		}
984		array.sort_by(|a, b| a.index.cmp(&b.index));
985		Ok(Symbols {array, n_symbols, n_terminals: self.n_terminals, default_symbol_index, start_symbol_index, error_symbol_index})
986	}
987}
988
989#[derive(Debug)]
990struct Symbols
991{	pub array: Vec<Symbol>, // Sorted array of all symbols
992	pub n_symbols: usize,                // Number of terminal and nonterminal symbols
993	pub n_terminals: usize,              // Number of terminal symbols
994	pub start_symbol_index: usize,
995	pub default_symbol_index: usize,
996	pub error_symbol_index: usize,
997}
998impl Symbols
999{	pub fn get_start_symbol(&self) -> &Symbol
1000	{	&self.array[self.start_symbol_index]
1001	}
1002
1003	pub fn get_error_symbol(&self) -> Option<&Symbol>
1004	{	self.array.get(self.error_symbol_index)
1005	}
1006}
1007
1008#[derive(Debug)]
1009struct States
1010{	pub array: Vec<State>,
1011	pub n_no_tail: usize, // Number of states with tail degenerate states removed
1012}
1013
1014#[derive(Debug)]
1015struct StatesBuilder;
1016impl StatesBuilder
1017{	/// Compute all LR(0) states for the grammar. Links are added to between some states so that the LR(1) follow sets can be computed later.
1018	pub fn build(symbols: &Symbols, rules: &mut Vec<Rule>, start: &Symbol, n_terminals: usize, actions_enum: &mut i32) -> ParserResult<States>
1019	{	let mut configs_basis_keys_arr = Vec::new();
1020		let mut configs_basis_arr = Vec::new();
1021		let mut configs_arr = Vec::new();
1022		let mut configs_map = HashMap::new();
1023		let mut states_map = HashMap::new();
1024
1025		// The basis configuration set for the first state is all rules which have the start symbol as their left-hand side
1026		for n_rule in start.sym_rules_arr.iter()
1027		{	rules[*n_rule].lhs_start = true;
1028			Self::configlist_add(rules, &mut configs_basis_keys_arr, &mut configs_basis_arr, &mut configs_arr, &mut configs_map, n_terminals, *n_rule, 0, true).borrow_mut().fws.add(0);
1029		}
1030
1031		// Compute the first state. All other states will be computed automatically during the computation of the first one.
1032		// The returned pointer to the first state is not used.
1033		Self::getstate(symbols, rules, &mut configs_basis_keys_arr, &mut configs_basis_arr, &mut configs_arr, &mut configs_map, &mut states_map, n_terminals, actions_enum)?;
1034
1035		let mut states = States {array: Vec::with_capacity(states_map.len()), n_no_tail: 0}; // Table of states sorted by state number
1036		for (_, elem) in states_map
1037		{	states.array.push(Rc::try_unwrap(elem).unwrap().into_inner());
1038		}
1039		states.array.sort_by(|a, b| a.n_state.cmp(&b.n_state));
1040		states.n_no_tail = states.array.len();
1041		Ok(states)
1042	}
1043
1044	/// Return a pointer to a state which is described by the configuration list which has been built from calls to configlist_add.
1045	fn getstate
1046	(	symbols: &Symbols,
1047		rules: &Vec<Rule>,
1048		configs_basis_keys_arr: &mut Vec<ConfigKey>,
1049		configs_basis_arr: &mut Vec<Rc<RefCell<Config>>>,
1050		configs_arr: &mut Vec<Rc<RefCell<Config>>>,
1051		configs_map: &mut HashMap<ConfigKey, Rc<RefCell<Config>>>,
1052		states_map: &mut HashMap<Vec<ConfigKey>, Rc<RefCell<State>>>,
1053		n_terminals: usize,
1054		actions_enum: &mut i32,
1055	) -> ParserResult<usize>
1056	{	// Extract the sorted basis of the new state.  The basis was constructed by prior calls to "configlist_add(*, *, *, true)".
1057		let mut basis_keys = mem::replace(configs_basis_keys_arr, Vec::new());
1058		let mut basis = mem::replace(configs_basis_arr, Vec::new());
1059		basis_keys.sort();
1060		basis.sort();
1061
1062		// Find a state with the same basis
1063		if let Some(found) = states_map.get(&basis_keys)
1064		{	let found = found.borrow();
1065			let n_state = found.n_state;
1066			// A state with the same basis already exists!  Copy all the follow-set propagation links from the state under construction into the
1067			// preexisting state, then return a pointer to the preexisting state
1068			for (i, x) in basis.iter().enumerate()
1069			{	let mut y = found.basis[i].borrow_mut();
1070				if let Ok(mut x) = x.try_borrow_mut()
1071				{	mem::swap(&mut x.bplp, &mut y.bplp);
1072					y.bplp.reserve(x.bplp.len());
1073					for config in x.bplp.iter()
1074					{	y.bplp.push(Rc::clone(config));
1075					}
1076				}
1077				else
1078				{	// assume x and y are the same object
1079					let len = y.bplp.len();
1080					y.bplp.reserve(len);
1081					for i in 0 .. len
1082					{	let o = Rc::clone(&y.bplp[i]);
1083						y.bplp.push(o);
1084					}
1085				}
1086			}
1087			configs_arr.clear();
1088			Ok(n_state)
1089		}
1090		else
1091		{	// This really is a new state.  Construct all the details
1092			Self::configlist_closure(symbols, rules, configs_basis_keys_arr, configs_basis_arr, configs_arr, configs_map, n_terminals)?; // Compute the configuration closure
1093			let n_state = states_map.len();
1094			let mut configurations = mem::replace(configs_arr, Vec::new());
1095			configurations.sort(); // Sort the configuration closure
1096			let stp = State::new // A new state structure
1097			(	n_state, // Every state gets a sequence number
1098				basis, // Remember the configuration basis
1099				configurations // Remember the configuration closure
1100			);
1101			let stp = Rc::new(RefCell::new(stp));
1102			states_map.insert(basis_keys, Rc::clone(&stp)); // Add to the state table
1103			let actions = Self::buildshifts(symbols, rules, configs_basis_keys_arr, configs_basis_arr, configs_arr, configs_map, states_map, n_terminals, actions_enum, &stp)?; // Recursively compute successor states
1104			stp.borrow_mut().actions = actions;
1105			Ok(n_state)
1106		}
1107	}
1108
1109	/// Construct all successor states to the given state.  A "successor" state is any state which can be reached by a shift action.
1110	fn buildshifts
1111	(	symbols: &Symbols,
1112		rules: &Vec<Rule>,
1113		configs_basis_keys_arr: &mut Vec<ConfigKey>,
1114		configs_basis_arr: &mut Vec<Rc<RefCell<Config>>>,
1115		configs_arr: &mut Vec<Rc<RefCell<Config>>>,
1116		configs_map: &mut HashMap<ConfigKey, Rc<RefCell<Config>>>,
1117		states_map: &mut HashMap<Vec<ConfigKey>, Rc<RefCell<State>>>,
1118		n_terminals: usize,
1119		actions_enum: &mut i32,
1120		stp: &Rc<RefCell<State>>
1121	) -> ParserResult<Vec<Rc<RefCell<Action>>>>
1122	{	let mut actions = Vec::new();
1123
1124		// Each configuration becomes complete after it contibutes to a successor state.  Initially, all configurations are incomplete
1125		for cfp in stp.borrow().configurations.iter()
1126		{	cfp.borrow_mut().status_is_complete = false;
1127		}
1128
1129		// Loop through all configurations of the state "stp"
1130		for (i, cfp) in stp.borrow().configurations.iter().enumerate()
1131		{	let (status_is_complete, dot, n_rule) =
1132			{	let cfp = cfp.borrow();
1133				(cfp.status_is_complete, cfp.dot, cfp.n_rule)
1134			};
1135			if !status_is_complete && dot<rules[n_rule].rhs.len() // !Already used by inner loop && !Can't shift this config
1136			{	configs_basis_keys_arr.clear();
1137				configs_basis_arr.clear();
1138				configs_arr.clear();
1139				configs_map.clear();
1140				let sp = rules[n_rule].rhs[dot].index; // Symbol following the dot in configuration "cfp"
1141
1142				// For every configuration in the state "stp" which has the symbol "sp" following its dot, add the same configuration to the basis set under
1143				// construction but with the dot shifted one symbol to the right.
1144				for bcfp in stp.borrow().configurations.iter().skip(i)
1145				{	if !bcfp.borrow().status_is_complete && bcfp.borrow().dot<rules[bcfp.borrow().n_rule].rhs.len() // !Already used && !Can't shift this one
1146					{	let bsp = rules[bcfp.borrow().n_rule].rhs[bcfp.borrow().dot].index; // Symbol following the dot in configuration "bcfp"
1147						if bsp == sp // Must be same as for "cfp"
1148						{	bcfp.borrow_mut().status_is_complete = true; // Mark this config as used
1149							let newcfg = Self::configlist_add(rules, configs_basis_keys_arr, configs_basis_arr, configs_arr, configs_map, n_terminals, bcfp.borrow().n_rule, bcfp.borrow().dot+1, true);
1150							newcfg.borrow_mut().bplp.push(Rc::clone(bcfp));
1151						}
1152					}
1153				}
1154
1155				// Get a pointer to the state described by the basis configuration set constructed in the preceding loop
1156				let n_state = Self::getstate(symbols, rules, configs_basis_keys_arr, configs_basis_arr, configs_arr, configs_map, states_map, n_terminals, actions_enum)?; // A pointer to a successor state
1157
1158				// The state "newstp" is reached from the state "stp" by a shift action on the symbol "sp"
1159				actions.insert(0, Rc::new(RefCell::new(Action::new_state(*actions_enum, sp, n_state)))); // TODO: maybe push(), not insert()
1160				*actions_enum += 1;
1161			}
1162		}
1163		Ok(actions)
1164	}
1165
1166	/// Add another configuration to the configuration list.
1167	/// dot - Index into the RHS of the rule where the dot goes
1168	fn configlist_add
1169	(	rules: &Vec<Rule>,
1170		configs_basis_keys_arr: &mut Vec<ConfigKey>,
1171		configs_basis_arr: &mut Vec<Rc<RefCell<Config>>>,
1172		configs_arr: &mut Vec<Rc<RefCell<Config>>>,
1173		configs_map: &mut HashMap<ConfigKey, Rc<RefCell<Config>>>,
1174		n_terminals: usize,
1175		n_rule: usize,
1176		dot: usize,
1177		is_basis: bool
1178	) -> Rc<RefCell<Config>>
1179	{	let key = ConfigKey {n_rule: rules[n_rule].index, dot};
1180
1181		if let Some(found) = configs_map.get(&key)
1182		{	Rc::clone(found)
1183		}
1184		else
1185		{	let cfp =  Rc::new(RefCell::new(Config::new(n_rule, dot, n_terminals+1)));
1186			configs_arr.push(Rc::clone(&cfp));
1187			let key = ConfigKey::new(&cfp.borrow());
1188			if is_basis
1189			{	configs_basis_keys_arr.push(key);
1190				configs_basis_arr.push(Rc::clone(&cfp));
1191			}
1192			configs_map.insert(key, Rc::clone(&cfp));
1193			cfp
1194		}
1195	}
1196
1197	/// Compute the closure of the configuration list
1198	fn configlist_closure
1199	(	symbols: &Symbols,
1200		rules: &Vec<Rule>,
1201		configs_basis_keys_arr: &mut Vec<ConfigKey>,
1202		configs_basis_arr: &mut Vec<Rc<RefCell<Config>>>,
1203		configs_arr: &mut Vec<Rc<RefCell<Config>>>,
1204		configs_map: &mut HashMap<ConfigKey, Rc<RefCell<Config>>>,
1205		n_terminals: usize
1206	) -> ParserResult<()>
1207	{	let mut c = 0;
1208		while c < configs_arr.len() // size of configs_arr increases during this loop
1209		{	let (rule, dot) =
1210			{	let config = configs_arr[c].borrow();
1211				(&rules[config.n_rule], config.dot)
1212			};
1213			if dot < rule.rhs.len()
1214			{	let sp = &symbols.array[rule.rhs[dot].index];
1215				if sp.typ == SymbolType::NONTERMINAL
1216				{	if sp.index!=symbols.error_symbol_index && sp.sym_rules_arr.is_empty()
1217					{	return Err(LemonMintError::new(&rule.rule_filename, rule.rule_n_line, format!("Nonterminal \"{}\" has no rules.", sp.name)));
1218					}
1219					for new_n_rule in sp.sym_rules_arr.iter()
1220					{	let newcfp = Self::configlist_add(rules, configs_basis_keys_arr, configs_basis_arr, configs_arr, configs_map, n_terminals, *new_n_rule, 0, false);
1221						let mut found = false;
1222						for i in dot+1 .. rule.rhs.len()
1223						{	let xsp = &symbols.array[rule.rhs[i].index];
1224							if xsp.typ == SymbolType::TERMINAL
1225							{	newcfp.borrow_mut().fws.add(xsp.index);
1226								found = true;
1227								break;
1228							}
1229							newcfp.borrow_mut().fws.intersect(&xsp.firstset);
1230							if !xsp.lambda
1231							{	found = true;
1232								break;
1233							}
1234						}
1235						if !found
1236						{	configs_arr[c].borrow_mut().fplp.insert(0, newcfp); // TODO: maybe push(), not insert()
1237						}
1238					}
1239				}
1240			}
1241			c += 1;
1242		}
1243		Ok(())
1244	}
1245}
1246
1247#[derive(Debug)]
1248struct StringInFile
1249{	filename: Arc<String>,
1250	n_line: usize,
1251	string: String,
1252}
1253
1254#[derive(Debug)]
1255struct PrecedenceInFile
1256{	filename: Arc<String>,
1257	n_line: usize,
1258	assoc: Associativity,
1259	precedence: i32,
1260}
1261
1262struct ArrayFormatter
1263{	i: usize,
1264	values_on_line: usize,
1265	endl: &'static str,
1266}
1267impl ArrayFormatter
1268{	pub fn new(values_on_line: usize) -> Self
1269	{	Self
1270		{	i: 0,
1271			values_on_line,
1272			endl: "\n[\t",
1273		}
1274	}
1275
1276	pub fn separ<W>(&mut self, out: &mut W) -> io::Result<()> where W: io::Write
1277	{	if self.i % self.values_on_line == 0
1278		{	write!(out, "{}/* {:5} */  ", self.endl, self.i)?;
1279			self.endl = ",\n\t";
1280		}
1281		else
1282		{	write!(out, ", ")?;
1283		}
1284		self.i += 1;
1285		Ok(())
1286	}
1287
1288	pub fn end<W>(self, out: &mut W) -> io::Result<()> where W: io::Write
1289	{	writeln!(out, "{}];", if self.i==0 {" ["} else {"\n"})
1290	}
1291}
1292
1293/// Builder class that will finally generate `LemonMint`. Call builder methods to supply parser rules and options - everything that you would normally put to Lemon's Y-grammar file.
1294/// Or you can feed the Y-file itself (it's syntax is similar to Lemon's one).
1295///
1296/// # Example
1297///
1298/// ```
1299/// use lemon_mint::LemonMintBuilder;
1300/// use std::sync::Arc;
1301///
1302/// let fake_filename = Arc::new("source.y".to_string()); // will appear in error messages
1303/// let builder = LemonMintBuilder::new().load_y(&fake_filename, "%token_type {f64}\nUnit ::= NEW_LINE.".as_bytes()).unwrap();
1304/// let lemon = builder.try_into_lemon().unwrap();
1305/// ```
1306///
1307/// Or:
1308///
1309/// ```
1310/// use lemon_mint::LemonMintBuilder;
1311/// use std::sync::Arc;
1312///
1313/// let fake_filename = Arc::new("source.y".to_string()); // will appear in error messages
1314/// let builder = LemonMintBuilder::new()
1315/// 	.set_token_type("f64".to_string()).unwrap()
1316/// 	.add_rule(&fake_filename, 1, "Unit".to_string(), "NEW_LINE", "".to_string()).unwrap();
1317/// let lemon = builder.try_into_lemon().unwrap();
1318/// ```
1319#[derive(Debug)]
1320pub struct LemonMintBuilder
1321{	rules: Vec<Rule>,                  // All rules
1322	token_type: String,                // Type of terminal symbols in the parser stack
1323	vartype: String,                   // The default type of non-terminal symbols
1324	start_name: String,                // Name of the start symbol for the grammar
1325	with_trace: bool,
1326	trace_prompt: String,              // Prompt to preface each trace message, if with_trace is true
1327	extracode: String,                 // Code appended to the generated file
1328	n_conflicts: usize,                // Number of parsing conflicts
1329	n_action_table_entries: usize,     // Number of entries in the yy_action[] table
1330	tables_size: usize,                // Total table size of all tables in bytes
1331	has_fallback: bool,                // True if any %fallback is seen in the grammar
1332	symbols_builder: SymbolsBuilder,
1333	prec_counter: i32,
1334	actions_enum: i32,
1335	nonterminal_types: HashMap<String, StringInFile>,
1336	precedence: HashMap<String, PrecedenceInFile>,
1337	extra_argument_type: String,
1338	min_shift_reduce: usize,
1339	error_action: usize,
1340	accept_action: usize,
1341	no_action: usize,
1342	min_reduce: usize,
1343	max_action: usize,
1344	no_compress: bool,                 // Don't compress the action table
1345	no_resort: bool,                   // Do not sort or renumber states
1346}
1347impl LemonMintBuilder
1348{	/// Creates new builder
1349	pub fn new() -> Self
1350	{	Self
1351		{	rules: Vec::with_capacity(64),
1352			token_type: String::new(),
1353			vartype: String::new(),
1354			start_name: String::new(),
1355			with_trace: false,
1356			trace_prompt: String::new(),
1357			extracode: String::new(),
1358			n_conflicts: 0,
1359			n_action_table_entries: 0,
1360			tables_size: 0,
1361			has_fallback: false,
1362			symbols_builder: SymbolsBuilder::new(false),
1363			prec_counter: 1,
1364			actions_enum: 0,
1365			nonterminal_types: HashMap::new(),
1366			precedence: HashMap::new(),
1367			extra_argument_type: String::new(),
1368			min_shift_reduce: 0,
1369			error_action: 0,
1370			accept_action: 0,
1371			no_action: 0,
1372			min_reduce: 0,
1373			max_action: 0,
1374			no_compress: false,
1375			no_resort: false,
1376		}
1377	}
1378
1379	/// Find a precedence symbol of every rule in the grammar.
1380	///
1381	/// Those rules which have a precedence symbol coded in the input grammar using the `"[symbol]"` construct will already have the
1382	/// rule->precsym field filled.  Other rules take as their precedence symbol the first RHS symbol with a defined precedence.  If there
1383	/// are not RHS symbols with a defined precedence, the precedence symbol field is left blank.
1384	fn find_rule_precedences(symbols: &mut Symbols, rules: &mut Vec<Rule>)
1385	{	for rule in rules.iter_mut()
1386    	{	if rule.precsym_index == std::usize::MAX
1387			{	for sp in &rule.rhs
1388				{	if symbols.array[sp.index].prec >= 0
1389					{	rule.precsym_index = sp.index;
1390						break;
1391					}
1392				}
1393			}
1394		}
1395	}
1396
1397	/// Find all nonterminals which will generate the empty string.  Then go back and compute the first sets of every nonterminal.
1398	/// The first set is the set of all terminal symbols which can begin a string generated by that nonterminal.
1399	fn find_first_sets(&self, symbols: &mut Symbols, rules: &mut Vec<Rule>)
1400	{	for (i, symbol) in symbols.array[0 .. symbols.n_symbols].iter_mut().enumerate()
1401		{	symbol.lambda = false;
1402			if i >= symbols.n_terminals
1403			{	symbol.firstset.set_size(symbols.n_terminals + 1);
1404			}
1405		}
1406
1407		// First compute all lambdas
1408		let mut progress = true;
1409		while progress
1410		{	progress = false;
1411'l:			for rule in rules.iter()
1412			{	let rule = rule;
1413				if !symbols.array[rule.lhs_index].lambda
1414				{	for sp in &rule.rhs
1415					{	let sp = &symbols.array[sp.index];
1416						assert!(sp.typ==SymbolType::NONTERMINAL || !sp.lambda);
1417						if !sp.lambda
1418						{	continue 'l;
1419						}
1420					}
1421					symbols.array[rule.lhs_index].lambda = true;
1422					progress = true;
1423				}
1424			}
1425		}
1426
1427		// Now compute all first sets
1428		progress = true;
1429		while progress
1430		{	progress = false;
1431			for rule in rules.iter()
1432			{	for rhs in &rule.rhs
1433				{	if symbols.array[rhs.index].typ == SymbolType::TERMINAL
1434					{	if symbols.array[rule.lhs_index].firstset.add(rhs.index)
1435						{	progress = true;
1436						}
1437						break;
1438					}
1439					else if rule.lhs_index == rhs.index
1440					{	if !symbols.array[rule.lhs_index].lambda
1441						{	break;
1442						}
1443					}
1444					else
1445					{	let set = mem::replace(&mut symbols.array[rhs.index].firstset, Set::new(0));
1446						if symbols.array[rule.lhs_index].firstset.intersect(&set)
1447						{	progress = true;
1448						}
1449						symbols.array[rhs.index].firstset = set;
1450						if !symbols.array[rhs.index].lambda
1451						{	break;
1452						}
1453					}
1454				}
1455			}
1456		}
1457	}
1458
1459	/// Construct the propagation links
1460	fn find_links(states: &States)
1461    {	// Housekeeping detail:
1462		// Add to every propagate link a pointer back to the state to which the link is attached.
1463		for stp in states.array.iter()
1464		{	for cfp in stp.configurations.iter()
1465			{	cfp.borrow_mut().n_state = stp.n_state;
1466			}
1467		}
1468
1469		// Convert all backlinks into forward links.
1470    	// Only the forward links are used in the follow-set computation.
1471    	for stp in states.array.iter()
1472    	{	for cfp in stp.configurations.iter()
1473    		{	for plp in cfp.borrow().bplp.iter()
1474    			{	plp.borrow_mut().fplp.insert(0, Rc::clone(&cfp)); // TODO: maybe push(), not insert()
1475    			}
1476    		}
1477    	}
1478    }
1479
1480	/// Compute all followsets.
1481    ///
1482    /// A followset is the set of all symbols which can come immediately after a configuration.
1483    fn find_follow_sets(states: &States)
1484    {	for stp in states.array.iter()
1485    	{	for cfp in stp.configurations.iter()
1486    		{	cfp.borrow_mut().status_is_complete = false;
1487    		}
1488    	}
1489
1490    	let mut progress = true;
1491		while progress
1492		{	progress = false;
1493    		for stp in states.array.iter()
1494    		{	for cfp in stp.configurations.iter()
1495    			{	if !cfp.borrow().status_is_complete
1496					{	for plp in cfp.borrow().fplp.iter()
1497						{	let mut plp = plp.borrow_mut();
1498							if plp.fws.intersect(&cfp.borrow().fws) // if changed
1499							{	plp.status_is_complete = false;
1500								progress = true;
1501							}
1502						}
1503						cfp.borrow_mut().status_is_complete = true;
1504					}
1505    			}
1506    		}
1507    	}
1508    }
1509
1510	/// Resolve a conflict between the two given actions.  If the conflict can't be resolved, return non-zero.
1511    ///
1512    /// NO LONGER TRUE:
1513    ///   To resolve a conflict, first look to see if either action is on an error rule.  In that case, take the action which
1514    ///   is not associated with the error rule.  If neither or both actions are associated with an error rule, then try to
1515    ///   use precedence to resolve the conflict.
1516    ///
1517    /// If either action is a SHIFT, then it must be apx.  This function won't work if apx->type==REDUCE and apy->type==SHIFT.
1518    fn resolve_conflict(symbols: &Symbols, rules: &mut Vec<Rule>, apx: &Rc<RefCell<Action>>, apy: &Rc<RefCell<Action>>) -> usize
1519	{	let mut errcnt = 0;
1520		let mut apx = apx.borrow_mut();
1521		let mut apy = apy.borrow_mut();
1522		assert_eq!(apx.symbol_index, apy.symbol_index);  // Otherwise there would be no conflict
1523		let mut apx_typ = apx.typ;
1524		let mut apy_typ = apy.typ;
1525		if apx_typ==ActionType::Shift && apy_typ==ActionType::Shift
1526		{	apy_typ = ActionType::SsConflict;
1527			errcnt += 1;
1528		}
1529		if apx_typ==ActionType::Shift && apy_typ==ActionType::Reduce
1530		{	let spx = &symbols.array[apx.symbol_index];
1531			if let StateOrRule::Rule(n_rule) = apy.x
1532			{	let spy = rules[n_rule].precsym_index;
1533				if spy != std::usize::MAX
1534				{	let spy = &symbols.array[spy];
1535					if spx.prec<0 || spy.prec<0
1536					{	// Not enough precedence information.
1537						apy_typ = ActionType::SrConflict;
1538						errcnt += 1;
1539					}
1540					else if spx.prec > spy.prec    // higher precedence wins
1541					{	apy_typ = ActionType::RdResolved;
1542					}
1543					else if spx.prec < spy.prec
1544					{	apx_typ = ActionType::ShResolved;
1545					}
1546					else if spx.prec==spy.prec && spx.assoc== Associativity::RIGHT // Use operator
1547					{	apy_typ = ActionType::RdResolved;                          // associativity
1548					}
1549					else if spx.prec==spy.prec && spx.assoc== Associativity::LEFT  // to break tie
1550					{	apx_typ = ActionType::ShResolved;
1551					}
1552					else
1553					{	assert!(spx.prec==spy.prec && spx.assoc== Associativity::NONASSOC);
1554						apy_typ = ActionType::Error;
1555					}
1556				}
1557				else
1558				{	// Not enough precedence information.
1559					apy_typ = ActionType::SrConflict;
1560					errcnt += 1;
1561				}
1562			}
1563		}
1564		else if apx_typ==ActionType::Reduce && apy_typ==ActionType::Reduce
1565		{	if let StateOrRule::Rule(n_rule_x) = apx.x
1566			{	if let StateOrRule::Rule(n_rule_y) = apy.x
1567				{	let spx = rules[n_rule_x].precsym_index;
1568					let spy = rules[n_rule_y].precsym_index;
1569					if spx != std::usize::MAX
1570					{	if spy != std::usize::MAX
1571						{	let spx = &symbols.array[spx];
1572							let spy = &symbols.array[spy];
1573							if spx.prec<0 || spy.prec<0 || spx.prec==spy.prec
1574							{	apy_typ = ActionType::RrConflict;
1575								errcnt += 1;
1576							}
1577							else if spx.prec > spy.prec
1578							{	apy_typ = ActionType::RdResolved;
1579							}
1580							else if spx.prec < spy.prec
1581							{	apx_typ = ActionType::RdResolved;
1582							}
1583						}
1584						else
1585						{	apy_typ = ActionType::RrConflict;
1586							errcnt += 1;
1587						}
1588					}
1589					else
1590					{	apy_typ = ActionType::RrConflict;
1591						errcnt += 1;
1592					}
1593				}
1594			}
1595		}
1596		else
1597		{	assert!
1598			(	apx_typ == ActionType::ShResolved ||
1599				apx_typ == ActionType::RdResolved ||
1600				apx_typ == ActionType::SsConflict ||
1601				apx_typ == ActionType::SrConflict ||
1602				apx_typ == ActionType::RrConflict ||
1603				apy_typ == ActionType::ShResolved ||
1604				apy_typ == ActionType::RdResolved ||
1605				apy_typ == ActionType::SsConflict ||
1606				apy_typ == ActionType::SrConflict ||
1607				apy_typ == ActionType::RrConflict
1608			);
1609			// The REDUCE/SHIFT case cannot happen because SHIFTs come before REDUCEs on the list.  If we reach this point it must be because
1610			// the parser conflict had already been resolved.
1611		}
1612		apx.typ = apx_typ;
1613		apy.typ = apy_typ;
1614		errcnt
1615    }
1616
1617	/// Compute the reduce actions, and resolve conflicts.
1618    fn find_actions(&mut self, symbols: &Symbols, rules: &mut Vec<Rule>, states: &mut States) -> ParserResult<()>
1619    {	// Add all of the reduce actions
1620    	// A reduce action is added for each element of the followset of a configuration which has its dot at the extreme right.
1621    	for stp in states.array.iter_mut()   // Loop over all states
1622    	{	for cfp in stp.configurations.iter()  // Loop over all configurations
1623    		{	if cfp.borrow().dot == rules[cfp.borrow().n_rule].rhs.len()  // Is dot at extreme right?
1624    			{	for (j, symbol) in symbols.array.iter().take(symbols.n_terminals).enumerate()
1625    				{	if cfp.borrow().fws.contains(j)
1626    					{	// Add a reduce action to the state "stp" which will reduce by the rule "cfp->rule" if the lookahead symbol is "symbols[j]"
1627    						stp.actions.push(Rc::new(RefCell::new(Action::new_rule(self.actions_enum, symbol.index, ActionType::Reduce, cfp.borrow().n_rule))));
1628							self.actions_enum += 1;
1629    					}
1630    				}
1631    			}
1632    		}
1633    	}
1634
1635    	// Add the accepting token
1636    	// Add to the first state (which is always the starting state of the finite state machine) an action to ACCEPT if the lookahead is the start nonterminal.
1637    	states.array[0].actions.push(Rc::new(RefCell::new(Action::new_empty_rule(self.actions_enum, symbols.start_symbol_index, ActionType::Accept))));
1638		self.actions_enum += 1;
1639
1640    	// Resolve conflicts
1641    	for stp in states.array.iter_mut()
1642    	{	if stp.actions.len() != 0
1643    		{	stp.actions.sort();
1644    			for action in stp.actions.windows(2)
1645				{	if action[0].borrow().symbol_index == action[1].borrow().symbol_index
1646    				{	// The two actions "action[0]" and "action[1]" have the same lookahead.
1647    					// Figure out which one should be used
1648    					self.n_conflicts += Self::resolve_conflict(symbols, rules, &action[0], &action[1]);
1649    				}
1650				}
1651    		}
1652    	}
1653
1654    	// Report an error for each rule that can never be reduced.
1655    	for stp in states.array.iter_mut()
1656    	{	for action in stp.actions.iter()
1657    		{	if action.borrow().typ == ActionType::Reduce
1658				{	if let StateOrRule::Rule(n_rule) = action.borrow().x
1659					{	rules[n_rule].can_reduce = true;
1660					}
1661				}
1662    		}
1663    	}
1664    	for rule in rules.iter()
1665		{	if !rule.can_reduce
1666			{	return Err(LemonMintError::new(&rule.rule_filename, rule.rule_n_line, "This rule can not be reduced.\n".to_string()));
1667			}
1668		}
1669		Ok(())
1670    }
1671
1672	fn get_filename_of_first_rule(rules: &Vec<Rule>) -> Arc<String>
1673	{	if let Some(rule) = rules.iter().next()
1674		{	return Arc::clone(&rule.rule_filename);
1675		}
1676		Arc::new("".to_string())
1677	}
1678
1679	/// Reduce the size of the action tables, if possible, by making use of defaults.
1680	///
1681	/// In this version, we take the most frequent REDUCE action and make it the default.
1682	fn compress_tables(&self, symbols: &Symbols, rules: &Vec<Rule>, states: &mut States, default_symbol_index: usize)
1683	{	for state in states.array.iter_mut()
1684		{	let mut n_best = 0;
1685			let mut r_best = std::usize::MAX;
1686
1687			let mut it = state.actions.iter();
1688			while let Some(action) = it.next()
1689			{	if action.borrow().typ == ActionType::Reduce
1690				{	if let StateOrRule::Rule(n_rule) = action.borrow().x
1691					{	let rule = &rules[n_rule];
1692						if !rule.lhs_start && n_rule != r_best
1693						{	let mut n = 1;
1694							let mut it2 = it.clone();
1695							while let Some(ap2) = it2.next()
1696							{	if ap2.borrow().typ == ActionType::Reduce
1697								{	if let StateOrRule::Rule(n_rule_2) = ap2.borrow().x
1698									{	if n_rule_2 != r_best && n_rule_2 == n_rule
1699										{	n += 1;
1700										}
1701									}
1702								}
1703							}
1704							if n > n_best
1705							{	n_best = n;
1706								r_best = n_rule;
1707							}
1708						}
1709					}
1710				}
1711			}
1712
1713			// Do not make a default if the number of rules to default is not at least 1
1714			if n_best < 1
1715			{	continue;
1716			}
1717
1718			// Combine matching REDUCE actions into a single default
1719			let mut found = false;
1720			for action in state.actions.iter()
1721			{	let mut action =  action.borrow_mut();
1722				if action.typ == ActionType::Reduce
1723				{	if let StateOrRule::Rule(n_rule) = action.x
1724					{	if rules[n_rule].index == r_best
1725						{	if !found
1726							{	action.symbol_index = default_symbol_index;
1727								found = true;
1728							}
1729							else
1730							{	action.typ = ActionType::NotUsed;
1731							}
1732						}
1733					}
1734				}
1735			}
1736			assert!(found);
1737			state.actions.sort();
1738
1739			found = false;
1740			for action in state.actions.iter()
1741			{	let action = action.borrow();
1742				if action.typ==ActionType::Shift || action.typ==ActionType::Reduce && match action.x {StateOrRule::Rule(n_rule) => rules[n_rule].index != r_best, _ => false}
1743				{	found = true;
1744					break;
1745				}
1746			}
1747			if !found
1748			{	state.auto_reduce = true;
1749				state.default_reduce_rule = r_best;
1750			}
1751		}
1752
1753		// Make a second pass over all states and actions.  Convert every action that is a SHIFT to an autoReduce state into a SHIFTREDUCE action.
1754		for stp in states.array.iter()
1755		{	for action in stp.actions.iter()
1756			{	let mut action = action.borrow_mut();
1757				if action.typ == ActionType::Shift
1758				{	if let StateOrRule::State(next_n_state) = action.x
1759					{	let next_state = &states.array[next_n_state];
1760						if next_state.auto_reduce && next_state.default_reduce_rule!=std::usize::MAX
1761						{	action.typ = ActionType::ShiftReduce;
1762							action.x = StateOrRule::Rule(next_state.default_reduce_rule);
1763						}
1764					}
1765				}
1766			}
1767		}
1768
1769		// If a SHIFTREDUCE action specifies a rule that has a single RHS term (meaning that the SHIFTREDUCE will land back in the state where it
1770		// started) and if there is no C-code associated with the reduce action, then we can go ahead and convert the action to be the same as the
1771		// action for the RHS of the rule.
1772		for stp in states.array.iter()
1773		{	for action in stp.actions.iter()
1774			{	let mut done = false;
1775				while !done
1776				{	done = true;
1777					let mut ap2 = None;
1778					{	let action = action.borrow();
1779						if action.typ == ActionType::ShiftReduce
1780						{	if let StateOrRule::Rule(n_rule) = action.x
1781							{	let rp = &rules[n_rule];
1782								if rp.code.is_empty() && rp.rhs.len()==1
1783								{	// Only apply this optimization to non-terminals.  It would be OK to apply it to terminal symbols too, but that makes the parser tables larger.
1784									if action.symbol_index >= symbols.n_terminals
1785									{	// If we reach this point, it means the optimization can be applied
1786										ap2 = stp.actions.iter().find
1787										(	|a|
1788											{	let a = a.borrow();
1789												a.id!= action.id && a.symbol_index==rp.lhs_index
1790											}
1791										);
1792										assert!(ap2.is_some());
1793										done = false;
1794									}
1795								}
1796							}
1797						}
1798					}
1799					if let Some(ap2) = ap2
1800					{	let mut action = action.borrow_mut();
1801						let ap2 = ap2.borrow();
1802						action.symbol_index_opt = ap2.symbol_index;
1803						action.typ = ap2.typ;
1804						action.x = ap2.x;
1805					}
1806				}
1807			}
1808		}
1809	}
1810
1811	/// Given an action, compute the integer value for that action which is to be put in the action table of the generated machine.
1812	/// Return negative if no action should be generated.
1813	fn compute_action(&self, symbols: &Symbols, action: &Rc<RefCell<Action>>) -> usize
1814	{	let action = action.borrow();
1815		match action.typ
1816		{	ActionType::Shift =>
1817			{	match action.x
1818				{	StateOrRule::State(n_state) => n_state,
1819					_ => std::usize::MAX
1820				}
1821			}
1822			ActionType::ShiftReduce =>
1823			{	// Since a SHIFT is inherient after a prior REDUCE, convert any SHIFTREDUCE action with a nonterminal on the LHS into a simple REDUCE action:
1824				match action.x
1825				{	StateOrRule::Rule(n_rule) =>
1826					{	if action.symbol_index >= symbols.n_terminals
1827						{	self.min_reduce + n_rule
1828						}
1829						else
1830						{	self.min_shift_reduce + n_rule
1831						}
1832					},
1833					_ => std::usize::MAX
1834				}
1835			}
1836			ActionType::Reduce =>
1837			{	match action.x
1838				{	StateOrRule::Rule(n_rule) => self.min_reduce + n_rule,
1839					_ => std::usize::MAX
1840				}
1841			}
1842			ActionType::Error =>
1843			{	self.error_action
1844			}
1845			ActionType::Accept =>
1846			{	self.accept_action
1847			}
1848			_ => std::usize::MAX
1849		}
1850	}
1851
1852	/// Renumber and resort states so that states with fewer choices occur at the end.  Except, keep state 0 as the first state.
1853	fn resort_states(&mut self, symbols: &Symbols, states: &mut States)
1854	{	let sorted_len = states.array.len();
1855		for stp in states.array.iter_mut()
1856		{	stp.n_token_act = 0;
1857			stp.n_nt_act = 0;
1858			stp.default_reduce_action = std::usize::MAX; // Init dflt action to "syntax error"
1859			stp.token_offset = std::isize::MIN;
1860			stp.nt_offset = std::isize::MIN;
1861			for action in stp.actions.iter()
1862			{	let n_action = self.compute_action(symbols, action);
1863				if n_action != std::usize::MAX
1864				{	let action = action.borrow();
1865					if action.symbol_index < symbols.n_terminals
1866					{	stp.n_token_act += 1;
1867					}
1868					else if action.symbol_index < symbols.n_symbols
1869					{	stp.n_nt_act += 1;
1870					}
1871					else
1872					{	assert!(!stp.auto_reduce || action.x == StateOrRule::Rule(stp.default_reduce_rule));
1873						stp.default_reduce_action = n_action;
1874					}
1875				}
1876			}
1877		}
1878
1879		// Compare two states for sorting purposes.  The smaller state is the one with the most non-terminal actions.
1880		// If they have the same number of non-terminal actions, then the smaller is the one with the most token actions.
1881		if sorted_len > 2
1882		{	states.array[1 ..].sort_by
1883			(	|a, b|
1884				{	let mut res = b.n_nt_act.cmp(&a.n_nt_act);
1885					if res == Ordering::Equal
1886					{	res = b.n_token_act.cmp(&a.n_token_act);
1887						if res == Ordering::Equal
1888						{	res = b.n_state.cmp(&a.n_state);
1889						}
1890					}
1891					res
1892				}
1893			);
1894		}
1895
1896		// update also in actions and configurations
1897		let mut map = Vec::new();
1898		map.resize(states.array.len(), 0);
1899		for (i, stp) in states.array.iter().enumerate()
1900		{	map[stp.n_state] = i;
1901		}
1902		for stp in states.array.iter()
1903		{	for action in stp.actions.iter()
1904			{	if let StateOrRule::State(ref mut state) = action.borrow_mut().x
1905				{	*state = map[*state];
1906				}
1907			}
1908			for configuration in stp.configurations.iter()
1909			{	let mut configuration = configuration.borrow_mut();
1910				configuration.n_state = map[configuration.n_state];
1911			}
1912		}
1913
1914		// update self
1915		for (new_n_state, stp) in states.array.iter_mut().enumerate()
1916		{	stp.n_state = new_n_state;
1917		}
1918
1919		while states.n_no_tail>1 && states.array[states.n_no_tail-1].auto_reduce
1920		{	states.n_no_tail -= 1;
1921		}
1922	}
1923
1924	/// Return the name of a C datatype able to represent values between lwr and upr, inclusive.
1925	fn minimum_size_type(lower: isize, upper: isize) -> isize
1926	{	if lower >= 0
1927		{	if upper <= 255
1928			{	1
1929			}
1930			else if upper < 65535
1931			{	2
1932			}
1933			else
1934			{	4
1935			}
1936		}
1937		else
1938		{	if lower>=-127 && upper<=127
1939			{	-1
1940			}
1941			else if lower>=-32767 && upper<32767
1942			{	-2
1943			}
1944			else
1945			{	-4
1946			}
1947		}
1948	}
1949
1950	/// zCode is a string that is the action associated with a rule.  Expand the symbols in this string so that the refer to elements of the parser stack.
1951	fn translate_code(&self, rule: &mut Rule) -> ParserResult<()>
1952	{	let mut used = Vec::new();   // True for each RHS element which is used
1953		used.resize(rule.rhs.len(), false);
1954
1955		let mut it = rule.code.chars();
1956		let mut it_prev = it.clone();
1957
1958		while let Some(cp) = it.next()
1959		{	if cp.is_ascii_alphabetic()
1960			{	let ident: String = it_prev.take_while(|c| c.is_ascii_alphanumeric() || *c=='_').collect();
1961				if ident.len() > 1
1962				{	it.nth(ident.chars().count() - 2).unwrap();
1963				}
1964				for (i, rhs) in rule.rhs.iter().enumerate()
1965				{	if rhs.alias == ident
1966					{	used[i] = true;
1967						break;
1968					}
1969				}
1970			}
1971			it_prev = it.clone();
1972		}
1973
1974		// Generate warnings for RHS symbols which aliases are not used in the reduce code
1975		for (i, rhs) in rule.rhs.iter().enumerate()
1976		{	if !rhs.alias.is_empty() && !used[i]
1977			{	return Err
1978				(	LemonMintError::new
1979					(	&rule.rule_filename,
1980						rule.rule_n_line,
1981						format!("Label {} for \"{}({})\" is never used.", rhs.alias, rhs.name, rhs.alias)
1982					)
1983				);
1984			}
1985		}
1986
1987		Ok(())
1988	}
1989
1990	/*
1991	** Print the definition of the union used for the parser's data stack.
1992	** This union contains fields for every possible data type for tokens
1993	** and nonterminals.  In the process of computing and printing this
1994	** union, also set the ".dtnum" field of every terminal and nonterminal
1995	** symbol.
1996	*/
1997	fn get_minor_type(&self, symbols: &mut Symbols) -> Vec<(String, String)>
1998	{	// Allocate and initialize types[] and allocate stddt[]
1999		let arraysize = symbols.n_symbols * 2; // Size of the "types" array
2000		let mut types = Vec::new(); // A hash table of datatypes
2001		types.resize(arraysize, String::new());
2002
2003		// Build a hash table of datatypes. The ".dtnum" field of each symbol is filled in with the hash index plus 1.  A ".dtnum" value of 0 is
2004		// used for terminal symbols.  If there is no %default_type defined then 0 is also used as the .dtnum value for nonterminals which do not specify
2005		// a datatype using the %type directive.
2006'l:		for (i, sp) in symbols.array[0 .. symbols.n_symbols].iter_mut().enumerate()
2007		{	if i == symbols.error_symbol_index
2008			{	sp.dtnum = arraysize+1;
2009				continue;
2010			}
2011			if sp.typ==SymbolType::TERMINAL || (sp.data_type.is_empty() && self.vartype.is_empty())
2012			{	sp.dtnum = 0;
2013				continue;
2014			}
2015			let stddt = if !sp.data_type.is_empty()
2016			{	&sp.data_type
2017			}
2018			else
2019			{	&self.vartype
2020			};
2021			if !self.token_type.is_empty() && &self.token_type == stddt
2022			{	sp.dtnum = 0;
2023				continue;
2024			}
2025			let mut hash = DefaultHasher::new();
2026			stddt.hash(&mut hash);
2027			let mut hash = hash.finish() as usize % arraysize;
2028			while !types[hash].is_empty()
2029			{	if &types[hash] == stddt
2030				{	sp.dtnum = hash + 1;
2031					continue 'l;
2032				}
2033				hash += 1;
2034				if hash >= arraysize
2035				{	hash = 0;
2036				}
2037			}
2038			sp.dtnum = hash + 1;
2039			types[hash] = stddt.to_string(); // TODO: no to_string()
2040		}
2041
2042		// Print out the definition of TokenValue and MinorType
2043		let mut minor_type = Vec::with_capacity(arraysize+3);
2044		minor_type.push(("None".to_string(), "".to_string()));
2045		minor_type.push(("Symbol0".to_string(), "TokenValue".to_string()));
2046		let mut i = 1;
2047		for name in types
2048		{	if !name.is_empty()
2049			{	minor_type.push((format!("Symbol{}", i), name));
2050			}
2051			i += 1;
2052		}
2053		if let Some(symbol) = symbols.get_error_symbol()
2054		{	minor_type.push((format!("Symbol{}", symbol.dtnum), "i32".to_string()));
2055		}
2056
2057		// Done
2058		minor_type
2059	}
2060
2061	fn init_acttab(&mut self, symbols: &Symbols, rules: &mut Vec<Rule>, states: &mut States) -> ActTab
2062	{	let mut acttab = ActTab::new(symbols.n_terminals, symbols.n_symbols);
2063
2064		// Compute the actions on all states and count them up
2065		let mut ax = Vec::with_capacity(states.n_no_tail*2);
2066		for stp in states.array[0 .. states.n_no_tail].iter()
2067		{	ax.push(AxSet::new(stp.n_state, true, stp.n_token_act, ax.len()));
2068			ax.push(AxSet::new(stp.n_state, false, stp.n_nt_act, ax.len()));
2069		}
2070		ax.sort();
2071
2072		let mut min_token_offset = 0;
2073		let mut max_token_offset = 0;
2074		let mut min_nt_offset = 0;
2075		let mut max_nt_offset = 0;
2076
2077		// Compute the action table.  In order to try to keep the size of the action table to a minimum, the heuristic of placing the largest action sets first is used.
2078		for ax_i in ax.iter()
2079		{	if ax_i.n_action == 0
2080			{	break;
2081			}
2082			let stp = &mut states.array[ax_i.n_state];
2083			if ax_i.is_tkn
2084			{	for action in stp.actions.iter()
2085				{	if action.borrow().symbol_index < symbols.n_terminals
2086					{	let n_action = self.compute_action(symbols, action);
2087						if n_action != std::usize::MAX
2088						{	acttab.acttab_action(action.borrow().symbol_index, n_action);
2089						}
2090					}
2091				}
2092				stp.token_offset = acttab.acttab_insert(true);
2093				if stp.token_offset < min_token_offset
2094				{	min_token_offset = stp.token_offset;
2095				}
2096				if stp.token_offset > max_token_offset
2097				{	max_token_offset = stp.token_offset;
2098				}
2099			}
2100			else
2101			{	for action in stp.actions.iter()
2102				{	if action.borrow().symbol_index >= symbols.n_terminals && action.borrow().symbol_index != symbols.n_symbols
2103					{	let n_action = self.compute_action(symbols, action);
2104						if n_action != std::usize::MAX
2105						{	acttab.acttab_action(action.borrow().symbol_index, n_action);
2106						}
2107					}
2108				}
2109				stp.nt_offset = acttab.acttab_insert(false);
2110				if stp.nt_offset < min_nt_offset
2111				{	min_nt_offset = stp.nt_offset;
2112				}
2113				if stp.nt_offset > max_nt_offset
2114				{	max_nt_offset = stp.nt_offset;
2115				}
2116			}
2117		}
2118
2119		// Mark rules that are actually used for reduce actions after all optimizations have been applied
2120		for rule in rules.iter_mut()
2121		{	rule.does_reduce = false;
2122		}
2123		for state in states.array[0 .. states.n_no_tail].iter()
2124		{	for action in state.actions.iter()
2125			{	let action = action.borrow_mut();
2126				if action.typ==ActionType::Reduce || action.typ==ActionType::ShiftReduce
2127				{	if let StateOrRule::Rule(n_rule) = action.x
2128					{	rules[n_rule].does_reduce = true;
2129					}
2130				}
2131			}
2132		}
2133
2134		let mut n_fallbacks = 0;
2135		if self.has_fallback
2136		{	n_fallbacks = symbols.n_terminals - 1;
2137			while n_fallbacks>0 && symbols.array[n_fallbacks].fallback_index==std::usize::MAX
2138			{	n_fallbacks -= 1;
2139			}
2140			n_fallbacks += 1;
2141		}
2142		self.has_fallback = n_fallbacks != 0;
2143
2144		let mut n_shift_offset = states.n_no_tail;
2145		while n_shift_offset >0 && states.array[n_shift_offset -1].token_offset == std::isize::MIN
2146		{	n_shift_offset -= 1;
2147		}
2148
2149		let mut reduce_count = states.n_no_tail;
2150		while reduce_count>0 && states.array[reduce_count-1].nt_offset == std::isize::MIN
2151		{	reduce_count -= 1;
2152		}
2153
2154		acttab.min_token_offset = min_token_offset;
2155		acttab.max_token_offset = max_token_offset;
2156		acttab.min_nt_offset = min_nt_offset;
2157		acttab.max_nt_offset = max_nt_offset;
2158		acttab.n_fallbacks = n_fallbacks;
2159		acttab.n_shift_offset = n_shift_offset;
2160		acttab.reduce_count = reduce_count;
2161
2162		acttab
2163	}
2164
2165	/// Generate source code for the parser
2166	fn get_lemon(mut self, mut symbols: Symbols, mut rules: Vec<Rule>, states: States, acttab: ActTab) -> ParserResult<LemonMint>
2167	{	// Generate types
2168		let sz_code_type = Self::minimum_size_type(0, symbols.n_symbols as isize+1);
2169		let sz_action_type =  Self::minimum_size_type(0, (states.array.len()+rules.len()+5) as isize);
2170		let sz_shift_offset_type =  Self::minimum_size_type(acttab.min_token_offset-1, acttab.max_token_offset);
2171		let sz_reduce_offset_type =  Self::minimum_size_type(acttab.min_nt_offset-1, acttab.max_nt_offset);
2172
2173		// Generate token constants
2174		let mut token = Vec::with_capacity(symbols.n_terminals);
2175		for symbol in symbols.array[1 .. symbols.n_terminals].iter()
2176		{	token.push(Arc::clone(&symbol.name));
2177		}
2178
2179		// Generate the table of rule information
2180		// Note: This code depends on the fact that rules are number sequentually beginning with 0.
2181		self.tables_size += rules.len() * sz_code_type.abs() as usize;
2182
2183		// Generate the action table and its associates:
2184		//
2185		//  yy_action[]        A single table containing all actions.
2186		//  yy_lookahead[]     A table containing the lookahead for each entry in
2187		//                     yy_action.  Used to detect hash collisions.
2188		//  SHIFT_OFFSET[]    For each state, the offset into yy_action for
2189		//                     shifting terminals.
2190		//  REDUCE_OFFSET[]   For each state, the offset into yy_action for
2191		//                     shifting non-terminals after a reduce.
2192		//  DEFAULT[]       Default action for each state.
2193
2194		// Output the LOOKAHEAD_AND_ACTION table
2195		self.n_action_table_entries = acttab.get_n_actions();
2196		let mut n = acttab.get_n_lookahead();
2197		let n_lookahead = std::cmp::max(n, symbols.n_terminals + self.n_action_table_entries);
2198		let mut lookahead_and_action = Vec::with_capacity(n_lookahead);
2199		for (i, LookaheadAction {lookahead, action}) in acttab.iter().enumerate()
2200		{	let lookahead = if *lookahead == std::usize::MAX {symbols.n_symbols} else {*lookahead};
2201			let action = if i >= self.n_action_table_entries {0} else if *action == std::usize::MAX {self.no_action} else {*action};
2202			lookahead_and_action.push((lookahead, action));
2203		}
2204		// Add extra entries to the end of the yy_lookahead[] table so that yy_shift_ofst[]+iToken will always be a valid index into the array,
2205		// even for the largest possible value of yy_shift_ofst[] and iToken.
2206		while n < n_lookahead
2207		{	lookahead_and_action.push((symbols.n_terminals, 0));
2208			n += 1;
2209		}
2210		self.tables_size += lookahead_and_action.len() * (sz_code_type + sz_action_type).abs() as usize;
2211
2212		// Output the SHIFT_OFFSET[] table
2213		let mut shift_offset = Vec::with_capacity(acttab.n_shift_offset);
2214		for stp in states.array.iter().take(acttab.n_shift_offset)
2215		{	shift_offset.push(if stp.token_offset==std::isize::MIN {acttab.min_token_offset - 1} else {stp.token_offset});
2216		}
2217		self.tables_size += shift_offset.len() * sz_shift_offset_type.abs() as usize;
2218
2219		// Output the REDUCE_OFFSET[] table
2220		let mut reduce_offset = Vec::with_capacity(acttab.reduce_count);
2221		for stp in states.array.iter().take(acttab.reduce_count)
2222		{	reduce_offset.push(if stp.nt_offset==std::isize::MIN {acttab.min_nt_offset - 1} else {stp.nt_offset});
2223		}
2224		self.tables_size += reduce_offset.len() * sz_reduce_offset_type.abs() as usize;
2225
2226		// Output the default action table
2227		let mut default = Vec::with_capacity(states.n_no_tail);
2228		for stp in states.array.iter().take(states.n_no_tail)
2229		{	default.push(if stp.default_reduce_action!=std::usize::MAX {stp.default_reduce_action + self.min_reduce} else {self.error_action});
2230		}
2231		self.tables_size += default.len() * sz_action_type.abs() as usize;
2232
2233		// Generate the table of fallback tokens
2234		let mut fallback = Vec::new();
2235		if self.has_fallback
2236		{	fallback.reserve(acttab.n_fallbacks);
2237			for symbol in symbols.array.iter().take(acttab.n_fallbacks)
2238			{	if symbol.fallback_index != std::usize::MAX
2239				{	let fb = &symbols.array[symbol.fallback_index];
2240					fallback.push((fb.index, Arc::clone(&symbol.name), Arc::clone(&fb.name)));
2241				}
2242				else
2243				{	fallback.push((0, Arc::clone(&symbol.name), Arc::new(String::new())));
2244				}
2245			}
2246		}
2247		self.tables_size += fallback.len() * sz_code_type.abs() as usize;
2248
2249		// Generate a table containing the symbolic name of every symbol
2250		let mut token_names = Vec::new();
2251		if self.with_trace && symbols.n_symbols!=0
2252		{	token_names.reserve(symbols.n_symbols);
2253			for symbol in symbols.array.iter().take(symbols.n_symbols)
2254			{	token_names.push(Arc::clone(&symbol.name));
2255			}
2256		}
2257
2258		// Generate code which execution during each REDUCE action
2259		for sym in symbols.array.iter()
2260		{	for n_rule in sym.sym_rules_arr.iter()
2261			{	self.translate_code(&mut rules[*n_rule])?;
2262			}
2263		}
2264
2265		let start_type = symbols.get_start_symbol().data_type.clone();
2266		let minor_type = self.get_minor_type(&mut symbols);
2267		let n_symbols = symbols.n_symbols;
2268		let n_states = states.array.len();
2269		let n_no_tail = states.n_no_tail;
2270		let error_symbol = if let Some(symbol) = symbols.get_error_symbol() {symbol.index} else {0};
2271		let n_terminals = symbols.n_terminals;
2272		let n_nonterminals = symbols.n_symbols - symbols.n_terminals;
2273
2274		Ok
2275		(	LemonMint
2276			{	symbols,
2277				rules,
2278				states,
2279				token_type: self.token_type,
2280				vartype: self.vartype,
2281				start_name: self.start_name,
2282				start_type,
2283				extra_argument_type: self.extra_argument_type,
2284				extracode: self.extracode,
2285				minor_type,
2286				token,
2287
2288				sz_code_type,
2289				sz_action_type,
2290				sz_shift_offset_type,
2291				sz_reduce_offset_type,
2292
2293				n_symbols,
2294				n_states,
2295				n_no_tail,
2296				n_fallbacks: acttab.n_fallbacks,
2297				error_symbol,
2298				with_fallback: self.has_fallback,
2299				shift_count: acttab.n_shift_offset-1,
2300				reduce_count: acttab.reduce_count-1,
2301				with_trace: self.with_trace,
2302				trace_prompt: self.trace_prompt,
2303				shift_min: acttab.min_token_offset,
2304				shift_max: acttab.max_token_offset,
2305				reduce_min: acttab.min_nt_offset,
2306				reduce_max: acttab.max_nt_offset,
2307
2308				n_terminals,
2309				n_nonterminals,
2310				tables_size: self.tables_size,
2311				n_action_table_entries: self.n_action_table_entries,
2312
2313				lookahead_and_action,
2314				shift_offset,
2315				reduce_offset,
2316				default,
2317				fallback,
2318				token_names,
2319			}
2320		)
2321	}
2322
2323	/// Load a Y-grammar file. You can call this function several times to load grammar by parts, and you can call other builder methods to add/override settings.
2324	pub fn load_y_file(self, filename: &Arc<String>) -> ParserResult<Self>
2325	{	self.load_y(filename, File::open(filename.as_ref()).map_err(|e| LemonMintError::new(filename, 1, e.to_string()))?)
2326	}
2327
2328	/// Like load_y_file(), but you give file contents as io::Read object.
2329	///
2330	/// # Example
2331	///
2332	/// ```
2333	/// use lemon_mint::LemonMintBuilder;
2334	/// use std::sync::Arc;
2335	///
2336	/// let fake_filename = Arc::new("source.y".to_string()); // will appear in error messages
2337	/// let builder = LemonMintBuilder::new().load_y(&fake_filename, "%token_type {f64}\nUnit ::= NEW_LINE.".as_bytes()).unwrap();
2338	/// ```
2339	pub fn load_y<R>(mut self, filename: &Arc<String>, input: R) -> ParserResult<Self> where R: io::Read
2340	{	let input = BufReader::new(input);
2341		let mut n_line = 0;
2342		let mut lines = input.lines();
2343		let mut part_till_comment: Option<String> = None; // if a multiline comment opened on a line, this line is not complete, and it will be stored here, and we will wait to closing token
2344'l:		while let Some(line) = lines.next()
2345		{	n_line += 1;
2346			let mut line = line.map_err(|e| LemonMintError::new(filename, n_line, e.to_string()))?;
2347			// comments?
2348			if let Some(part) = part_till_comment.take()
2349			{	if let Some(pos) = line.find("*/")
2350				{	line.replace_range(.. pos+2, &part);
2351				}
2352				else
2353				{	part_till_comment = Some(part);
2354					continue;
2355				}
2356			}
2357			loop
2358			{	if let Some(pos) = line.find('/')
2359				{	match line.bytes().skip(pos+1).next()
2360					{	Some(b'/') => // line comment
2361						{	line.truncate(pos);
2362						}
2363						Some(b'*') => // multiline comment
2364						{	if let Some(len_minus_2) = line[pos+2 ..].find("*/")
2365							{	line.replace_range(pos .. pos+len_minus_2+2, "");
2366								continue;
2367							}
2368							else
2369							{	line.truncate(pos);
2370								part_till_comment = Some(line);
2371								continue 'l;
2372							}
2373						}
2374						_ => {}
2375					}
2376				}
2377				break;
2378			}
2379			// comments cut from line
2380			let mut line = line.trim();
2381			if !line.is_empty()
2382			{	let mut directive = Directive::Rule;
2383				let mut symbol_name: Cow<str> = "".into();
2384				let mut rule_rhs: Cow<str> = "".into();
2385				if line.as_bytes()[0] == b'%'
2386				{	let pos = line.bytes().position(|c| c.is_ascii_whitespace()).unwrap_or(line.len());
2387					let token = &line[1 .. pos];
2388					line = &line[pos ..].trim_start();
2389					directive = match token
2390					{	"token_type" => Directive::TokenType,
2391						"type" => Directive::Type,
2392						"default_type" => Directive::DefaultType,
2393						"start_symbol" => Directive::StartSymbol,
2394						"trace" => Directive::Trace,
2395						"extra_argument" => Directive::ExtraArgument,
2396						"left" => Directive::Left,
2397						"right" => Directive::Right,
2398						"nonassoc" => Directive::Nonassoc,
2399						"fallback" => Directive::Fallback,
2400						"code" | "include" => Directive::Code,
2401						_ =>
2402						{	return Err(LemonMintError::new(filename, n_line, format!("Directive not supported: %{}", token)));
2403						}
2404					};
2405				}
2406				match directive
2407				{	Directive::Type | Directive::Fallback =>
2408					{	// read symbol name
2409						let pos = line.bytes().position(|c| !c.is_ascii_alphanumeric() && c!=b'_').unwrap_or(line.len());
2410						if pos == 0
2411						{	return Err(LemonMintError::new(filename, n_line, "Expected symbol name after %type".to_string()));
2412						}
2413						symbol_name = line[.. pos].to_string().into();
2414						line = &line[pos ..].trim_start();
2415					}
2416					Directive::Rule =>
2417					{	let pos = line.find("::=").ok_or_else(|| LemonMintError::new(filename, n_line, "Couldn't interpret this line".to_string()))?;
2418						symbol_name = line[.. pos].trim_end().to_string().into();
2419						line = &line[pos+3 ..].trim_start();
2420						let pos = line.find('.').ok_or_else(|| LemonMintError::new(filename, n_line, "Rules must be terminated with a dot".to_string()))?;
2421						rule_rhs = line[.. pos].trim_end().to_string().into();
2422						line = &line[pos+1 ..].trim_start();
2423					}
2424					_ => {}
2425				}
2426				let mut value: Cow<str> = line.into();
2427				if line.bytes().next() == Some(b'{')
2428				{	line = &line[1 ..].trim_start(); // skip '{' at the beginning
2429					let (mut balance, mut last_close) = (1, usize::MAX);
2430					Self::balanced_braces(filename, n_line, line, &mut balance, &mut last_close)?;
2431					if balance == 0
2432					{	value = line[.. last_close].into(); // cut '}' at the end
2433					}
2434					else
2435					{	// read lines untill all braces closed
2436						let mut buffer = String::with_capacity(128);
2437						buffer.push_str(line);
2438						buffer.push('\n');
2439						let from_n_line = n_line;
2440						while let Some(line) = lines.next()
2441						{	n_line += 1;
2442							let line = line.map_err(|e| LemonMintError::new(filename, n_line, e.to_string()))?;
2443							Self::balanced_braces(filename, n_line, &line, &mut balance, &mut last_close)?;
2444							if balance == 0
2445							{	buffer.push_str(&line[.. last_close]); // cut '}' at the end
2446								break;
2447							}
2448							buffer.push_str(&line);
2449							buffer.push('\n');
2450						}
2451						if balance > 0
2452						{	return Err(LemonMintError::new(filename, n_line, format!("Braces not closed at the end of file since line {}", from_n_line)));
2453						}
2454						value = buffer.into();
2455					}
2456				}
2457				else if !line.is_empty() && line.as_bytes()[line.len()-1]==b'.'
2458				{	value = line[.. line.len()-1].trim_end().into(); // cut '.' at end
2459				}
2460				self = match directive
2461				{	Directive::Rule => self.add_rule(filename, n_line, symbol_name.into(), rule_rhs.as_ref(), value.into()),
2462					Directive::TokenType => self.set_token_type(value.into()),
2463					Directive::Type => self.add_type(filename, n_line, symbol_name.into(), value.into()),
2464					Directive::DefaultType => self.set_default_type(value.into()),
2465					Directive::StartSymbol => self.set_start_symbol(filename, n_line, value.into()),
2466					Directive::Trace => self.set_trace_prompt(value.into()),
2467					Directive::ExtraArgument => self.set_extra_argument_type(value.into()),
2468					Directive::Left => self.set_left(filename, n_line, value.as_ref()),
2469					Directive::Right => self.set_right(filename, n_line, value.as_ref()),
2470					Directive::Nonassoc => self.set_nonassoc(filename, n_line, value.as_ref()),
2471					Directive::Fallback => self.add_fallback(filename, n_line, symbol_name.into(), value.as_ref()),
2472					Directive::Code => self.add_code(value.into()),
2473				}?;
2474			}
2475		}
2476		Ok(self)
2477	}
2478
2479	fn balanced_braces(filename: &Arc<String>, n_line: usize, line: &str, balance: &mut i32, last_close: &mut usize) -> ParserResult<()>
2480	{	for (i, c) in line.bytes().enumerate()
2481		{	match c
2482			{	b'{' => *balance += 1,
2483				b'}' => {*balance -= 1; *last_close = i}
2484				_ => {}
2485			}
2486		}
2487		if *balance < 0
2488		{	return Err(LemonMintError::new(filename, n_line, "Braces on line not balanced".to_string()));
2489		}
2490		if *balance == 0
2491		{	if !line[*last_close+1 ..].trim_end().is_empty()
2492			{	return Err(LemonMintError::new(filename, n_line, "Junk after closing brace".to_string()));
2493			}
2494		}
2495		Ok(())
2496	}
2497
2498	///	Set the parser "%start_symbol".
2499	pub fn set_start_symbol(mut self, filename: &Arc<String>, n_line: usize, mut value: String) -> ParserResult<Self>
2500	{	let trimmed = value.trim();
2501		if trimmed.len() != value.len()
2502		{	value = trimmed.to_string();
2503		}
2504		if value.find(|c: char| !c.is_ascii_alphanumeric() && c!='_').is_some()
2505		{	return Err(LemonMintError::new(filename, n_line, format!("Invalid start symbol name: {}", value)));
2506		}
2507		if is_terminal_name(&value)
2508		{	return Err(LemonMintError::new(filename, n_line, "Start symbol must be nonterminal".to_string()));
2509		}
2510		self.start_name = value;
2511		Ok(self)
2512	}
2513
2514	///	Set the parser "%token_type".
2515	pub fn set_token_type(mut self, value: String) -> ParserResult<Self>
2516	{	self.token_type = typename_to_string(value);
2517		Ok(self)
2518	}
2519
2520	///	Set the parser "%default_type".
2521	pub fn set_default_type(mut self, value: String) -> ParserResult<Self>
2522	{	self.vartype = typename_to_string(value);
2523		Ok(self)
2524	}
2525
2526	///	Enable trace, and set prompt that will be printed before each message.
2527	/// The prompt can be empty string.
2528	pub fn set_trace_prompt(mut self, value: String) -> ParserResult<Self>
2529	{	self.with_trace = true;
2530		self.trace_prompt = value;
2531		Ok(self)
2532	}
2533
2534	/// Set the parser %extra_argument.
2535	/// Only it's type, like:
2536	///
2537	/// ```
2538	/// # use lemon_mint::LemonMintBuilder;
2539	///
2540	/// let builder = LemonMintBuilder::new().set_extra_argument_type("String".to_string()).unwrap();
2541	/// ```
2542	///
2543	/// In your rust code that uses the generated parser, you initialize the extra argument when you create a Parser object:
2544	///
2545	/// ```ignore
2546	/// %code {
2547	/// 	fn main()
2548	/// 	{	let mut parser = Parser::new("Initial value".to_string()); // Initial value of the extra argument
2549	/// 		assert_eq!(parser.extra, "Initial value".to_string());
2550	/// 	}
2551	/// }
2552	/// ```
2553	///
2554	/// In actions code, the extra argument is available as variable `&mut extra`:
2555	///
2556	/// ```ignore
2557	/// %token_type {String}
2558	/// Unit ::= NEW_LINE(tok). extra.push_str(&tok);
2559	/// ```
2560	pub fn set_extra_argument_type(mut self, value: String) -> ParserResult<Self>
2561	{	self.extra_argument_type = typename_to_string(value);
2562		Ok(self)
2563	}
2564
2565	///	Add the parser "%left A B C".
2566	///
2567	/// # Example
2568	///
2569	/// ```
2570	/// # use lemon_mint::LemonMintBuilder;
2571	/// # use std::sync::Arc;
2572	///
2573	/// let fake_filename = Arc::new("source.y".to_string()); // will appear in error messages
2574	/// let builder = LemonMintBuilder::new().set_left(&fake_filename, 1, "PLUS MINUS").unwrap().set_left(&fake_filename, 2, "TIMES DIVIDE").unwrap();
2575	/// ```
2576	///
2577	/// * symbol_names - Terminal symbol names, separated by whitespace characters. All the symbols will have the same precedence.
2578	/// Further calls to `set_left()`, `set_right()` or `set_nonassoc()` will set higher precedence.
2579	pub fn set_left(self, filename: &Arc<String>, n_line: usize, symbol_names: &str) -> ParserResult<Self>
2580	{	self.add_associativity(filename, n_line, symbol_names, Associativity::LEFT)
2581	}
2582
2583	///	Add the parser "%right A B C".
2584	pub fn set_right(self, filename: &Arc<String>, n_line: usize, symbol_names: &str) -> ParserResult<Self>
2585	{	self.add_associativity(filename, n_line, symbol_names, Associativity::RIGHT)
2586	}
2587
2588	///	Add the parser "%nonassoc A B C".
2589	pub fn set_nonassoc(self, filename: &Arc<String>, n_line: usize, symbol_names: &str) -> ParserResult<Self>
2590	{	self.add_associativity(filename, n_line, symbol_names, Associativity::NONASSOC)
2591	}
2592
2593	fn add_associativity(mut self, filename: &Arc<String>, n_line: usize, symbol_names: &str, assoc: Associativity) -> ParserResult<Self>
2594	{	for symbol_name in symbol_names.trim().split(|c: char| c.is_ascii_whitespace())
2595		{	if !symbol_name.is_empty()
2596			{	if symbol_name.find(|c: char| !c.is_ascii_alphanumeric() && c!='_').is_some()
2597				{	return Err(LemonMintError::new(filename, n_line, format!("Invalid token name: {}", symbol_name)));
2598				}
2599				if !is_terminal_name(symbol_name)
2600				{	return Err(LemonMintError::new(filename, n_line, format!("Can only set precedence for terminal symbols, not \"{}\"", symbol_name)));
2601				}
2602				if let Some(prev) = self.precedence.get(symbol_name)
2603				{	return Err(LemonMintError::new(filename, n_line, format!("Symbol \"{}\" has already be given a precedence at {}:{}", symbol_name, prev.filename, prev.n_line)));
2604				}
2605				self.precedence.insert
2606				(	symbol_name.to_string(),
2607					PrecedenceInFile
2608					{	filename: Arc::clone(filename),
2609						n_line,
2610						assoc,
2611						precedence: self.prec_counter,
2612					}
2613				);
2614			}
2615		}
2616		self.prec_counter += 1;
2617		Ok(self)
2618	}
2619
2620	///	Add the parser "%type symbol_name {Type}".
2621	pub fn add_type(mut self, filename: &Arc<String>, n_line: usize, mut symbol_name: String, type_name: String) -> ParserResult<Self>
2622	{	let trimmed = symbol_name.trim();
2623		if trimmed.len() != symbol_name.len()
2624		{	symbol_name = trimmed.to_string();
2625		}
2626		if symbol_name.find(|c: char| !c.is_ascii_alphanumeric() && c!='_').is_some()
2627		{	return Err(LemonMintError::new(filename, n_line, format!("Invalid symbol name: {}", symbol_name)));
2628		}
2629		if is_terminal_name(&symbol_name)
2630		{	return Err(LemonMintError::new(filename, n_line, format!("Can only set type for nonterminal symbols, not \"{}\"", symbol_name)));
2631		}
2632		if let Some(prev) = self.nonterminal_types.get(&symbol_name)
2633		{	return Err(LemonMintError::new(filename, n_line, format!("Type for symbol \"{}\" already defined at {}:{}", symbol_name, prev.filename, prev.n_line)));
2634		}
2635		self.nonterminal_types.insert
2636		(	symbol_name,
2637			StringInFile
2638			{	filename: Arc::clone(filename),
2639				n_line,
2640				string: typename_to_string(type_name),
2641			}
2642		);
2643		Ok(self)
2644	}
2645
2646	/// Return `Some((filename, n_line))` if given symbol was added through `add_type()`.
2647	pub fn get_type(&self, mut symbol_name: &str) -> Option<(Arc<String>, usize)>
2648	{	symbol_name = symbol_name.trim();
2649		self.nonterminal_types.get(symbol_name).map(|v| (Arc::clone(&v.filename), v.n_line))
2650	}
2651
2652	///	Add the parser "%fallback FB A B C".
2653	pub fn add_fallback(mut self, filename: &Arc<String>, n_line: usize, mut fallback_to_symbol_name: String, symbol_names: &str) -> ParserResult<Self>
2654	{	let trimmed = fallback_to_symbol_name.trim();
2655		if trimmed.len() != fallback_to_symbol_name.len()
2656		{	fallback_to_symbol_name = trimmed.to_string();
2657		}
2658		if fallback_to_symbol_name.find(|c: char| !c.is_ascii_alphanumeric() && c!='_').is_some()
2659		{	return Err(LemonMintError::new(filename, n_line, format!("Invalid token name: {}", fallback_to_symbol_name)));
2660		}
2661		let fallback_to_symbol_name = Arc::new(fallback_to_symbol_name);
2662		for symbol_name in symbol_names.trim().split(|c: char| c.is_ascii_whitespace())
2663		{	if !symbol_name.is_empty()
2664			{	if symbol_name.find(|c: char| !c.is_ascii_alphanumeric() && c!='_').is_some()
2665				{	return Err(LemonMintError::new(filename, n_line, format!("Invalid token name: {}", symbol_name)));
2666				}
2667				if !is_terminal_name(symbol_name)
2668				{	return Err(LemonMintError::new(filename, n_line, format!("Can only set fallback to terminal symbols, not \"{}\"", symbol_name)));
2669				}
2670				let symbol_name = Arc::new(symbol_name.to_string());
2671				self.symbols_builder.add(&symbol_name);
2672				self.symbols_builder.add(&fallback_to_symbol_name);
2673				let sp = self.symbols_builder.get(&symbol_name);
2674				if sp.fallback_index != std::usize::MAX
2675				{	return Err(LemonMintError::new(filename, n_line, format!("More than one fallback assigned to token \"{}\"", symbol_name)));
2676				}
2677				let fsp = self.symbols_builder.get(&fallback_to_symbol_name);
2678				if *fsp == *sp
2679				{	return Err(LemonMintError::new(filename, n_line, format!("Symbol \"{}\" is asked fallback to self // {}, {}", symbol_name, fallback_to_symbol_name, symbol_name)));
2680				}
2681				self.symbols_builder.get_mut(&symbol_name).fallback_index = fsp.index;
2682				self.has_fallback = true;
2683			}
2684		}
2685		Ok(self)
2686	}
2687
2688	///	Add one grammar rule, equivalent to a `Lhs ::= Rhs. action` line in a Y-grammar.
2689	///
2690	/// * `lhs_name` - left-hand side nonterminal, e.g. `"Exprs"`.
2691	/// * `rhs_names_aliases` - the right-hand side: whitespace-separated symbol names, each optionally
2692	///   followed by an alias in parentheses to bind its semantic value, e.g. `"Exprs(items) COMMA Expr(item)"`.
2693	///   An empty string is an empty production.
2694	/// * `code` - the action: Rust code producing the left-hand side's value (it may use the aliases
2695	///   and `&mut extra`). An empty string produces `()`.
2696	///
2697	/// # Example
2698	///
2699	/// ```
2700	/// # use lemon_mint::LemonMintBuilder;
2701	/// # use std::sync::Arc;
2702	/// let fake_filename = Arc::new("source.y".to_string());
2703	/// let builder = LemonMintBuilder::new()
2704	/// 	.set_default_type("Vec<f64>".to_string()).unwrap()
2705	/// 	.add_rule(&fake_filename, 1, "List".to_string(), "List(items) NUM(n)", "let mut items = items; items.push(n); items".to_string()).unwrap()
2706	/// 	.add_rule(&fake_filename, 2, "List".to_string(), "", "Vec::new()".to_string()).unwrap();
2707	/// ```
2708	pub fn add_rule(mut self, filename: &Arc<String>, n_line: usize, mut lhs_name: String, rhs_names_aliases: &str, code: String) -> ParserResult<Self>
2709	{	let trimmed = lhs_name.trim();
2710		if trimmed.len() != lhs_name.len()
2711		{	lhs_name = trimmed.to_string();
2712		}
2713		if is_terminal_name(&lhs_name)
2714		{	return Err(LemonMintError::new(filename, n_line, format!("Invalid LHS symbol: \"{}\"", lhs_name)));
2715		}
2716		let mut code = code;
2717		if code.trim().is_empty()
2718		{	code = String::new();
2719		}
2720		if self.start_name.is_empty()
2721		{	self.start_name = lhs_name.clone();
2722		}
2723		let lhs_name = Arc::new(lhs_name);
2724		let lhs_index = self.symbols_builder.add(&lhs_name);
2725		let mut rule = Rule::new(filename, n_line, &lhs_name, lhs_index, self.rules.len(), code);
2726		// parse rhs_names_aliases
2727		let mut s = rhs_names_aliases.trim_start();
2728		while s.len() != 0
2729		{	let name_len = s.chars().position(|c| !c.is_ascii_alphanumeric() && c!='_').unwrap_or(s.len());
2730			if name_len == 0
2731			{	return Err(LemonMintError::new(filename, n_line, format!("Invalid RHS expression: \"{}\"", rhs_names_aliases)));
2732			}
2733			let rhs_name = Arc::new(s[.. name_len].to_string());
2734			let rhs_index = self.symbols_builder.add(&rhs_name);
2735			s = s[name_len ..].trim_start();
2736			let mut alias = String::new();
2737			if s.bytes().next() == Some(b'(')
2738			{	s = s[1 ..].trim_start();
2739				let alias_len = s.chars().position(|c| !c.is_ascii_alphanumeric() && c!='_').unwrap_or(s.len());
2740				alias = s[.. alias_len].to_string();
2741				s = s[alias_len ..].trim_start();
2742				if alias_len==0 || s.bytes().next() != Some(b')')
2743				{	return Err(LemonMintError::new(filename, n_line, format!("Invalid alias in RHS expression: \"{}\"", rhs_names_aliases)));
2744				}
2745				s = s[1 ..].trim_start();
2746			}
2747			rule.rhs.push(Rhs{name: rhs_name, index: rhs_index, alias});
2748		}
2749		self.symbols_builder.get_mut(&lhs_name).sym_rules_arr.insert(0, self.rules.len()); // TODO: maybe push(), not insert()
2750		self.rules.push(rule);
2751		Ok(self)
2752	}
2753
2754	///	Add the parser %code or %include
2755	pub fn add_code(mut self, code: String) -> ParserResult<Self>
2756	{	if self.extracode.is_empty()
2757		{	self.extracode = code;
2758		}
2759		else
2760		{	self.extracode.push_str("\n\n");
2761			self.extracode.push_str(&code);
2762		}
2763		Ok(self)
2764	}
2765
2766	/// Allows to disable finite-state machine tables compression. Don't do this.
2767	pub fn set_no_compress(mut self, new_no_compress: bool) -> ParserResult<Self>
2768	{	self.no_compress = new_no_compress;
2769		Ok(self)
2770	}
2771
2772	/// Disable resorting states. You don't need this functionality.
2773	pub fn set_no_resort(mut self, new_no_resort: bool) -> ParserResult<Self>
2774	{	self.no_resort = new_no_resort;
2775		Ok(self)
2776	}
2777
2778	/// When you feed all the parser rules and options, call this method to finally build the parser finite-state machine transition tables.
2779	/// If there are problems with your grammar or if there are parser conflicts, this will return Err.
2780	/// If parser build succeeds this returns the parser representation as `LemonMint` object.
2781	pub fn try_into_lemon(mut self) -> ParserResult<LemonMint>
2782	{	// rules
2783		let mut rules = mem::replace(&mut self.rules, Vec::new());
2784		if rules.len() == 0
2785		{	return Err(LemonMintError::new(&Arc::new(String::new()), 1, "Empty grammar".to_string()));
2786		}
2787
2788		// Count and index the symbols of the grammar
2789		let mut symbols =
2790		{	let symbols_builder = mem::replace(&mut self.symbols_builder, SymbolsBuilder::new(true));
2791			let nonterminal_types = mem::replace(&mut self.nonterminal_types, HashMap::new());
2792			let precedence = mem::replace(&mut self.precedence, HashMap::new());
2793
2794			symbols_builder.into_symbols(&self.start_name, nonterminal_types, precedence, &mut rules)? // symbols - Sorted array of all symbols
2795		};
2796
2797		// Put rules that have no reduce action C-code associated with them last, so that the switch() statement that selects reduction actions will have a smaller jump table.
2798		rules.sort_by
2799		(	|a, b|
2800			{	if a.code.is_empty() == b.code.is_empty()
2801				{	a.index.cmp(&b.index)
2802				}
2803				else if a.code.is_empty()
2804				{	Ordering::Greater
2805				}
2806				else
2807				{	Ordering::Less
2808				}
2809			}
2810		);
2811		for (i, rule) in rules.iter_mut().enumerate()
2812		{	rule.index = i;
2813		}
2814
2815		// Find the precedence for every production rule (that has one)
2816		Self::find_rule_precedences(&mut symbols, &mut rules);
2817
2818		// Compute the lambda-nonterminals and the first-sets for every nonterminal
2819		self.find_first_sets(&mut symbols, &mut rules);
2820
2821		// Find the start symbol
2822		if !self.start_name.is_empty()
2823		{	if symbols.start_symbol_index == std::usize::MAX
2824			{	return Err(LemonMintError::new(&Self::get_filename_of_first_rule(&rules), 1, format!("The specified start symbol \"{}\" is not in a nonterminal of the grammar", self.start_name)));
2825			}
2826		}
2827		else
2828		{	return Err(LemonMintError::new(&Self::get_filename_of_first_rule(&rules), 1, "Please, specify a start symbol".to_string()));
2829		}
2830
2831		// Make sure the start symbol doesn't occur on the right-hand side of any rule.  Report an error if it does.
2832		// (YACC would generate a new start symbol in this case.)
2833		for rule in rules.iter()
2834		{	for rhs in &rule.rhs
2835			{	if rhs.index == symbols.start_symbol_index
2836				{	return Err(LemonMintError::new(&Self::get_filename_of_first_rule(&rules), 1, format!("The start symbol \"{}\" occurs on the right-hand side of a rule", rhs.name)));
2837				}
2838			}
2839		}
2840
2841		dump_symbols(&symbols, &rules);
2842
2843		// Compute all LR(0) states.  Also record follow-set propagation links so that the follow-set can be computed later
2844		let mut states = StatesBuilder::build(&symbols, &mut rules, symbols.get_start_symbol(), symbols.n_terminals, &mut self.actions_enum)?;
2845
2846		dump_states(&states, &rules, &symbols, 1);
2847
2848		// Tie up loose ends on the propagation links
2849		Self::find_links(&states);
2850
2851		dump_states(&states, &rules, &symbols, 2);
2852
2853		// Compute the follow set of every reducible configuration
2854		Self::find_follow_sets(&states);
2855
2856		dump_states(&states, &rules, &symbols, 3);
2857
2858		// Compute the action tables
2859		self.find_actions(&symbols, &mut rules, &mut states)?;
2860
2861		dump_states(&states, &rules, &symbols, 4);
2862
2863		// Compress the action tables
2864		if !self.no_compress
2865		{	self.compress_tables(&symbols, &rules, &mut states, symbols.default_symbol_index);
2866		}
2867
2868		dump_states(&states, &rules, &symbols, 5);
2869
2870		// Reorder and renumber the states so that states with fewer choices occur at the end.  This is an optimization that helps make the
2871		// generated parser tables smaller.
2872		if !self.no_resort
2873		{	self.resort_states(&symbols, &mut states);
2874		}
2875
2876		dump_states(&states, &rules, &symbols, 6);
2877
2878		// Compute the action table
2879		self.min_shift_reduce = states.array.len();
2880		self.error_action = self.min_shift_reduce + rules.len();
2881		self.accept_action = self.error_action + 1;
2882		self.no_action = self.accept_action + 1;
2883		self.min_reduce = self.no_action + 1;
2884		self.max_action = self.min_reduce + rules.len();
2885		let acttab = self.init_acttab(&symbols, &mut rules, &mut states);
2886
2887		dump_states(&states, &rules, &symbols, 7);
2888
2889		// Generate the source code for the parser
2890		if self.n_conflicts > 0
2891		{	Err(LemonMintError::new(&Self::get_filename_of_first_rule(&rules), 1, format!("{} parsing conflicts", self.n_conflicts)))
2892		}
2893		else
2894		{	self.get_lemon(symbols, rules, states, acttab)
2895		}
2896	}
2897}
2898
2899#[derive(Debug, Copy, Clone, PartialEq)]
2900enum Lang
2901{	Rust
2902}
2903
2904fn size_type_to_str(lang: Lang, n_bytes: isize) -> &'static str
2905{	match (lang, n_bytes)
2906	{	(Lang::Rust, -1) => "i8",
2907		(Lang::Rust, -2) => "i16",
2908		(Lang::Rust, -4) => "i32",
2909		(Lang::Rust,  1) => "u8",
2910		(Lang::Rust,  2) => "u16",
2911		(Lang::Rust,  4) => "u32",
2912		(Lang::Rust,  _) => "isize",
2913	}
2914}
2915
2916/// The compiled parser that can be saved to a rust file. Use `LemonMintBuilder` to build it.
2917#[derive(Debug)]
2918pub struct LemonMint
2919{	symbols: Symbols,
2920	rules: Vec<Rule>,                  // All rules
2921	states: States,
2922	token_type: String,                // Type of terminal symbols in the parser stack
2923	vartype: String,                   // The default type of non-terminal symbols
2924	start_name: String,                // Name of the start symbol for the grammar
2925	start_type: String,
2926	extra_argument_type: String,
2927	extracode: String,
2928	minor_type: Vec<(String, String)>,
2929	token: Vec<Arc<String>>,
2930
2931	sz_code_type: isize,
2932	sz_action_type: isize,
2933	sz_shift_offset_type: isize,
2934	sz_reduce_offset_type: isize,
2935
2936	n_symbols: usize,
2937	n_states: usize,
2938	n_no_tail: usize,
2939	n_fallbacks: usize,
2940	error_symbol: usize,
2941	#[allow(dead_code)] with_fallback: bool,
2942	shift_count: usize,
2943	reduce_count: usize,
2944	with_trace: bool,
2945	trace_prompt: String,              // Prompt to preface each trace message, if with_trace is true
2946	shift_min: isize,
2947	shift_max: isize,
2948	reduce_min: isize,
2949	reduce_max: isize,
2950
2951	n_terminals: usize,
2952	#[allow(dead_code)] n_nonterminals: usize,
2953	#[allow(dead_code)] tables_size: usize,                // Total table size of all tables in bytes
2954	n_action_table_entries: usize,     // Number of entries in the yy_action[] table
2955
2956	lookahead_and_action: Vec<(usize, usize)>,
2957	shift_offset: Vec<isize>,
2958	reduce_offset: Vec<isize>,
2959	default: Vec<usize>,
2960	fallback: Vec<(usize, Arc<String>, Arc<String>)>,
2961	token_names: Vec<Arc<String>>,
2962}
2963impl LemonMint
2964{	/// Generate the Rust source code of the parser, writing it to `out`.
2965	///
2966	/// The output is self-contained (no dependency on this crate) and exposes a `code` module
2967	/// containing the `Parser` struct and the `Token` enum. Typically you write it to a file under
2968	/// `OUT_DIR` from a build script and `include!` it, or generate it once and commit it.
2969	pub fn gen_rust<W>(&self, out: &mut W) -> io::Result<()> where W: io::Write
2970	{	writeln!(out, "pub mod code {{")?;
2971
2972		let mut lempar_reader = LemparReader::new();
2973		lempar_reader.copy_part(out)?; // to %% no. 1
2974
2975		// Generate types
2976		writeln!(out, "pub type TokenValue = {};", if !self.token_type.is_empty() {&self.token_type} else {"String"})?;
2977		writeln!(out, "pub type ExtraArgumentType = {};", if !self.extra_argument_type.is_empty() {&self.extra_argument_type} else {"()"})?;
2978		writeln!(out, "pub type StartType = {};", if !self.start_type.is_empty() {&self.start_type} else {"()"})?;
2979		writeln!(out, "type CodeType = {};", size_type_to_str(Lang::Rust, self.sz_code_type))?;
2980		writeln!(out, "type ActionType = {};", size_type_to_str(Lang::Rust, self.sz_action_type))?;
2981		writeln!(out, "type ShiftOffsetType = {};", size_type_to_str(Lang::Rust, self.sz_shift_offset_type))?;
2982		writeln!(out, "type ReduceOffsetType = {};", size_type_to_str(Lang::Rust, self.sz_reduce_offset_type))?;
2983
2984		write!(out, "enum MinorType\n{{")?;
2985		for (variant, typ) in self.minor_type.iter()
2986		{	if typ.is_empty()
2987			{	writeln!(out, "\t{},", variant)?;
2988			}
2989			else
2990			{	writeln!(out, "\t{}({}),", variant, typ)?;
2991			}
2992		}
2993		writeln!(out, "}}")?;
2994
2995		// Generate token constants
2996		writeln!(out, "#[repr(u32)]\n#[derive(Copy, Clone, PartialEq)]\n#[allow(non_camel_case_types)]")?;
2997		write!(out, "pub enum Token\n{{")?;
2998		for (i, name) in self.token.iter().enumerate()
2999		{	if self.token_type.is_empty()
3000			{	writeln!(out, "\t{:<30} = {:2},", name, i+1)?;
3001			}
3002			else
3003			{	writeln!(out, "\t{:<30} = {:2},", name, i+1)?;
3004			}
3005		}
3006		writeln!(out, "}}\n")?;
3007
3008		// Generate constants
3009		writeln!(out, "const NO_CODE: CodeType = {}; // YYNOCODE", self.n_symbols)?;
3010		writeln!(out, "const N_STATES: usize = {}; // YYNSTATE", self.n_no_tail)?;
3011		writeln!(out, "const N_RULES: usize = {}; // YYNRULE", self.rules.len())?;
3012		writeln!(out, "const N_TERMINALS: usize = {}; // YYNTOKEN", self.n_terminals)?;
3013		writeln!(out, "const MAX_SHIFT: usize = N_STATES-1; // YY_MAX_SHIFT")?;
3014		writeln!(out, "const MIN_SHIFTREDUCE: usize = {}; // YY_MIN_SHIFTREDUCE", self.n_states)?;
3015		writeln!(out, "const MAX_SHIFTREDUCE: usize = MIN_SHIFTREDUCE + N_RULES - 1; // YY_MAX_SHIFTREDUCE")?;
3016		writeln!(out, "const ERROR_ACTION: usize = MAX_SHIFTREDUCE + 1; // YY_ERROR_ACTION")?;
3017		writeln!(out, "const ACCEPT_ACTION: usize = ERROR_ACTION + 1; // YY_ACCEPT_ACTION")?;
3018		writeln!(out, "const NO_ACTION: usize = ACCEPT_ACTION + 1; // YY_NO_ACTION")?;
3019		writeln!(out, "const MIN_REDUCE: usize = NO_ACTION + 1; // YY_MIN_REDUCE")?;
3020		writeln!(out, "//const MAX_REDUCE: usize = MIN_REDUCE + N_RULES - 1; // YY_MAX_REDUCE")?;
3021		writeln!(out, "const ERROR_SYMBOL: CodeType = {}; // YYERRORSYMBOL", self.error_symbol)?;
3022		writeln!(out, "const WITH_FALLBACK: bool = {}; // YYFALLBACK", if self.n_fallbacks>0 {"true"} else {"false"})?;
3023		writeln!(out, "const SHIFT_COUNT: usize = {}; // YY_SHIFT_COUNT", self.shift_count)?;
3024		writeln!(out, "const REDUCE_COUNT: usize = {}; // YY_REDUCE_COUNT", self.reduce_count)?;
3025		writeln!(out, "//const SHIFT_MIN: i32 = {}; // YY_SHIFT_MIN", self.shift_min)?;
3026		writeln!(out, "//const SHIFT_MAX: i32 = {}; // YY_SHIFT_MAX", self.shift_max)?;
3027		writeln!(out, "//const REDUCE_MIN: i32 = {}; // YY_REDUCE_MIN", self.reduce_min)?;
3028		writeln!(out, "//const REDUCE_MAX: i32 = {}; // YY_REDUCE_MAX", self.reduce_max)?;
3029		writeln!(out, "const ACTTAB_COUNT: usize = {}; // YY_ACTTAB_COUNT", self.n_action_table_entries)?;
3030		writeln!(out, "const TRACE: bool = {};", if self.with_trace {"true"} else {"false"})?;
3031
3032		// trace
3033		if self.trace_prompt.chars().position(|c| c=='\\' || c=='"').is_none()
3034		{	writeln!(out, "const TRACE_PROMPT: &str = \"{}\";", self.trace_prompt)?;
3035		}
3036		else
3037		{	let mut tag = String::with_capacity(self.trace_prompt.len()+1);
3038			for _i in 0 .. self.trace_prompt.len()+1
3039			{	tag.push('#');
3040				if !self.trace_prompt.contains(&tag)
3041				{	break;
3042				}
3043			}
3044			writeln!(out, "const TRACE_PROMPT: &str = r{tag}\"{}\"{tag};", self.trace_prompt, tag=tag)?;
3045		}
3046
3047		// Generate the action table and its associates:
3048		//
3049		//  yy_action[]        A single table containing all actions.
3050		//  yy_lookahead[]     A table containing the lookahead for each entry in
3051		//                     yy_action.  Used to detect hash collisions.
3052		//  SHIFT_OFFSET[]    For each state, the offset into yy_action for
3053		//                     shifting terminals.
3054		//  REDUCE_OFFSET[]   For each state, the offset into yy_action for
3055		//                     shifting non-terminals after a reduce.
3056		//  DEFAULT[]       Default action for each state.
3057
3058		// Output the LOOKAHEAD_AND_ACTION table
3059		write!(out, "const LOOKAHEAD_AND_ACTION: [LookaheadAndAction; {}] =", self.lookahead_and_action.len())?;
3060		let mut formatter = ArrayFormatter::new(2);
3061		for (lookahead, action) in self.lookahead_and_action.iter()
3062		{	formatter.separ(out)?;
3063			write!(out, "LookaheadAndAction {{lookahead: {:4}, action: {:4}}}", lookahead, action)?;
3064		}
3065		formatter.end(out)?;
3066
3067		// Output the SHIFT_OFFSET[] table
3068		write!(out, "const SHIFT_OFFSET: [ShiftOffsetType; {}] =", self.shift_offset.len())?;
3069		let mut formatter = ArrayFormatter::new(16);
3070		for offset in self.shift_offset.iter()
3071		{	formatter.separ(out)?;
3072			write!(out, "{:4}", offset)?;
3073		}
3074		formatter.end(out)?;
3075
3076		// Output the REDUCE_OFFSET[] table
3077		write!(out, "const REDUCE_OFFSET: [ReduceOffsetType; {}] =", self.reduce_offset.len())?;
3078		let mut formatter = ArrayFormatter::new(16);
3079		for offset in self.reduce_offset.iter()
3080		{	formatter.separ(out)?;
3081			write!(out, "{:4}", offset)?;
3082		}
3083		formatter.end(out)?;
3084
3085		// Output the default action table
3086		write!(out, "const DEFAULT: [ActionType; {}] =", self.default.len())?;
3087		let mut formatter = ArrayFormatter::new(16);
3088		for action in self.default.iter()
3089		{	formatter.separ(out)?;
3090			write!(out, "{:4}", action)?;
3091		}
3092		formatter.end(out)?;
3093
3094		// Next
3095		lempar_reader.copy_part(out)?; // to %% no. 2
3096
3097		// Generate the table of fallback tokens
3098		write!(out, "const FALLBACK: [CodeType; {}] =", self.fallback.len())?;
3099		let mut formatter = ArrayFormatter::new(1);
3100		for (index, name, to_name) in self.fallback.iter()
3101		{	formatter.separ(out)?;
3102			write!(out, "{:3} /* {:10} => {} */", index, name, to_name)?;
3103		}
3104		formatter.end(out)?;
3105
3106		// Next
3107		lempar_reader.copy_part(out)?; // to %% no. 3
3108
3109		// Generate a table containing the symbolic name of every symbol
3110		write!(out, "const TOKEN_NAMES: [&str; {}] =", self.token_names.len())?;
3111		let mut formatter = ArrayFormatter::new(1);
3112		for name in self.token_names.iter()
3113		{	formatter.separ(out)?;
3114			write!(out, "{:<15}", format!("\"{}\"", name))?;
3115		}
3116		formatter.end(out)?;
3117
3118		// Next
3119		lempar_reader.copy_part(out)?; // to %% no. 4
3120
3121		// Generate a table containing a text string that describes every rule in the rule set of the grammar.
3122		// This information is used when tracing REDUCE actions.
3123		write!(out, "const RULE_NAMES: [&str; {}] =", self.rules.len())?;
3124		let mut formatter = ArrayFormatter::new(1);
3125		for rule in self.rules.iter()
3126		{	formatter.separ(out)?;
3127			write!(out, "\"{}\"", rule)?;
3128		}
3129		formatter.end(out)?;
3130
3131		// Next
3132		lempar_reader.copy_part(out)?; // to %% no. 5
3133
3134		// Generate the table of rule information
3135		// Note: This code depends on the fact that rules are number sequentually beginning with 0.
3136		write!(out, "const RULES_INFO: [CodeType; {}] =", self.rules.len())?;
3137		let mut formatter = ArrayFormatter::new(16);
3138		for rule in &self.rules
3139		{	formatter.separ(out)?;
3140			write!(out, "{:4}", rule.lhs_index)?;
3141		}
3142		formatter.end(out)?;
3143
3144		// Next
3145		lempar_reader.copy_part(out)?; // to %% no. 6
3146
3147		// First output rules other than the default: rule
3148		for rule in self.rules.iter()
3149		{	if !rule.code.is_empty() // Will be default:
3150			{	write!(out, "\t\t\t{} =>", rule.index)?;
3151				let has_data_type = !self.symbols.array[rule.lhs_index].data_type.is_empty();
3152				let mut next_indent = "\t\t\t\t";
3153				if has_data_type && !rule.lhs_start
3154				{	write!(out, " MinorType::Symbol{}\n\t\t\t(\t{{", self.symbols.array[rule.lhs_index].dtnum)?;
3155					next_indent = "\t\t\t\t\t";
3156				}
3157				else
3158				{	write!(out, "\n\t\t\t{{")?;
3159				}
3160				let mut indent = "\t";
3161				let mut n_aliases = 0;
3162				let n_args = rule.rhs.len();
3163				for i in (0 .. n_args).rev()
3164				{	let has_alias = !rule.rhs[i].alias.is_empty();
3165					if has_alias
3166					{	n_aliases += 1;
3167						writeln!(out, "{}let arg{} = self.stack.pop().unwrap();", indent, i+1)?;
3168					}
3169					else
3170					{	writeln!(out, "{}self.stack.pop();", indent)?;
3171					}
3172					indent = next_indent;
3173				}
3174				if n_aliases > 0
3175				{	write!(out, "{}{}match {}", indent, if rule.lhs_start {"let result = "} else {""}, if n_aliases>1 {"("} else {""})?;
3176					let mut comma = "";
3177					for i in 0 .. n_args
3178					{	if !rule.rhs[i].alias.is_empty()
3179						{	write!(out, "{}arg{}.minor", comma, i+1)?;
3180							comma = ", ";
3181						}
3182					}
3183					write!(out, "{}\n{}{{\t{}", if n_aliases>1 {")"} else {""}, indent, if n_aliases>1 {"("} else {""})?;
3184					comma = "";
3185					for (i, rhs) in rule.rhs.iter().enumerate()
3186					{	if !rhs.alias.is_empty()
3187						{	write!(out, "{}MinorType::Symbol{}(arg{})", comma, self.symbols.array[rhs.index].dtnum, i+1)?;
3188							comma = ", ";
3189						}
3190					}
3191					write!(out, "{} => super::rules::do_rule_{}(&mut self.extra", if n_aliases>1 {")"} else {""}, rule.index)?;
3192					for i in 0 .. n_args
3193					{	if !rule.rhs[i].alias.is_empty()
3194						{	write!(out, ", arg{}", i+1)?;
3195						}
3196					}
3197					if rule.lhs_start
3198					{	writeln!(out, "),\n{}\t_ => unreachable!()\n{}}};\n\t\t\t\tself.result = Some(result);\n\t\t\t\tMinorType::None\n\t\t\t}},", indent, indent)?;
3199					}
3200					else if has_data_type
3201					{	writeln!(out, "),\n{}\t_ => unreachable!()\n{}}}\n\t\t\t\t}}\n\t\t\t),", indent, indent)?;
3202					}
3203					else
3204					{	writeln!(out, "),\n{}\t_ => unreachable!()\n{}}};\n\t\t\t\tMinorType::None\n\t\t\t}},", indent, indent)?;
3205					}
3206				}
3207				else
3208				{	if rule.lhs_start
3209					{	writeln!(out, "{}self.result = Some(super::rules::do_rule_{}(&mut self.extra));\n\t\t\t\tMinorType::None\n\t\t\t}},", indent, rule.index)?;
3210					}
3211					else if has_data_type
3212					{	writeln!(out, "{}super::rules::do_rule_{}(&mut self.extra)\n\t\t\t}}),", indent, rule.index)?;
3213					}
3214					else
3215					{	writeln!(out, "{}super::rules::do_rule_{}(&mut self.extra);\n\t\t\t\tMinorType::None\n\t\t\t}},", indent, rule.index)?;
3216					}
3217				}
3218			}
3219		}
3220		// Finally, output the default: rule.
3221		writeln!(out, "\t\t\t_ =>\n\t\t\t{{\tself.stack.pop(); MinorType::None\n\t\t\t}}")?;
3222
3223		// Next
3224		lempar_reader.copy_part(out)?; // to %% no. 7
3225
3226		writeln!(out, "\n}}\n\n\nmod rules\n{{\tuse super::code::{{TokenValue, ExtraArgumentType}};")?;
3227		for rule in self.rules.iter()
3228		{	let rule = rule;
3229			if !rule.code.is_empty()
3230			{	write!(out, "\n\t/// {}\n", rule)?;
3231				write!(out, "\t#[inline]\n\t#[allow(non_snake_case, unused_variables)]\n")?;
3232				write!(out, "\tpub fn do_rule_{}(extra: &mut ExtraArgumentType", rule.index)?;
3233				for rhs in &rule.rhs
3234				{	if !rhs.alias.is_empty()
3235					{	let data_type = if rhs.index < self.n_terminals
3236						{	"TokenValue"
3237						}
3238						else
3239						{	&self.symbols.array[rhs.index].data_type
3240						};
3241						write!(out, ", {}: {}", rhs.alias, if data_type.is_empty() {"()"} else {data_type})?;
3242					}
3243				}
3244				write!(out, ")")?;
3245				let lhs = &self.symbols.array[rule.lhs_index];
3246				if !lhs.data_type.is_empty()
3247				{	write!(out, " -> {}", lhs.data_type)?;
3248				}
3249				write!(out, "\n\t{{\t")?;
3250				let mut it = rule.code.chars();
3251'l:				while let Some(mut c) = it.next()
3252				{	'm:while c == '\n'
3253					{	write!(out, "\n\t\t")?;
3254						while let Some(c2) = it.next()
3255						{	if c2=='\n' || !c2.is_ascii_whitespace()
3256							{	c = c2;
3257								continue 'm;
3258							}
3259						}
3260						break 'l;
3261					}
3262					write!(out, "{}", c)?;
3263				}
3264				writeln!(out, "\n\t}}")?;
3265			}
3266		}
3267		writeln!(out, "}}\n")?;
3268
3269		// End
3270		lempar_reader.copy_part(out)?;
3271		if !self.extracode.is_empty()
3272		{	writeln!(out, "\n\n{}", self.extracode)?;
3273		}
3274
3275		Ok(())
3276	}
3277
3278	/// Write a human-readable report of the generated state machine (classic Lemon's `y.output`).
3279	///
3280	/// Useful for understanding the parser and for debugging grammar conflicts.
3281	///
3282	/// * `basisflag` - print only the basis configurations of each state, not the full closure.
3283	/// * `show_precedence_conflict` - also report conflicts that were resolved by precedence rules.
3284	pub fn gen_log<W>(&self, out: &mut W, basisflag: bool, show_precedence_conflict: bool) -> io::Result<()> where W: io::Write
3285	{	for stp in self.states.array[0 .. self.states.n_no_tail].iter()
3286		{	writeln!(out, "State {}:", stp.n_state)?;
3287
3288			for cfp in stp.configurations.iter()
3289			{	if basisflag
3290				{	let mut is_basis = false;
3291					for bp in stp.basis.iter()
3292					{	if *cfp.borrow() == *bp.borrow()
3293						{	is_basis = true;
3294							break;
3295						}
3296					}
3297					if !is_basis
3298					{	continue;
3299					}
3300				}
3301				if cfp.borrow().dot == self.rules[cfp.borrow().n_rule].rhs.len()
3302				{	let buf = format!("({})", self.rules[cfp.borrow().n_rule].index);
3303					write!(out, "    {:>5} ", buf)?;
3304				}
3305				else
3306				{	write!(out, "          ")?;
3307				}
3308				Self::config_print(&self.rules, out, cfp)?;
3309				writeln!(out, "")?;
3310			}
3311
3312			writeln!(out, "")?;
3313			for action in stp.actions.iter()
3314			{	if Self::print_action(&self.symbols, &self.rules, action, out, 30, show_precedence_conflict)?
3315				{	writeln!(out, "")?;
3316				}
3317			}
3318			writeln!(out, "")?;
3319		}
3320		writeln!(out, "----------------------------------------------------")?;
3321		writeln!(out, "Symbols:")?;
3322		for i in 0 .. self.symbols.n_symbols
3323		{	let sp = &self.symbols.array[i];
3324			write!(out, " {:>3}: {}", i, sp.name)?;
3325			if sp.typ == SymbolType::NONTERMINAL
3326			{	write!(out, ":")?;
3327				if sp.lambda
3328				{	write!(out, " <lambda>")?;
3329				}
3330				for j in 0 .. self.symbols.n_terminals
3331				{	if sp.firstset.len()>0 && sp.firstset.contains(j)
3332					{	write!(out, " {}", self.symbols.array[j].name)?;
3333					}
3334				}
3335			}
3336			writeln!(out, "")?;
3337		}
3338		Ok(())
3339	}
3340
3341	fn config_print<W>(rules: &Vec<Rule>, out: &mut W, cfp: &Rc<RefCell<Config>>) -> io::Result<()> where W: io::Write
3342	{	write!(out, "{} ::=", rules[cfp.borrow().n_rule].lhs)?;
3343		for i in 0 ..= rules[cfp.borrow().n_rule].rhs.len()
3344		{	if i == cfp.borrow().dot
3345			{	write!(out, " *")?;
3346			}
3347			if i == rules[cfp.borrow().n_rule].rhs.len()
3348			{	break;
3349			}
3350			write!(out, " {}", rules[cfp.borrow().n_rule].rhs[i].name)?;
3351		}
3352		Ok(())
3353	}
3354
3355	/// Print an action to the given file descriptor.  Return FALSE if nothing was actually printed.
3356	fn print_action<W>(symbols: &Symbols, rules: &[Rule], action: &Rc<RefCell<Action>>, out: &mut W, indent: usize, show_precedence_conflict: bool) -> io::Result<bool> where W: io::Write
3357	{	let mut result = false;
3358		match action.borrow().typ
3359		{	ActionType::Shift =>
3360			{	if let StateOrRule::State(n_state) = action.borrow().x
3361				{	write!(out, "{:>w$} shift        {:<7}", symbols.array[action.borrow().symbol_index].name, n_state, w=indent)?;
3362					result = true;
3363				}
3364			}
3365			ActionType::Reduce =>
3366			{	if let StateOrRule::Rule(n_rule) = action.borrow().x
3367				{	write!(out, "{:>w$} reduce       {:<7}", symbols.array[action.borrow().symbol_index].name, rules[n_rule].index, w=indent)?;
3368					Self::rule_print(out, &rules[n_rule], std::usize::MAX)?;
3369					result = true;
3370				}
3371			}
3372			ActionType::ShiftReduce =>
3373			{	if let StateOrRule::Rule(n_rule) = action.borrow().x
3374				{	write!(out, "{:>w$} shift-reduce {:<7}", symbols.array[action.borrow().symbol_index].name, rules[n_rule].index, w=indent)?;
3375					Self::rule_print(out, &rules[n_rule], std::usize::MAX)?;
3376					result = true;
3377				}
3378			}
3379			ActionType::Accept =>
3380			{	write!(out, "{:>w$} accept", symbols.array[action.borrow().symbol_index].name, w=indent)?;
3381				result = true;
3382			}
3383			ActionType::Error =>
3384			{	write!(out, "{:>w$} error", symbols.array[action.borrow().symbol_index].name, w=indent)?;
3385				result = true;
3386			}
3387			ActionType::SrConflict | ActionType::RrConflict =>
3388			{	if let StateOrRule::Rule(n_rule) = action.borrow().x
3389				{	write!(out, "{:>w$} reduce       {:<7} ** Parsing conflict **", symbols.array[action.borrow().symbol_index].name, rules[n_rule].index, w=indent)?;
3390					result = true;
3391				}
3392			}
3393			ActionType::SsConflict =>
3394			{	if let StateOrRule::State(n_state) = action.borrow().x
3395				{	write!(out, "{:>w$} shift        {:<7} ** Parsing conflict **", symbols.array[action.borrow().symbol_index].name, n_state, w=indent)?;
3396					result = true;
3397				}
3398			}
3399			ActionType::ShResolved =>
3400			{	if show_precedence_conflict
3401				{	if let StateOrRule::State(n_state) = action.borrow().x
3402					{	write!(out, "{:>w$} shift        {:<7} -- dropped by precedence", symbols.array[action.borrow().symbol_index].name, n_state, w=indent)?;
3403						result = true;
3404					}
3405				}
3406			}
3407			ActionType::RdResolved =>
3408			{	if show_precedence_conflict
3409				{	if let StateOrRule::Rule(n_rule) = action.borrow().x
3410					{	write!(out, "{:>w$} reduce {:<7} -- dropped by precedence", symbols.array[action.borrow().symbol_index].name, rules[n_rule].index, w=indent)?;
3411						result = true;
3412					}
3413				}
3414			}
3415			ActionType::NotUsed => {}
3416		}
3417		Ok(result)
3418	}
3419
3420	/// Print a single rule.
3421	fn rule_print<W>(out: &mut W, rule: &Rule, cursor: usize) -> io::Result<()> where W: io::Write
3422	{	write!(out, "{} ::=", rule.lhs)?;
3423		for (i, symbol) in rule.rhs.iter().enumerate()
3424		{	if i == cursor
3425			{	write!(out, " *")?;
3426			}
3427			write!(out, " {}", symbol.name)?;
3428		}
3429		if cursor == rule.rhs.len()
3430		{	write!(out, " *")?;
3431		}
3432		Ok(())
3433	}
3434
3435	/// Write a normalized copy of the grammar to `out`: the list of symbols and the rules, without
3436	/// comments or action code. Handy when the grammar was assembled through builder calls and you
3437	/// want to see the equivalent Y-grammar.
3438	pub fn gen_y<W>(&self, out: &mut W) -> io::Result<()> where W: io::Write
3439	{	writeln!(out, "// Symbols:")?;
3440		let mut maxlen = 10;
3441		for sp in self.symbols.array[0 .. self.symbols.n_symbols].iter()
3442		{	if sp.name.len() > maxlen
3443			{	maxlen = sp.name.len();
3444			}
3445		}
3446		let mut ncolumns = 76 / (maxlen+5);
3447		if ncolumns < 1
3448		{	ncolumns = 1;
3449		}
3450		let skip = (self.symbols.n_symbols+ncolumns-1) / ncolumns;
3451		for i in 0 .. skip
3452		{	write!(out, "//")?;
3453			for j in (i .. self.symbols.n_symbols).step_by(skip)
3454			{	let sp = &self.symbols.array[j];
3455				assert_eq!(sp.index, j);
3456				write!(out, " {:3} {:<w$}", maxlen, sp.name, w=maxlen)?;
3457			}
3458			writeln!(out, "")?;
3459		}
3460		writeln!(out, "")?;
3461		// %start_symbol
3462		if !self.start_name.is_empty()
3463		{	writeln!(out, "%start_symbol {{{}}}", self.start_name)?;
3464		}
3465		// %token_type
3466		if !self.token_type.is_empty()
3467		{	writeln!(out, "%token_type {{{}}}", self.token_type)?;
3468		}
3469		// %default_type
3470		if !self.vartype.is_empty()
3471		{	writeln!(out, "%default_type {{{}}}", self.vartype)?;
3472		}
3473		// %extra_argument
3474		if !self.extra_argument_type.is_empty()
3475		{	writeln!(out, "%extra_argument {{{}}}", self.extra_argument_type)?;
3476		}
3477		// %left, %right, %nonassoc
3478		let mut prec = 0;
3479		loop
3480		{	let mut has_greater_prec = false;
3481			let mut started = false;
3482			for symbol in self.symbols.array[1 .. self.symbols.n_terminals].iter()
3483			{	if symbol.prec >= prec
3484				{	if symbol.prec > prec
3485					{	has_greater_prec = true;
3486					}
3487					else
3488					{	if !started
3489						{	write!(out, "{}", if symbol.assoc== Associativity::LEFT {"%left"} else if symbol.assoc== Associativity::RIGHT {"%right"} else {"%nonassoc"})?;
3490							started = true;
3491						}
3492						write!(out, " {}", symbol.name)?;
3493					}
3494				}
3495			}
3496			if started
3497			{	writeln!(out, ".")?;
3498			}
3499			if !has_greater_prec
3500			{	break;
3501			}
3502			prec += 1;
3503		}
3504		// %type
3505		for symbol in self.symbols.array[self.symbols.n_terminals+1 .. self.symbols.n_symbols].iter()
3506		{	let symbol = symbol;
3507			writeln!(out, "%type {} {{{}}}", symbol.name, symbol.data_type)?;
3508		}
3509		// rules
3510		for rule in self.rules.iter()
3511		{	write!(out, "{}", rule.lhs)?;
3512			if self.symbols.array[rule.lhs_index].dtnum != 0
3513			{	write!(out, "(RESULT)")?;
3514			}
3515			write!(out, " ::=")?;
3516			for sp in &rule.rhs
3517			{	write!(out, " {}", sp.name)?;
3518				if !sp.alias.is_empty()
3519				{	write!(out, "({})", sp.alias)?;
3520				}
3521			}
3522			write!(out, ".")?;
3523			if rule.precsym_index != std::usize::MAX
3524			{	write!(out, " [{}]", self.symbols.array[rule.precsym_index].name)?;
3525			}
3526			if !rule.code.is_empty()
3527			{	writeln!(out, " {{\n{}\n}}", rule.code)?;
3528			}
3529			writeln!(out, "")?;
3530		}
3531		Ok(())
3532	}
3533}
3534impl TryFrom<LemonMintBuilder> for LemonMint
3535{	type Error = LemonMintError;
3536
3537	fn try_from(builder: LemonMintBuilder) -> ParserResult<Self>
3538	{	builder.try_into_lemon()
3539	}
3540}
3541
3542#[cfg(not(feature = "with-debug"))]
3543fn dump_symbols(_symbols: &Symbols, _rules: &Vec<Rule>)
3544{
3545}
3546
3547#[cfg(not(feature = "with-debug"))]
3548fn dump_states(_states: &States, _rules: &Vec<Rule>, _symbols: &Symbols, _n: i32)
3549{
3550}
3551
3552#[cfg(feature = "with-debug")]
3553fn dump_symbols(symbols: &Symbols, rules: &Vec<Rule>)
3554{	use std::io::prelude::*;
3555	let mut out = File::create("/tmp/symbols-rust.js").unwrap();
3556	for s in symbols.array.iter()
3557	{	writeln!(out, "{} ({}) {:?} #{} {:?} {} {}LAM:", s.name, s.index, s.typ, s.dtnum, s.assoc, s.prec, if s.lambda {""} else {"!"}).unwrap();
3558		if s.firstset.len() > 0
3559		{	write!(out, "  ").unwrap();
3560			for (j, v) in s.firstset.data.iter().enumerate()
3561			{	write!(out, "{}{}", if j%4==0&&j>0 {" "} else {""}, if *v {'y'} else {'n'}).unwrap();
3562			}
3563			writeln!(out).unwrap();
3564		}
3565		for n_rule in s.sym_rules_arr.iter()
3566		{	let rule = &rules[*n_rule];
3567			writeln!(out, "   {} = {}", rule.index, rule.code).unwrap();
3568		}
3569	}
3570	/*	The same in lemon.c:
3571
3572		void dump_symbols(struct lemon *lemp)
3573		{	FILE *out = fopen("/tmp/symbols-c.js", "w");
3574			for (int i=0; i<lemp->nsymbol+1; i++)
3575			{	struct symbol *sym = lemp->symbols[i];
3576				fprintf(out, "%s (%d) %s #%d %s %d %s:\n", sym->name, sym->index, sym->type==TERMINAL?"TERMINAL":"NONTERMINAL", sym->dtnum, sym->assoc==LEFT?"LEFT":sym->assoc==RIGHT?"RIGHT":sym->assoc==NONE?"NONE":"UNKNOWN", sym->prec, sym->lambda?"LAM":"!LAM");
3577				if (sym->firstset)
3578				{	fprintf(out, "  ");
3579					for (int j=0; j<lemp->nterminal+1; j++)
3580					{	fprintf(out, "%s%c", j%4==0&&j>0 ? " " : "", sym->firstset[j]?'y':'n');
3581					}
3582					fprintf(out, "\n");
3583				}
3584				for (struct rule *rp=sym->rule; rp; rp=rp->nextlhs)
3585				{	const char *code = rp->code;
3586					if (code == nullptr) code = "";
3587					while (ISSPACE(code[0])) code++;
3588					int len = strlen(code);
3589					while (len>0 && ISSPACE(code[len-1])) len--;
3590					fprintf(out, "  %d = %.*s\n", rp->index, len, code);
3591				}
3592			}
3593			fclose(out);
3594		}
3595	*/
3596}
3597
3598#[cfg(feature = "with-debug")]
3599fn dump_states(states: &States, rules: &Vec<Rule>, symbols: &Symbols, n: i32)
3600{	use std::io::prelude::*;
3601	let mut out = File::create(format!("/tmp/states-{}-rust.js", n)).unwrap();
3602	for s in states.array.iter()
3603	{	writeln!
3604		(	out,
3605			"{}. nTknAct={}, nNtAct={}, iTknOfst={}, iNtOfst={}, iDfltReduce={}, {} dfR{}[{}]",
3606			s.n_state,
3607			s.n_token_act,
3608			s.n_nt_act,
3609			if s.token_offset==std::isize::MIN {-1000} else {s.token_offset},
3610			if s.nt_offset==std::isize::MIN {-1000} else {s.nt_offset},
3611			if s.default_reduce_action==std::usize::MAX {-1} else {s.default_reduce_action as isize},
3612			if s.auto_reduce {"A"} else {"!A"},
3613			if s.default_reduce_rule==std::usize::MAX {-1} else {s.default_reduce_rule as isize},
3614			if s.default_reduce_rule==std::usize::MAX {"".to_string()} else {rules[s.default_reduce_rule].lhs.to_string()}
3615		).unwrap();
3616		for cfp in s.basis.iter()
3617		{	let cfp = cfp.borrow();
3618			writeln!(out, "  bs{} R{}[{}] .{}", cfp.n_state as isize, cfp.n_rule, rules[cfp.n_rule].lhs, cfp.dot).unwrap();
3619		}
3620		for cfp in s.configurations.iter()
3621		{	let cfp = cfp.borrow();
3622			// rule
3623			writeln!(out, "  cf{} R{}[{}] .{}", cfp.n_state as isize, cfp.n_rule, rules[cfp.n_rule].lhs, cfp.dot).unwrap();
3624			// fws
3625			let mut delim = "";
3626			write!(out, "{:<12}[", "").unwrap();
3627			for (j, v) in cfp.fws.data.iter().enumerate()
3628			{	if *v
3629				{	write!(out, "{}{}", delim, symbols.array[j].name).unwrap();
3630					delim = " ";
3631				}
3632			}
3633			writeln!(out, "]").unwrap();
3634			// fplp
3635			for cfp in cfp.fplp.iter()
3636			{	write!(out, "{:<12}{} (state {:2}) ", "", "To  ", cfp.borrow().n_state as isize).unwrap();
3637				LemonMint::config_print(rules, &mut out, cfp).unwrap();
3638				writeln!(out).unwrap();
3639			}
3640			// bplp
3641			for cfp in cfp.bplp.iter()
3642			{	write!(out, "{:<12}{} (state {:2}) ", "", "From", cfp.borrow().n_state as isize).unwrap();
3643				LemonMint::config_print(rules, &mut out, cfp).unwrap();
3644				writeln!(out).unwrap();
3645			}
3646		}
3647		for action in s.actions.iter()
3648		{	if LemonMint::print_action(symbols, rules, action, &mut out, 30, true).unwrap()
3649			{	writeln!(out).unwrap();
3650			}
3651		}
3652	}
3653	/*	The same in lemon.c:
3654
3655		void dump_states(struct lemon *lemp, int n)
3656		{	char filename[1024];
3657			sprintf(filename, "/tmp/states-%d-c.js", n);
3658			FILE *out = fopen(filename, "w");
3659			showPrecedenceConflict = 1;
3660			for (int i=0; i<lemp->nstate; i++)
3661			{	struct state *stp = lemp->sorted[i];
3662				fprintf
3663				(	out,
3664					"%d. nTknAct=%d, nNtAct=%d, iTknOfst=%d, iNtOfst=%d, iDfltReduce=%d, %s dfR%d[%s]\n",
3665					stp->statenum,
3666					stp->nTknAct,
3667					stp->nNtAct,
3668					stp->iTknOfst==NO_OFFSET ? -1000 : stp->iTknOfst,
3669					stp->iNtOfst==NO_OFFSET ? -1000 : stp->iNtOfst,
3670					stp->iDfltReduce,
3671					stp->autoReduce?"A":"!A",
3672					stp->pDfltReduce ? stp->pDfltReduce->index : -1,
3673					stp->pDfltReduce ? stp->pDfltReduce->lhs->name : ""
3674				);
3675				for (struct config *cfp=stp->bp; cfp; cfp=cfp->bp)
3676				{	fprintf(out, "  bs%d R%d[%s] .%d\n", cfp->stp ? cfp->stp->statenum : -1, cfp->rp->index, cfp->rp->lhs->name, cfp->dot);
3677				}
3678				for (struct config *cfp=stp->cfp; cfp; cfp=cfp->next)
3679				{	fprintf(out, "  cf%d R%d[%s] .%d\n", cfp->stp ? cfp->stp->statenum : -1, cfp->rp->index, cfp->rp->lhs->name, cfp->dot);
3680					SetPrint(out, cfp->fws,lemp);
3681					PlinkPrint(out, cfp->fplp,"To  ");
3682					PlinkPrint(out, cfp->bplp,"From");
3683				}
3684				for (struct action *ap=stp->ap; ap; ap=ap->next)
3685				{	if (PrintAction(ap, out, 30)) fprintf(out, "\n");
3686				}
3687			}
3688			fclose(out);
3689		}
3690	*/
3691}