# Building Parsers from Scratch
The `trivet` module provides very, _very_, **very** simple parser primitives for building recursive descent parsers.
> We'll explain how to use the parser by showing how to parse numbers and identifiers, but you should know that **Trivet** actually provides simple methods for parsing both. See the [Cookbook](cookbook.md) chapter for details.
The root module provides three important structs.
- `Loc` represents a location in the parse (source, line, and column)
- `Parser` provides parsing services around some stream
- `ParserCore` provides a subset of the facilities of `Parser`
You will seldom (if ever) need to interact with `ParserCore`. It exists to break a dependency cycle in the library's use graph.
Parsers are build around two primitive actions.
- You can _peek_ at upcoming characters in the stream
- You can _consume_ characters from the stream
A simple application of this is recognizing an integer. Here is some very simple pseudocode.
```text
while the next thing in the stream is a digit {
collect the digit into the number
consume the digit from the stream
}
```
Composites of these primitives are available to simplify things. For example, the implementation of the above pseudocode might look like the code below. Peeking at the next character is a low-cost operation.
```rust,ignore
{{#include ../../examples/book_building_parse_integer_1.rs}}
```
That's still a lot of code. `Parser` provides a `take_while` method that handles all of this for us. Here's a slightly simpler program that parses an integer from standard input.
```rust,ignore
{{#include ../../examples/book_building_parse_integer_2.rs}}
```
Here the `take_while` peeks at and consumes the next character while it is a digit.
If nothing is entered we get `ERROR: 1:1: cannot parse integer from empty string`. If we enter a huge number like `99999999999999999999` (that's 20 nines) we get `ERROR: 1:21: number too large to fit in target type`. If we enter something like `65fred` then we get `65`, with the parser left pointing at the `f`.
Of course, this probably isn't what we want. Suppose we have a stream of identifiers and numbers and we want to parse these. We already know how to parse unsigned integers. Let's see how to parse identifiers.
```rust,ignore
# // Include the parse_identifier implementation.
{{#include ../../examples/book_building_sequence.rs:9:13}}
```
Since this method doesn't generate any errors, we don't have to report any errors and just return the string.
Okay, now let's create a type for our tokens.
```rust,ignore
# // Include the type for Thing.
{{#include ../../examples/book_building_sequence.rs:15:19}}
```
One thing to note is the inclusion of a `Loc` instance in both variants. This provides a way for us to store the _location_ in the stream where the token was found, and if we encounter an error later and want to report it, we can use the `Loc` instance to provide information to the user. This obviously isn't mandatory, but it is a good idea.
We can parse a sequence of tokens and create a vector of `Thing` instances. The following code does that, and also adds some error handling. This method always consumes trailing whitespace (which is a good idea) so we add a `_ws` suffix to the name as a visual indicator to users. Note the use of `parser.loc()` to get the location in the parse for each token. Again, not essential, but helpful if you need to generate messages for the end user of your parser.
```rust,ignore
# // Now include parse_sequence_ws.
{{#include ../../examples/book_building_sequence.rs:21:43}}
```
The following main function pulls this all together.
```rust,ignore
# // Include main.
{{#include ../../examples/book_building_sequence.rs:45:64}}
```
Running this reports the location in the stream (in this case, standard input) of each token parsed, along with the value of that token.
That's pretty much it. If it seems like there's a lot of stuff to build in, that's because there _is_. The `trivet::Parser` is not a parser _generator_, it's a parser _facilitator_.