use std::sync::Arc;
use swiftlet::preclude::*;
const GRAMMAR: &str = r#"
start: message
message: request
| response
request: request_line header_section CRLF message_body?
response: status_line header_section CRLF message_body?
request_line: method SP request_target SP http_version CRLF
status_line: http_version SP status_code SP reason_phrase CRLF
header_section: (header_line CRLF)*
header_line: field_name ":" field_value?
method: METHOD
request_target: REQUEST_TARGET
http_version: HTTP_VERSION
status_code: STATUS_CODE
reason_phrase: REASON_PHRASE
field_name: TOKEN
field_value: FIELD_VALUE
message_body: BODY
CRLF: /\r\n/
SP: " "
METHOD: /(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS|TRACE|CONNECT)/
HTTP_VERSION: /HTTP\/\d\.\d/
STATUS_CODE: /\d{3}/
REQUEST_TARGET: /[^ \t\r\n]+/
REASON_PHRASE: /[^\r\n]+/
TOKEN: /[!#$%&'*+.^_`|~0-9A-Za-z-]+/
FIELD_VALUE: /[ \t]*[^\r\n]+/
BODY: /.+/s
"#;
fn main() {
let parser_opt = Arc::new(ParserConfig {
algorithm: Algorithm::Earley,
debug: false,
..Default::default()
});
match Swiftlet::from_str(GRAMMAR).map(|grammar| grammar.parser(parser_opt)) {
Ok(parser) => {
let texts = [
"GET /users?id=42&active=true HTTP/1.1\r\nHost: example.com\r\nAccept: application/json\r\n\r\n",
"POST /api/messages HTTP/1.1\r\nHost: example.com\r\nContent-Type: application/json\r\nContent-Length: 17\r\n\r\n{\"message\":\"hi\"}",
"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\nhello",
];
let prefix_text = "HTTP message: ";
texts.into_iter().for_each(|text| {
println!("{}", "-".repeat(text.len() + prefix_text.len()));
println!("{}{}", prefix_text, text);
println!("{}", "-".repeat(text.len() + prefix_text.len()));
let parsed = parser.parse(text);
println!("AST =>");
match parsed {
Ok(ast) => {
ast.pretty_print();
println!();
}
Err(err) => {
eprintln!("{err}");
}
}
});
}
Err(err) => {
eprintln!("{}", err);
}
}
}