#kma #ukma #contact-book

bin+lib toml_contact_book_parser

Parser for a contact book

5 releases

0.1.4 Nov 14, 2024
0.1.3 Nov 14, 2024
0.1.2 Nov 13, 2024
0.1.1 Nov 11, 2024
0.1.0 Nov 11, 2024

#652 in Parser implementations

Download history 357/week @ 2024-11-10 45/week @ 2024-11-17

402 downloads per month

MIT license

15KB
190 lines

toml_contact_book_parser

Toml Contact Book Parser

This is a simple parser for contact book, stored in toml format. It can parse a file with contacts and return a list of contacts. Made for Rust course.

Table of contents

Example of contact book

[contact]
name = "John"
surname = "Doe"
phones = ["+380501234567", "+380501234568"]
address = "Some address"
birthday = "2000-01-01"

Usage example

use toml_contact_book_parser::parse_contacts;

fn main() {
    let raw_contact_str = "[contact]\nname = \"John\"\nsurname = \"Doe\"\nphones = [\"+380501..."; // fill with your contact book or load from file
    
    let contacts = parse_contacts(raw_contact_str).unwrap();

    println!("{:?}", contacts);
    // [Contact { name: "John", surname: "Doe", phones: ["+380501234567", "+380501234568"], address: "Some address", birthday: "2000-01-01" }, ...]
}

Grammar

Toml grammar

// Helper rules
equals = _{ " "* ~ "=" ~ " "* }

// Phone helper rules
country_code = _{ ASCII_DIGIT{1,3} }
area_code = _{ ASCII_DIGIT{3} }
exchange_code = _{ ASCII_DIGIT{3} }
subscriber_number = _{ ASCII_DIGIT{4} }
subscriber_number_dashed = _{ ASCII_DIGIT{2} ~ "-" ~ ASCII_DIGIT{2} }
subscriber_number_combo = _{ subscriber_number | subscriber_number_dashed }

// Main rules
name = { "\"" ~ (ASCII_ALPHA)+ ~ "\"" }
surname = { "\"" ~ (ASCII_ALPHA)+ ~ "\"" }
address = { "\"" ~ (ASCII_ALPHANUMERIC | " " | "." | "," | "-")+ ~ "\"" }
phone = { "\"" ~ ("+")? ~ (
    // Without brackets
    (ASCII_DIGIT{11,13}) |
    (country_code ~ " "{0,1} ~ area_code ~ " "{0,1} ~ exchange_code ~ " "{0,1} ~ subscriber_number) |
    (country_code ~ "-" ~ area_code ~ "-" ~ exchange_code ~ "-" ~ subscriber_number) |
    // With brackets
    (country_code ~ " "{0,1} ~ "(" ~ area_code ~ ")" ~ " "{0,1} ~ exchange_code ~ " "{0,1} ~ subscriber_number) |
    (country_code ~ "(" ~ area_code ~ ")" ~ "-"{0,1} ~ exchange_code ~ "-" ~ subscriber_number_combo)
) ~ "\"" }
date = { "\"" ~ ASCII_DIGIT{4} ~ "-" ~ ASCII_DIGIT{2} ~ "-" ~ ASCII_DIGIT{2} ~ "\"" }
phones = { "[" ~ phone ~ ("," ~ " "{0, 1} ~ phone)* ~ "]" }

contact = {
    "[contact]" ~ " "* ~ NEWLINE ~
    "name" ~ equals ~ name ~ NEWLINE ~
    "surname" ~ equals ~ surname ~ NEWLINE ~
    "phones" ~ equals ~ phones ~ NEWLINE ~
    "address" ~ equals ~ address ~ NEWLINE ~
    "birthday" ~ equals ~ date ~ NEWLINE
}
file = { SOI ~ (contact ~ NEWLINE{0,})* ~ EOI }

Name and surname rules

These rules match any string that contains only ASCII letters and is enclosed in double quotes, e.g. "John", "Doe", "Carl", etc.

name = { "\"" ~ (ASCII_ALPHA)+ ~ "\"" }
surname = { "\"" ~ (ASCII_ALPHA)+ ~ "\"" }

Address rule

This rule matches any string that contains only ASCII alphanumeric characters, spaces, dots, commas, and dashes, e.g. "Some address", "Some address, 123", "Some address, 123, apt. 45", etc.

address = { "\"" ~ (ASCII_ALPHANUMERIC | " " | "." | "," | "-")+ ~ "\"" }

Phone rule

This rule matches any phone number in the following formats:

  • +380501234567
  • +380 50 123 45 67
  • +380-50-123-45-67
  • +380 (50) 123 45 67
  • +380(50)-123-45-67
phone = { "\"" ~ ("+")? ~ (
    (ASCII_DIGIT{11,13}) |
    (country_code ~ " "{0,1} ~ area_code ~ " "{0,1} ~ exchange_code ~ " "{0,1} ~ subscriber_number) |
    (country_code ~ "-" ~ area_code ~ "-" ~ exchange_code ~ "-" ~ subscriber_number) |
    (country_code ~ " "{0,1} ~ "(" ~ area_code ~ ")" ~ " "{0,1} ~ exchange_code ~ " "{0,1} ~ subscriber_number) |
    (country_code ~ "(" ~ area_code ~ ")" ~ "-"{0,1} ~ exchange_code ~ "-" ~ subscriber_number_combo)
) ~ "\"" }

Date rule

This rule matches any date in the format YYYY-MM-DD, e.g. "2000-01-01", "2021-12-31", etc.

date = { "\"" ~ ASCII_DIGIT{4} ~ "-" ~ ASCII_DIGIT{2} ~ "-" ~ ASCII_DIGIT{2} ~ "\"" }

Phones rule

This rule matches a list of phone numbers, e.g. ["+380501234567", "+380501234568"].

phones = { "[" ~ phone ~ ("," ~ " "{0, 1} ~ phone)* ~ "]" }

Contact rule

This rule matches a single contact in the following format:

[contact]
name = "John"
surname = "Doe"
phones = ["+380501234567", "+380501234568"]
address = "Some address"
birthday = "2000-01-01"
contact = {
    "[contact]" ~ " "* ~ NEWLINE ~
    "name" ~ equals ~ name ~ NEWLINE ~
    "surname" ~ equals ~ surname ~ NEWLINE ~
    "phones" ~ equals ~ phones ~ NEWLINE ~
    "address" ~ equals ~ address ~ NEWLINE ~
    "birthday" ~ equals ~ date ~ NEWLINE
}

File rule

This rule matches a file that contains one or more contacts.

file = { SOI ~ (contact ~ NEWLINE{0,})* ~ EOI }

Dependencies

~4MB
~74K SLoC