diff --git a/.gitignore b/.gitignore index a0b4a1b..7a67f03 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ lalrpop/src/parser/lrgrammar.rs doc/calculator/src/calculator1.rs doc/calculator/src/calculator2.rs +doc/calculator/src/calculator2b.rs doc/calculator/src/calculator3.rs doc/calculator/src/calculator4.rs doc/calculator/src/calculator5.rs diff --git a/doc/calculator/src/calculator2b.lalrpop b/doc/calculator/src/calculator2b.lalrpop new file mode 100644 index 0000000..f620d6b --- /dev/null +++ b/doc/calculator/src/calculator2b.lalrpop @@ -0,0 +1,38 @@ +grammar; + +pub Term = { + Num, + "(" ")", + "22" => format!("Twenty-two!"), + ID => format!("Id({})", <>), +}; + +Num: String = r"[0-9]+" => <>.to_string(); + +// `match`: Declares the precedence of regular expressions +// relative to one another when synthesizing +// the lexer +match { + // These items have highest precedence. + + r"[0-9]+", + + // Within a match level, fixed strings like `"22"` get + // precedence over regular expresions. + "22" +} else { + // These items have next highest precedence. + + // Given an input like `123`, the number regex above + // will match; but otherwise, given something like + // `123foo` or `foo123`, this will match. + // + // Here, we also renamed the regex to the name `ID`, which we can + // use in the grammar itself. + r"\w+" => ID, + + // This `_` means "add in all the other strings and + // regular expressions in the grammer here" (e.g., + // `"("`). + _ +} // you can have more `else` sections if you like diff --git a/doc/calculator/src/main.rs b/doc/calculator/src/main.rs index 8112dc1..5976395 100644 --- a/doc/calculator/src/main.rs +++ b/doc/calculator/src/main.rs @@ -20,6 +20,16 @@ fn calculator2() { assert!(calculator2::parse_Term("((22)").is_err()); } +pub mod calculator2b; + +#[test] +fn calculator2b() { + assert_eq!(calculator2b::parse_Term("33").unwrap(), "33"); + assert_eq!(calculator2b::parse_Term("foo33").unwrap(), "Id(foo33)"); + assert_eq!(calculator2b::parse_Term("(22)").unwrap(), "Twenty-two!"); + assert_eq!(calculator2b::parse_Term("(222)").unwrap(), "222"); +} + pub mod calculator3; macro_rules! test3 { @@ -74,7 +84,7 @@ fn calculator6() { "[((22 * 44) + 66), (error * 3)]"); assert_eq!(&format!("{:?}", calculator6::parse_Exprs(&mut errors, "*").unwrap()), "[(error * error)]"); - + assert_eq!(errors.len(), 4); } diff --git a/doc/tutorial.md b/doc/tutorial.md index 23d1563..29351eb 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -27,6 +27,8 @@ want to skip ahead, or just look at the LALRPOP sources: ([source][calculator1], [read](#calculator1)) - calculator2: LALRPOP shorthands and type inference ([source][calculator2], [read](#calculator2)) +- calculator2b: Controlling the lexer with `match` declarations + ([source][calculator2b], [read](#calculator2b)) - calculator3: Handling full-featured expressions like `22+44*66` ([source][calculator3], [read](#calculator3)) - calculator4: Building ASTs @@ -35,6 +37,8 @@ want to skip ahead, or just look at the LALRPOP sources: ([source][calculator5], [read](#calculator5)) - calculator6: Error recovery ([source][calculator6], [read](#calculator6)) +- calculator7: `match` declarations and controlling the lexer/tokenizer + ([source][calculator7], [read](#calculator7)) This tutorial is still incomplete. Here are some topics that I aim to cover when I get time to write about them: @@ -169,11 +173,11 @@ case, just LALRPOP. The `[dependencies]` section describes the dependencies that LALRPOP needs at runtime. All LALRPOP parsers require at least the `lalrpop-util` crate. In addition, if you don't want to write the -lexer by hand, you need to add a dependency on the regex crate. (If +lexer by hand, you need to add a dependency on the regex crate. (If you don't know what a lexer is, don't worry, it's not important just -now; if you *do* know what a lexer is, and you want to know how to -write a lexer by hand and use it with LALRPOP, then check out the -[lexer tutorial].) +now, though we will cover it in [section 7][calculator7]; if you *do* +know what a lexer is, and you want to know how to write a lexer by +hand and use it with LALRPOP, then check out the [lexer tutorial].) [lexer tutorial]: lexer_tutorial.md @@ -408,6 +412,317 @@ give you the idea: | ` B => bar(<>)` | ` B => bar(a)` | | ` => bar(<>)` | ` => bar(a, b)` | + +### calculator2b: Controlling the lexer with `match` declarations + +This example dives a bit deeper into how LALRPOP works. In particular, +it dives into the meaning of those strings and regular expression that +we used in the previous tutorial, and how they are used to process the +input string (a process which you can control). This first step of +breaking up the input using regular expressions is often called +**lexing** or **tokenizing**. + +If you're comfortable with the idea of a lexer or tokenizer, you may +wish to skip ahead to the [calculator3](#calculator3) example, which covers +parsing bigger expressions, and come back here only when you find you +want more control. You may also be interested in the +[tutorial on writing a custom lexer][lexer tutorial]. + +#### Terminals vs nonterminals + +You may have noticed that our grammar included two distinct kinds of +symbols. There were the nonterminals, `Term` and `Num`, which we +defined by specifying a series of symbols that they must match, along +with some action code that should execute once they have matched: + +```rust + Num: i32 = r"[0-9]+" => i32::from_str(<>).unwrap(); +// ~~~ ~~~ ~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~ +// | | | Action code +// | | Symbol(s) that should match +// | Return type +// Name of nonterminal +``` + +But there are also **terminals**, which consist of the string literals +and regular expressions sprinkled throughout the grammar. (Terminals +are also often called **tokens**, and I will use the terms +interchangeably.) + +This distinction between terminals and nonterminals is very important +to how LALRPOP works. In fact, when LALRPOP generates a parser, it +always works in a two-phase process. The first phase is called the +**lexer** or **tokenizer**. It has the job of figuring out the +sequence of **terminals**: so basically it analyzes the raw characters +of your text and breaks them into a series of terminals. It does this +without having any idea about your grammar or where you are in your +grammar. Next, the parser proper is a bit of code that looks at this +stream of tokens and figures out which nonterminals apply: + + +-------------------+ +----------------------+ + Text -> | Lexer | -> | Parser | + | | | | + | Applies regex to | | Consumers terminals, | + | produce terminals | | executes your code | + +-------------------+ | as it recognizes | + | nonterminals | + +----------------------+ + +LALRPOP's default lexer is based on regular expressions. By default, +it works by extracting all the terminals (e.g., `"("` or `r"\d+"`) +from your grammar and compiling them into one big list. At runtime, it +will walk over the string and, at each point, find the longest match +from the literals and regular expressions in your grammar and produces +one of those. As an example, let's look again at our example grammar: + +``` +pub Term: i32 = { + => n, + "(" ")" => t, +}; + +Num: i32 = => i32::from_str(s).unwrap(); +``` + +This grammar in fact contains three terminals: + +- `"("` -- a string literal, which must match exactly +- `")"` -- a string literal, which must match exactly +- `r"[0-9]+"` -- a regular expression + +When we generate a lexer, it is effectively going to be checking for +each of these three terminals in a loop, sort of like this pseudocode: + +``` +let mut i = 0; // index into string +loop { + skip whitespace; // we do this implicitly, at least by default + if (data at index i is "(") { produce "("; } + else if (data at index i is ")") { produce ")"; } + else if (data at index i matches regex "[0-9]+") { produce r"[0-9]+"; } +} +``` + +Note that this has nothing to do with your grammar. For example, the tokenizer +would happily tokenize a string like this one, which doesn't fit our grammar: + +``` + ( 22 44 ) ) + ^ ^^ ^^ ^ ^ + | | | | ")" terminal + | | | | + | | | ")" terminal + | +----+ + | | + | 2 r"[0-9]+" terminals + | + "(" terminal +``` + +When these tokens are fed into the **parser**, it would notice that we +have one left paren but then two numbers (`r"[0-9]+"` terminals), and +hence report an error. + +#### Precedence of fixed strings + +Terminals in LALRPOP can be specified (by default) in two ways. As a +fixed string (like `"("`) or a regular expression (like +`r[0-9]+`). There is actually an important difference: if, at some +point in the input, both a fixed string **and** a regular expression +could match, LALRPOP gives the fixed string precedence. To demonstrate +this, let's modify our parser. If you recall, the current parser +parses parenthesized numbers, producing a `i32`. We're going to modify +if to produce a **string**, and we'll add an "easter egg" so that `22` +(or `(22)`, `((22))`, etc) produces the string `"Twenty-two"`: + +``` +pub Term = { + Num, + "(" ")", + "22" => format!("Twenty-two!"), +}; + +Num: String = r"[0-9]+" => <>.to_string(); +``` + +If we write some simple unit tests, we can see that in fact an input +of `22` has matched the string literal. Interestingly, the input `222` +matches the regular expression instead; this is because LALRPOP +prefers to find the **longest** match first. After that, if there are +two matches of equal length, it prefers the fixed string: + +```rust +#[test] +fn calculator2b() { + assert_eq!(calculator2b::parse_Term("33").unwrap(), "33"); + assert_eq!(calculator2b::parse_Term("(22)").unwrap(), "Twenty-two!"); + assert_eq!(calculator2b::parse_Term("(222)").unwrap(), "222"); +} +``` + +#### Ambiguities between regular expressions + +In the previous section, we saw that fixed strings have precedence +over regular expressions. But what if we have two regular expressions +that can match the same input? Which one wins? For example, consider +this various of the grammar above, where we also try to support +parenthesized **identifiers** like `((foo22))`: + +``` +pub Term = { + Num, + "(" ")", + "22" => format!("Twenty-two!"), + r"\w+" => format!("Id({})", <>), // <-- we added this +}; + +Num: String = r"[0-9]+" => <>.to_string(); +``` + +Here I've written the regular expression `r\w+`. However, if you check +out the [docs for regex](https://docs.rs/regex), you'll see that `\w` +is defined to match alphabetic characteres but also digits. So there +is actually an ambiguity here: if we have something like `123`, it +could be considered to match either `r"[0-9]+"` **or** `r"\w+"`. If +you try this grammar, you'll find that LALRPOP helpfully reports an +error: + +``` +error: ambiguity detected between the terminal `r#"\w+"#` and the terminal `r#"[0-9]+"#` + + r"\w+" => <>.to_string(), + ~~~~~~ +``` + +There are various ways to fix this. We might try adjusting our regular +expression so that the first character cannot be a number, so perhaps +something like `r"[[:alpha:]]\w*"`. This will work, but it actually +matches something different than what we had before (e.g., `123foo` +will not be considered to match, for better or worse). And anyway it's +not always convenient to make your regular expressions completely +disjoint like that. Another option is to use a `match` declaration, +which lets you control the precedence between regular expressions. + +#### Simple `match` declarations + +A `match` declaration lets you explicitly give the precedence between +terminals. In its simplest form, it consists of just ordering regular +expressions and string literals into groups, with the higher +precedence items coming first. So, for example, we could resolve +our conflict above by giving `r"[0-9]+"` **precedence** over `r"\w+"`, +thus saying that if something can be lexed as a number, we'll do that, +and otherwise consider it to be an identifier. + +``` +match { + r"[0-9]+" +} else { + r"\w+", + _ +} +``` + +Here the match contains two levels; each level can have more than one +item in it. The top-level contains only `r"[0-9]+"`, which means that this +regular expression is given highest priority. The next level contains +`r\w+`, so that will match afterwards. + +The final `_` indicates that other string literals and regular +expressions that appear elsewhere in the grammar (e.g., `"("` or +`"22"`) should be added into that final level of precedence (without +an `_`, it is illegal to use a terminal that does not appear in the +match declaration). + +If we add this `match` section into our example, we'll find that it +compiles, but it doesn't work exactly like we wanted. Let's update our +unit test a bit to include some identifier examples:: + +```rust +#[test] +fn calculator2b() { + // These will all work: + assert_eq!(calculator2b::parse_Term("33").unwrap(), "33"); + assert_eq!(calculator2b::parse_Term("foo33").unwrap(), "Id(foo33)"); + assert_eq!(calculator2b::parse_Term("(foo33)").unwrap(), "Id(foo33)"); + + // This line will fail: + assert_eq!(calculator2b::parse_Term("(22)").unwrap(), "Twenty-two!"); +} +``` + +The problem comes about when we parse `22`. Before, the fixed string +`22` got precedence, but with the new match declaration, we've +explicitly stated that the regular expression `r"[0-9]+"` has full +precedence. Since the `22` is not listed explicitly, it gets added at +the last level, where the `_` appears. We can fix this by adjusting +our `match` to mention `22` explicitly: + +``` +match { + r"[0-9]+", + "22" +} else { + r"\w+", + _ +} +``` + +This raises the interesting question of what the precedence is **within** +a match rung -- after all, both the regex and `"22"` can match the same +string. The answer is that within a match rung, fixed literals get precedence +over regular expressions, just as before, and all regular expressions +must not overlap. + +With this new `match` declaration, we will find that our tests all pass. + +#### Renaming `match` declarations + +There is one final twist before we reach the +[final version of our example that you will find in the repository][calculator2b]. We +can also use `match` declarations to give names to regular +expressions, so that we don't have to type them directly in our +grammar. For example, maybe instead of writing `r"\w+"`, we would +prefer to write `ID`. We could do that by modifying the match declaration like +so: + +``` +match { + r"[0-9]+", + "22" +} else { + r"\w+" => ID, // <-- give a name here + _ +} +``` + +And then adjusting the definition of `Term` to reference `ID` instead: + +``` +pub Term = { + Num, + "(" ")", + "22" => format!("Twenty-two!"), + ID => format!("Id({})", <>), // <-- changed this +}; +``` + +In fact, the match declaration can map a regular expression to any +kind of symbol you want (i.e., you can also map to a string literal or +even a regular expression). Whatever symbol appears after the `=>` is +what you should use in your grammar. As an example, in some languages +have case-insensitive keywords; if you wanted to write `"BEGIN"` in the +grammar itself, but have that map to a regular expression in the lexer, you might write: + +``` +match { + r"(?i)begin" => "BEGIN", + ... +} +``` + +And now any reference in your grammar to `"BEGIN"` will actually match +any capitalization. + ### calculator3: Full-featured expressions @@ -768,18 +1083,141 @@ fn calculator6() { "[((22 * 44) + 66), (error * 3)]"); assert_eq!(&format!("{:?}", calculator6::parse_Exprs(&mut errors, "*").unwrap()), "[(error * error)]"); - + assert_eq!(errors.len(), 4); } ``` + +### calculator7: `match` declarations and controlling the lexer/tokenizer + +This section will describe how LALRPOP allows you to control the +generator lexer, which is the first phase of parsing, where we break +up the raw text by applying regular expressions. If you're already +familiar with what a lexer is, you may want to skip past the +introductory section. If you're more interested in using LALRPOP with +your own hand-written lexer (or you want to consume something other +than `&str` inputs), you should check out the +[tutorial on custom lexers][lexer tutorial]. + +#### What is a lexer? + +Throughout all the examples we've seen, we've drawn a distinction +between two kinds of symbols: + +- Terminals, written (thus far) as string literals or regular expressions, + like `"("` or `r"\d+"`. +- Nonterminals, written without quotes, that are defined in terms of productions, + like: + + ``` + ExprOp: Opcode = { // (3) + "+" => Opcode::Add, + "-" => Opcode::Sub, + }; + ``` + +When LALRPOP generates a parser, it always works in a two-phase +process. The first phase is called the **lexer** or **tokenizer**. It +has the job of figuring out the sequence of **terminals**: so +basically it analyzes the raw characters of your text and breaks them +into a series of terminals. It does this without having any idea about +your grammar or where you are in your grammar. Next, the parser proper +is a bit of code that looks at this stream of tokens and figures out +which nonterminals apply: + + +-------------------+ +----------------------+ + Text -> | Lexer | -> | Parser | + | | | | + | Applies regex to | | Consumers terminals, | + | produce terminals | | executes your code | + +-------------------+ | as it recognizes | + | nonterminals | + +----------------------+ + +#### How do lexers work in LALRPOP? + +LALRPOP's default lexer is based on regular expressions. By default, +it works by extracting all the terminals (e.g., `"("` or `r"\d+"`) +from your grammar and compiling them into one big list. At runtime, it +will walk over the string and, at each point, find the longest match +from the literals and regular expressions in your grammar and produces +one of those. As an example, let's go back to the +[very first grammar we saw][calculator1], which just parsed +parenthesized numbers: + +``` +pub Term: i32 = { + => n, + "(" ")" => t, +}; + +Num: i32 = => i32::from_str(s).unwrap(); +``` + +This grammar in fact contains three terminals: + +- `"("` -- a string literal, which must match exactly +- `")"` -- a string literal, which must match exactly +- `r"[0-9]+"` -- a regular expression + +When + +To help keep things concrete, let's use a simple calculator grammar. +We'll start with the grammar we saw before in +[the section on building the AST](#calculator4). It looks roughly like this +(excluding the actions for now): + +``` +Expr: Box = { + Expr ExprOp Factor, + Factor, +}; + +ExprOp: Opcode = { + "+" + "-" +}; + +Factor: Box = { + Factor FactorOp Term, + Term, +}; + +FactorOp: Opcode = { + "*" => Opcode::Mul, + "/" => Opcode::Div, +}; + +Term: Box = { + Num => Box::new(Expr::Number(<>)), + FnCode Term => Box::new(Expr::Fn(<>)), + "(" ")" +}; + +FnCode: FnCode = { + "SIN" => FnCode::Sin, + "COS" => FnCode::Cos, + ID => FnCode::Other(<>.to_string()), +}; + +Num: i32 = { + r"[0-9]+" => i32::from_str(<>).unwrap() +}; + +If you've used other parser generators before -- particularly ones +that are not PEG or parser combinators -- you may have noticed that +LALRPOP doesn't require you to specify a **tokenizer**. + [main]: ./calculator/src/main.rs [calculator]: ./calculator/ [cargotoml]: ./calculator/Cargo.toml [calculator1]: ./calculator/src/calculator1.lalrpop [calculator2]: ./calculator/src/calculator2.lalrpop +[calculator2b]: ./calculator/src/calculator2b.lalrpop [calculator3]: ./calculator/src/calculator3.lalrpop [calculator4]: ./calculator/src/calculator4.lalrpop [calculator5]: ./calculator/src/calculator5.lalrpop [calculator6]: ./calculator/src/calculator6.lalrpop +[calculator7]: ./calculator/src/calculator7.lalrpop [astrs]: ./calculator/src/ast.rs diff --git a/lalrpop-test/src/match_section.rs b/lalrpop-test/src/match_section.rs new file mode 100644 index 0000000..01a2f9d --- /dev/null +++ b/lalrpop-test/src/match_section.rs @@ -0,0 +1,1113 @@ +extern crate lalrpop_util as __lalrpop_util; + +mod __parse__Query { + #![allow(non_snake_case, non_camel_case_types, unused_mut, unused_variables, unused_imports)] + + extern crate lalrpop_util as __lalrpop_util; + pub fn parse_Query< + 'input, + >( + input: &'input str, + ) -> Result> + { + let __ascent = __ascent::parse_Query( + input, + ); + let __parse_table = __parse_table::parse_Query( + input, + ); + assert_eq!(__ascent, __parse_table); + return __ascent; + } + mod __ascent { + + mod __parse__Query { + #![allow(non_snake_case, non_camel_case_types, unused_mut, unused_variables, unused_imports)] + + extern crate lalrpop_util as __lalrpop_util; + pub fn parse_Query< + 'input, + >( + input: &'input str, + ) -> Result> + { + let mut __tokens = super::super::super::__intern_token::__Matcher::new(input); + let __lookahead = match __tokens.next() { + Some(Ok(v)) => Some(v), + None => None, + Some(Err(e)) => return Err(e), + }; + match try!(__state0(input, &mut __tokens, __lookahead, ::std::marker::PhantomData::<()>)) { + (Some(__lookahead), _) => { + Err(__lalrpop_util::ParseError::ExtraToken { token: __lookahead }) + } + (None, __Nonterminal::____Query((_, __nt, _))) => { + Ok(__nt) + } + _ => unreachable!(), + } + } + + #[allow(dead_code)] + pub enum __Nonterminal<> { + Keyword((usize, String, usize)), + Query((usize, String, usize)), + Table((usize, String, usize)), + ____Query((usize, String, usize)), + } + + // State 0 + // AllInputs = [] + // OptionalInputs = [] + // FixedInputs = [] + // WillPushLen = 0 + // WillPush = [] + // WillProduce = None + // + // Keyword = (*) "INSERT" ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // Keyword = (*) r#"(?i)select"# ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // Keyword = (*) UPDATE ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // Query = (*) Keyword Table ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // __Query = (*) Query ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // + // "INSERT" -> S3 + // r#"(?i)select"# -> S4 + // UPDATE -> S5 + // + // Keyword -> S1 + // Query -> S2 + pub fn __state0< + 'input, + __TOKENS: Iterator>>, + >( + input: &'input str, + __tokens: &mut __TOKENS, + __lookahead: Option<(usize, (usize, &'input str), usize)>, + _: ::std::marker::PhantomData<()>, + ) -> Result<(Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>), __lalrpop_util::ParseError> + { + let mut __result: (Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>); + match __lookahead { + Some((__loc1, (1, __tok0), __loc2)) => { + let __sym0 = (__loc1, (__tok0), __loc2); + __result = try!(__state3(input, __tokens, __sym0, ::std::marker::PhantomData::<()>)); + } + Some((__loc1, (2, __tok0), __loc2)) => { + let __sym0 = (__loc1, (__tok0), __loc2); + __result = try!(__state4(input, __tokens, __sym0, ::std::marker::PhantomData::<()>)); + } + Some((__loc1, (3, __tok0), __loc2)) => { + let __sym0 = (__loc1, (__tok0), __loc2); + __result = try!(__state5(input, __tokens, __sym0, ::std::marker::PhantomData::<()>)); + } + _ => { + return Err(__lalrpop_util::ParseError::UnrecognizedToken { + token: __lookahead, + expected: vec![ + r###""INSERT""###.to_string(), + r###"r#"(?i)select"#"###.to_string(), + r###"UPDATE"###.to_string(), + ] + }); + } + } + loop { + let (__lookahead, __nt) = __result; + match __nt { + __Nonterminal::Keyword(__sym0) => { + __result = try!(__state1(input, __tokens, __lookahead, __sym0, ::std::marker::PhantomData::<()>)); + } + __Nonterminal::Query(__sym0) => { + __result = try!(__state2(input, __tokens, __lookahead, __sym0, ::std::marker::PhantomData::<()>)); + } + _ => { + return Ok((__lookahead, __nt)); + } + } + } + } + + // State 1 + // AllInputs = [Keyword] + // OptionalInputs = [] + // FixedInputs = [Keyword] + // WillPushLen = 1 + // WillPush = [Table] + // WillProduce = Some(Query) + // + // Query = Keyword (*) Table ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // Table = (*) r#"(?i)[a-z]+"# ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // + // r#"(?i)[a-z]+"# -> S7 + // + // Table -> S6 + pub fn __state1< + 'input, + __TOKENS: Iterator>>, + >( + input: &'input str, + __tokens: &mut __TOKENS, + __lookahead: Option<(usize, (usize, &'input str), usize)>, + __sym0: (usize, String, usize), + _: ::std::marker::PhantomData<()>, + ) -> Result<(Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>), __lalrpop_util::ParseError> + { + let mut __result: (Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>); + match __lookahead { + Some((__loc1, (0, __tok0), __loc2)) => { + let __sym1 = (__loc1, (__tok0), __loc2); + __result = try!(__state7(input, __tokens, __sym1, ::std::marker::PhantomData::<()>)); + } + _ => { + return Err(__lalrpop_util::ParseError::UnrecognizedToken { + token: __lookahead, + expected: vec![ + r###"r#"(?i)[a-z]+"#"###.to_string(), + ] + }); + } + } + loop { + let (__lookahead, __nt) = __result; + match __nt { + __Nonterminal::Table(__sym1) => { + __result = try!(__state6(input, __tokens, __lookahead, __sym0, __sym1, ::std::marker::PhantomData::<()>)); + return Ok(__result); + } + _ => { + return Ok((__lookahead, __nt)); + } + } + } + } + + // State 2 + // AllInputs = [Query] + // OptionalInputs = [] + // FixedInputs = [Query] + // WillPushLen = 0 + // WillPush = [] + // WillProduce = Some(__Query) + // + // __Query = Query (*) ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // + // ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] -> __Query = Query => ActionFn(0); + // + pub fn __state2< + 'input, + __TOKENS: Iterator>>, + >( + input: &'input str, + __tokens: &mut __TOKENS, + __lookahead: Option<(usize, (usize, &'input str), usize)>, + __sym0: (usize, String, usize), + _: ::std::marker::PhantomData<()>, + ) -> Result<(Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>), __lalrpop_util::ParseError> + { + let mut __result: (Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>); + match __lookahead { + Some((_, (1, _), _)) | + Some((_, (0, _), _)) | + Some((_, (2, _), _)) | + Some((_, (3, _), _)) | + None => { + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::super::super::__action0::<>(input, __sym0); + let __nt = __Nonterminal::____Query(( + __start, + __nt, + __end, + )); + __result = (__lookahead, __nt); + return Ok(__result); + } + _ => { + return Err(__lalrpop_util::ParseError::UnrecognizedToken { + token: __lookahead, + expected: vec![ + r###""INSERT""###.to_string(), + r###"r#"(?i)[a-z]+"#"###.to_string(), + r###"r#"(?i)select"#"###.to_string(), + r###"UPDATE"###.to_string(), + ] + }); + } + } + } + + // State 3 + // AllInputs = ["INSERT"] + // OptionalInputs = [] + // FixedInputs = ["INSERT"] + // WillPushLen = 0 + // WillPush = [] + // WillProduce = Some(Keyword) + // + // Keyword = "INSERT" (*) ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // + // ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] -> Keyword = "INSERT" => ActionFn(2); + // + pub fn __state3< + 'input, + __TOKENS: Iterator>>, + >( + input: &'input str, + __tokens: &mut __TOKENS, + __sym0: (usize, &'input str, usize), + _: ::std::marker::PhantomData<()>, + ) -> Result<(Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>), __lalrpop_util::ParseError> + { + let mut __result: (Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>); + let __lookahead = match __tokens.next() { + Some(Ok(v)) => Some(v), + None => None, + Some(Err(e)) => return Err(e), + }; + match __lookahead { + Some((_, (1, _), _)) | + Some((_, (0, _), _)) | + Some((_, (2, _), _)) | + Some((_, (3, _), _)) | + None => { + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::super::super::__action2::<>(input, __sym0); + let __nt = __Nonterminal::Keyword(( + __start, + __nt, + __end, + )); + __result = (__lookahead, __nt); + return Ok(__result); + } + _ => { + return Err(__lalrpop_util::ParseError::UnrecognizedToken { + token: __lookahead, + expected: vec![ + r###""INSERT""###.to_string(), + r###"r#"(?i)[a-z]+"#"###.to_string(), + r###"r#"(?i)select"#"###.to_string(), + r###"UPDATE"###.to_string(), + ] + }); + } + } + } + + // State 4 + // AllInputs = [r#"(?i)select"#] + // OptionalInputs = [] + // FixedInputs = [r#"(?i)select"#] + // WillPushLen = 0 + // WillPush = [] + // WillProduce = Some(Keyword) + // + // Keyword = r#"(?i)select"# (*) ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // + // ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] -> Keyword = r#"(?i)select"# => ActionFn(1); + // + pub fn __state4< + 'input, + __TOKENS: Iterator>>, + >( + input: &'input str, + __tokens: &mut __TOKENS, + __sym0: (usize, &'input str, usize), + _: ::std::marker::PhantomData<()>, + ) -> Result<(Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>), __lalrpop_util::ParseError> + { + let mut __result: (Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>); + let __lookahead = match __tokens.next() { + Some(Ok(v)) => Some(v), + None => None, + Some(Err(e)) => return Err(e), + }; + match __lookahead { + Some((_, (1, _), _)) | + Some((_, (0, _), _)) | + Some((_, (2, _), _)) | + Some((_, (3, _), _)) | + None => { + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::super::super::__action1::<>(input, __sym0); + let __nt = __Nonterminal::Keyword(( + __start, + __nt, + __end, + )); + __result = (__lookahead, __nt); + return Ok(__result); + } + _ => { + return Err(__lalrpop_util::ParseError::UnrecognizedToken { + token: __lookahead, + expected: vec![ + r###""INSERT""###.to_string(), + r###"r#"(?i)[a-z]+"#"###.to_string(), + r###"r#"(?i)select"#"###.to_string(), + r###"UPDATE"###.to_string(), + ] + }); + } + } + } + + // State 5 + // AllInputs = [UPDATE] + // OptionalInputs = [] + // FixedInputs = [UPDATE] + // WillPushLen = 0 + // WillPush = [] + // WillProduce = Some(Keyword) + // + // Keyword = UPDATE (*) ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // + // ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] -> Keyword = UPDATE => ActionFn(3); + // + pub fn __state5< + 'input, + __TOKENS: Iterator>>, + >( + input: &'input str, + __tokens: &mut __TOKENS, + __sym0: (usize, &'input str, usize), + _: ::std::marker::PhantomData<()>, + ) -> Result<(Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>), __lalrpop_util::ParseError> + { + let mut __result: (Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>); + let __lookahead = match __tokens.next() { + Some(Ok(v)) => Some(v), + None => None, + Some(Err(e)) => return Err(e), + }; + match __lookahead { + Some((_, (1, _), _)) | + Some((_, (0, _), _)) | + Some((_, (2, _), _)) | + Some((_, (3, _), _)) | + None => { + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::super::super::__action3::<>(input, __sym0); + let __nt = __Nonterminal::Keyword(( + __start, + __nt, + __end, + )); + __result = (__lookahead, __nt); + return Ok(__result); + } + _ => { + return Err(__lalrpop_util::ParseError::UnrecognizedToken { + token: __lookahead, + expected: vec![ + r###""INSERT""###.to_string(), + r###"r#"(?i)[a-z]+"#"###.to_string(), + r###"r#"(?i)select"#"###.to_string(), + r###"UPDATE"###.to_string(), + ] + }); + } + } + } + + // State 6 + // AllInputs = [Keyword, Table] + // OptionalInputs = [] + // FixedInputs = [Keyword, Table] + // WillPushLen = 0 + // WillPush = [] + // WillProduce = Some(Query) + // + // Query = Keyword Table (*) ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // + // ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] -> Query = Keyword, Table => ActionFn(5); + // + pub fn __state6< + 'input, + __TOKENS: Iterator>>, + >( + input: &'input str, + __tokens: &mut __TOKENS, + __lookahead: Option<(usize, (usize, &'input str), usize)>, + __sym0: (usize, String, usize), + __sym1: (usize, String, usize), + _: ::std::marker::PhantomData<()>, + ) -> Result<(Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>), __lalrpop_util::ParseError> + { + let mut __result: (Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>); + match __lookahead { + Some((_, (1, _), _)) | + Some((_, (0, _), _)) | + Some((_, (2, _), _)) | + Some((_, (3, _), _)) | + None => { + let __start = __sym0.0.clone(); + let __end = __sym1.2.clone(); + let __nt = super::super::super::__action5::<>(input, __sym0, __sym1); + let __nt = __Nonterminal::Query(( + __start, + __nt, + __end, + )); + __result = (__lookahead, __nt); + return Ok(__result); + } + _ => { + return Err(__lalrpop_util::ParseError::UnrecognizedToken { + token: __lookahead, + expected: vec![ + r###""INSERT""###.to_string(), + r###"r#"(?i)[a-z]+"#"###.to_string(), + r###"r#"(?i)select"#"###.to_string(), + r###"UPDATE"###.to_string(), + ] + }); + } + } + } + + // State 7 + // AllInputs = [r#"(?i)[a-z]+"#] + // OptionalInputs = [] + // FixedInputs = [r#"(?i)[a-z]+"#] + // WillPushLen = 0 + // WillPush = [] + // WillProduce = Some(Table) + // + // Table = r#"(?i)[a-z]+"# (*) ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // + // ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] -> Table = r#"(?i)[a-z]+"# => ActionFn(4); + // + pub fn __state7< + 'input, + __TOKENS: Iterator>>, + >( + input: &'input str, + __tokens: &mut __TOKENS, + __sym0: (usize, &'input str, usize), + _: ::std::marker::PhantomData<()>, + ) -> Result<(Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>), __lalrpop_util::ParseError> + { + let mut __result: (Option<(usize, (usize, &'input str), usize)>, __Nonterminal<>); + let __lookahead = match __tokens.next() { + Some(Ok(v)) => Some(v), + None => None, + Some(Err(e)) => return Err(e), + }; + match __lookahead { + Some((_, (1, _), _)) | + Some((_, (0, _), _)) | + Some((_, (2, _), _)) | + Some((_, (3, _), _)) | + None => { + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::super::super::__action4::<>(input, __sym0); + let __nt = __Nonterminal::Table(( + __start, + __nt, + __end, + )); + __result = (__lookahead, __nt); + return Ok(__result); + } + _ => { + return Err(__lalrpop_util::ParseError::UnrecognizedToken { + token: __lookahead, + expected: vec![ + r###""INSERT""###.to_string(), + r###"r#"(?i)[a-z]+"#"###.to_string(), + r###"r#"(?i)select"#"###.to_string(), + r###"UPDATE"###.to_string(), + ] + }); + } + } + } + } + pub use self::__parse__Query::parse_Query; + } + mod __parse_table { + + mod __parse__Query { + #![allow(non_snake_case, non_camel_case_types, unused_mut, unused_variables, unused_imports)] + + extern crate lalrpop_util as __lalrpop_util; + #[allow(dead_code)] + pub enum __Symbol<'input> { + Term_22INSERT_22(&'input str), + Termr_23_22_28_3fi_29_5ba_2dz_5d_2b_22_23(&'input str), + Termr_23_22_28_3fi_29select_22_23(&'input str), + TermUPDATE(&'input str), + NtKeyword(String), + NtQuery(String), + NtTable(String), + Nt____Query(String), + } + const __ACTION: &'static [i32] = &[ + // State 0 + // Keyword = (*) "INSERT" ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // Keyword = (*) r#"(?i)select"# ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // Keyword = (*) UPDATE ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // Query = (*) Keyword Table ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // __Query = (*) Query ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + 4, // on "INSERT", goto 3 + 0, // on r#"(?i)[a-z]+"#, error + 5, // on r#"(?i)select"#, goto 4 + 6, // on UPDATE, goto 5 + + // State 1 + // Query = Keyword (*) Table ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + // Table = (*) r#"(?i)[a-z]+"# ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + 0, // on "INSERT", error + 8, // on r#"(?i)[a-z]+"#, goto 7 + 0, // on r#"(?i)select"#, error + 0, // on UPDATE, error + + // State 2 + // __Query = Query (*) ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + -6, // on "INSERT", reduce `__Query = Query => ActionFn(0);` + -6, // on r#"(?i)[a-z]+"#, reduce `__Query = Query => ActionFn(0);` + -6, // on r#"(?i)select"#, reduce `__Query = Query => ActionFn(0);` + -6, // on UPDATE, reduce `__Query = Query => ActionFn(0);` + + // State 3 + // Keyword = "INSERT" (*) ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + -2, // on "INSERT", reduce `Keyword = "INSERT" => ActionFn(2);` + -2, // on r#"(?i)[a-z]+"#, reduce `Keyword = "INSERT" => ActionFn(2);` + -2, // on r#"(?i)select"#, reduce `Keyword = "INSERT" => ActionFn(2);` + -2, // on UPDATE, reduce `Keyword = "INSERT" => ActionFn(2);` + + // State 4 + // Keyword = r#"(?i)select"# (*) ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + -1, // on "INSERT", reduce `Keyword = r#"(?i)select"# => ActionFn(1);` + -1, // on r#"(?i)[a-z]+"#, reduce `Keyword = r#"(?i)select"# => ActionFn(1);` + -1, // on r#"(?i)select"#, reduce `Keyword = r#"(?i)select"# => ActionFn(1);` + -1, // on UPDATE, reduce `Keyword = r#"(?i)select"# => ActionFn(1);` + + // State 5 + // Keyword = UPDATE (*) ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + -3, // on "INSERT", reduce `Keyword = UPDATE => ActionFn(3);` + -3, // on r#"(?i)[a-z]+"#, reduce `Keyword = UPDATE => ActionFn(3);` + -3, // on r#"(?i)select"#, reduce `Keyword = UPDATE => ActionFn(3);` + -3, // on UPDATE, reduce `Keyword = UPDATE => ActionFn(3);` + + // State 6 + // Query = Keyword Table (*) ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + -4, // on "INSERT", reduce `Query = Keyword, Table => ActionFn(5);` + -4, // on r#"(?i)[a-z]+"#, reduce `Query = Keyword, Table => ActionFn(5);` + -4, // on r#"(?i)select"#, reduce `Query = Keyword, Table => ActionFn(5);` + -4, // on UPDATE, reduce `Query = Keyword, Table => ActionFn(5);` + + // State 7 + // Table = r#"(?i)[a-z]+"# (*) ["INSERT", r#"(?i)[a-z]+"#, r#"(?i)select"#, UPDATE, EOF] + -5, // on "INSERT", reduce `Table = r#"(?i)[a-z]+"# => ActionFn(4);` + -5, // on r#"(?i)[a-z]+"#, reduce `Table = r#"(?i)[a-z]+"# => ActionFn(4);` + -5, // on r#"(?i)select"#, reduce `Table = r#"(?i)[a-z]+"# => ActionFn(4);` + -5, // on UPDATE, reduce `Table = r#"(?i)[a-z]+"# => ActionFn(4);` + + ]; + const __EOF_ACTION: &'static [i32] = &[ + 0, // on EOF, error + + 0, // on EOF, error + + -6, // on EOF, reduce `__Query = Query => ActionFn(0);` + + -2, // on EOF, reduce `Keyword = "INSERT" => ActionFn(2);` + + -1, // on EOF, reduce `Keyword = r#"(?i)select"# => ActionFn(1);` + + -3, // on EOF, reduce `Keyword = UPDATE => ActionFn(3);` + + -4, // on EOF, reduce `Query = Keyword, Table => ActionFn(5);` + + -5, // on EOF, reduce `Table = r#"(?i)[a-z]+"# => ActionFn(4);` + + ]; + const __GOTO: &'static [i32] = &[ + // State 0 + 2, // on Keyword, goto 1 + 3, // on Query, goto 2 + 0, // on Table, error + 0, // on __Query, error + + // State 1 + 0, // on Keyword, error + 0, // on Query, error + 7, // on Table, goto 6 + 0, // on __Query, error + + // State 2 + 0, // on Keyword, error + 0, // on Query, error + 0, // on Table, error + 0, // on __Query, error + + // State 3 + 0, // on Keyword, error + 0, // on Query, error + 0, // on Table, error + 0, // on __Query, error + + // State 4 + 0, // on Keyword, error + 0, // on Query, error + 0, // on Table, error + 0, // on __Query, error + + // State 5 + 0, // on Keyword, error + 0, // on Query, error + 0, // on Table, error + 0, // on __Query, error + + // State 6 + 0, // on Keyword, error + 0, // on Query, error + 0, // on Table, error + 0, // on __Query, error + + // State 7 + 0, // on Keyword, error + 0, // on Query, error + 0, // on Table, error + 0, // on __Query, error + + ]; + fn __expected_tokens(__state: usize) -> Vec<::std::string::String> { + const __TERMINAL: &'static [&'static str] = &[ + r###""INSERT""###, + r###"r#"(?i)[a-z]+"#"###, + r###"r#"(?i)select"#"###, + r###"UPDATE"###, + ]; + __ACTION[(__state * 4)..].iter().zip(__TERMINAL).filter_map(|(&state, terminal)| { + if state == 0 { + None + } else { + Some(terminal.to_string()) + } + }).collect() + } + pub fn parse_Query< + 'input, + >( + input: &'input str, + ) -> Result> + { + let mut __tokens = super::super::super::__intern_token::__Matcher::new(input); + let mut __states = vec![0_i32]; + let mut __symbols = vec![]; + let mut __integer; + let mut __lookahead; + let mut __last_location = Default::default(); + '__shift: loop { + __lookahead = match __tokens.next() { + Some(Ok(v)) => v, + None => break '__shift, + Some(Err(e)) => return Err(e), + }; + __last_location = __lookahead.2.clone(); + __integer = match __lookahead.1 { + (1, _) if true => 0, + (0, _) if true => 1, + (2, _) if true => 2, + (3, _) if true => 3, + _ => { + let __state = *__states.last().unwrap() as usize; + let __error = __lalrpop_util::ParseError::UnrecognizedToken { + token: Some(__lookahead), + expected: __expected_tokens(__state), + }; + return Err(__error); + } + }; + '__inner: loop { + let __state = *__states.last().unwrap() as usize; + let __action = __ACTION[__state * 4 + __integer]; + if __action > 0 { + let __symbol = match __integer { + 0 => match __lookahead.1 { + (1, __tok0) => __Symbol::Term_22INSERT_22((__tok0)), + _ => unreachable!(), + }, + 1 => match __lookahead.1 { + (0, __tok0) => __Symbol::Termr_23_22_28_3fi_29_5ba_2dz_5d_2b_22_23((__tok0)), + _ => unreachable!(), + }, + 2 => match __lookahead.1 { + (2, __tok0) => __Symbol::Termr_23_22_28_3fi_29select_22_23((__tok0)), + _ => unreachable!(), + }, + 3 => match __lookahead.1 { + (3, __tok0) => __Symbol::TermUPDATE((__tok0)), + _ => unreachable!(), + }, + _ => unreachable!(), + }; + __states.push(__action - 1); + __symbols.push((__lookahead.0, __symbol, __lookahead.2)); + continue '__shift; + } else if __action < 0 { + if let Some(r) = __reduce(input, __action, Some(&__lookahead.0), &mut __states, &mut __symbols, ::std::marker::PhantomData::<()>) { + return r; + } + } else { + let __state = *__states.last().unwrap() as usize; + let __error = __lalrpop_util::ParseError::UnrecognizedToken { + token: Some(__lookahead), + expected: __expected_tokens(__state), + }; + return Err(__error) + } + } + } + loop { + let __state = *__states.last().unwrap() as usize; + let __action = __EOF_ACTION[__state]; + if __action < 0 { + if let Some(r) = __reduce(input, __action, None, &mut __states, &mut __symbols, ::std::marker::PhantomData::<()>) { + return r; + } + } else { + let __state = *__states.last().unwrap() as usize; + let __error = __lalrpop_util::ParseError::UnrecognizedToken { + token: None, + expected: __expected_tokens(__state), + }; + return Err(__error); + } + } + } + pub fn __reduce< + 'input, + >( + input: &'input str, + __action: i32, + __lookahead_start: Option<&usize>, + __states: &mut ::std::vec::Vec, + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)>, + _: ::std::marker::PhantomData<()>, + ) -> Option>> + { + let __nonterminal = match -__action { + 1 => { + // Keyword = r#"(?i)select"# => ActionFn(1); + let __sym0 = __pop_Termr_23_22_28_3fi_29select_22_23(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::super::super::__action1::<>(input, __sym0); + let __states_len = __states.len(); + __states.truncate(__states_len - 1); + __symbols.push((__start, __Symbol::NtKeyword(__nt), __end)); + 0 + } + 2 => { + // Keyword = "INSERT" => ActionFn(2); + let __sym0 = __pop_Term_22INSERT_22(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::super::super::__action2::<>(input, __sym0); + let __states_len = __states.len(); + __states.truncate(__states_len - 1); + __symbols.push((__start, __Symbol::NtKeyword(__nt), __end)); + 0 + } + 3 => { + // Keyword = UPDATE => ActionFn(3); + let __sym0 = __pop_TermUPDATE(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::super::super::__action3::<>(input, __sym0); + let __states_len = __states.len(); + __states.truncate(__states_len - 1); + __symbols.push((__start, __Symbol::NtKeyword(__nt), __end)); + 0 + } + 4 => { + // Query = Keyword, Table => ActionFn(5); + let __sym1 = __pop_NtTable(__symbols); + let __sym0 = __pop_NtKeyword(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym1.2.clone(); + let __nt = super::super::super::__action5::<>(input, __sym0, __sym1); + let __states_len = __states.len(); + __states.truncate(__states_len - 2); + __symbols.push((__start, __Symbol::NtQuery(__nt), __end)); + 1 + } + 5 => { + // Table = r#"(?i)[a-z]+"# => ActionFn(4); + let __sym0 = __pop_Termr_23_22_28_3fi_29_5ba_2dz_5d_2b_22_23(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::super::super::__action4::<>(input, __sym0); + let __states_len = __states.len(); + __states.truncate(__states_len - 1); + __symbols.push((__start, __Symbol::NtTable(__nt), __end)); + 2 + } + 6 => { + // __Query = Query => ActionFn(0); + let __sym0 = __pop_NtQuery(__symbols); + let __start = __sym0.0.clone(); + let __end = __sym0.2.clone(); + let __nt = super::super::super::__action0::<>(input, __sym0); + return Some(Ok(__nt)); + } + _ => panic!("invalid action code {}", __action) + }; + let __state = *__states.last().unwrap() as usize; + let __next_state = __GOTO[__state * 4 + __nonterminal] - 1; + __states.push(__next_state); + None + } + fn __pop_Term_22INSERT_22< + 'input, + >( + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, &'input str, usize) { + match __symbols.pop().unwrap() { + (__l, __Symbol::Term_22INSERT_22(__v), __r) => (__l, __v, __r), + _ => panic!("symbol type mismatch") + } + } + fn __pop_Termr_23_22_28_3fi_29_5ba_2dz_5d_2b_22_23< + 'input, + >( + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, &'input str, usize) { + match __symbols.pop().unwrap() { + (__l, __Symbol::Termr_23_22_28_3fi_29_5ba_2dz_5d_2b_22_23(__v), __r) => (__l, __v, __r), + _ => panic!("symbol type mismatch") + } + } + fn __pop_Termr_23_22_28_3fi_29select_22_23< + 'input, + >( + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, &'input str, usize) { + match __symbols.pop().unwrap() { + (__l, __Symbol::Termr_23_22_28_3fi_29select_22_23(__v), __r) => (__l, __v, __r), + _ => panic!("symbol type mismatch") + } + } + fn __pop_TermUPDATE< + 'input, + >( + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, &'input str, usize) { + match __symbols.pop().unwrap() { + (__l, __Symbol::TermUPDATE(__v), __r) => (__l, __v, __r), + _ => panic!("symbol type mismatch") + } + } + fn __pop_NtKeyword< + 'input, + >( + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, String, usize) { + match __symbols.pop().unwrap() { + (__l, __Symbol::NtKeyword(__v), __r) => (__l, __v, __r), + _ => panic!("symbol type mismatch") + } + } + fn __pop_NtQuery< + 'input, + >( + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, String, usize) { + match __symbols.pop().unwrap() { + (__l, __Symbol::NtQuery(__v), __r) => (__l, __v, __r), + _ => panic!("symbol type mismatch") + } + } + fn __pop_NtTable< + 'input, + >( + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, String, usize) { + match __symbols.pop().unwrap() { + (__l, __Symbol::NtTable(__v), __r) => (__l, __v, __r), + _ => panic!("symbol type mismatch") + } + } + fn __pop_Nt____Query< + 'input, + >( + __symbols: &mut ::std::vec::Vec<(usize,__Symbol<'input>,usize)> + ) -> (usize, String, usize) { + match __symbols.pop().unwrap() { + (__l, __Symbol::Nt____Query(__v), __r) => (__l, __v, __r), + _ => panic!("symbol type mismatch") + } + } + } + pub use self::__parse__Query::parse_Query; + } +} +pub use self::__parse__Query::parse_Query; +mod __intern_token { + extern crate lalrpop_util as __lalrpop_util; + extern crate regex as __regex; + pub struct __Matcher<'input> { + text: &'input str, + consumed: usize, + regex_set: __regex::RegexSet, + regex_vec: Vec<__regex::Regex>, + } + + impl<'input> __Matcher<'input> { + pub fn new(s: &'input str) -> __Matcher<'input> { + let __strs: &[&str] = &[ + "^(?u:[A-Za-zſ-ſK-K])+", + "^(?iu:insert)", + "^(?iu:select)", + "^(?iu:update)", + ]; + let __regex_set = __regex::RegexSet::new(__strs).unwrap(); + let __regex_vec = vec![ + __regex::Regex::new("^(?u:[A-Za-zſ-ſK-K])+").unwrap(), + __regex::Regex::new("^(?iu:insert)").unwrap(), + __regex::Regex::new("^(?iu:select)").unwrap(), + __regex::Regex::new("^(?iu:update)").unwrap(), + ]; + __Matcher { + text: s, + consumed: 0, + regex_set: __regex_set, + regex_vec: __regex_vec, + } + } + } + + impl<'input> Iterator for __Matcher<'input> { + type Item = Result<(usize, (usize, &'input str), usize), __lalrpop_util::ParseError>; + + fn next(&mut self) -> Option { + let __text = self.text.trim_left(); + let __whitespace = self.text.len() - __text.len(); + let __start_offset = self.consumed + __whitespace; + if __text.is_empty() { + self.text = __text; + self.consumed = __start_offset; + None + } else { + let __matches = self.regex_set.matches(__text); + if !__matches.matched_any() { + Some(Err(__lalrpop_util::ParseError::InvalidToken { + location: __start_offset, + })) + } else { + let mut __longest_match = 0; + let mut __index = 0; + for __i in 0 .. 4 { + if __matches.matched(__i) { + let __match = self.regex_vec[__i].find(__text).unwrap(); + let __len = __match.end(); + if __len >= __longest_match { + __longest_match = __len; + __index = __i; + } + } + } + let __result = &__text[..__longest_match]; + let __remaining = &__text[__longest_match..]; + let __end_offset = __start_offset + __longest_match; + self.text = __remaining; + self.consumed = __end_offset; + Some(Ok((__start_offset, (__index, __result), __end_offset))) + } + } + } + } +} + +#[allow(unused_variables)] +pub fn __action0< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, String, usize), +) -> String +{ + (__0) +} + +#[allow(unused_variables)] +pub fn __action1< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, &'input str, usize), +) -> String +{ + String::from("SELECT") +} + +#[allow(unused_variables)] +pub fn __action2< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, &'input str, usize), +) -> String +{ + String::from("INSERT") +} + +#[allow(unused_variables)] +pub fn __action3< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, &'input str, usize), +) -> String +{ + String::from("UPDATE") +} + +#[allow(unused_variables)] +pub fn __action4< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, &'input str, usize), +) -> String +{ + String::from(__0) +} + +#[allow(unused_variables)] +pub fn __action5< + 'input, +>( + input: &'input str, + (_, __0, _): (usize, String, usize), + (_, __1, _): (usize, String, usize), +) -> String +{ + format!("{} {}", __0, __1) +} + +pub trait __ToTriple<'input, > { + type Error; + fn to_triple(value: Self) -> Result<(usize,(usize, &'input str),usize),Self::Error>; +} + +impl<'input, > __ToTriple<'input, > for (usize, (usize, &'input str), usize) { + type Error = (); + fn to_triple(value: Self) -> Result<(usize,(usize, &'input str),usize),()> { + Ok(value) + } +} +impl<'input, > __ToTriple<'input, > for Result<(usize, (usize, &'input str), usize),()> { + type Error = (); + fn to_triple(value: Self) -> Result<(usize,(usize, &'input str),usize),()> { + value + } +}