Skip to content

Commit 6c34f9c

Browse files
committed
Review syntax and add http header test for benchmarks
1 parent f93e023 commit 6c34f9c

File tree

7 files changed

+104
-32
lines changed

7 files changed

+104
-32
lines changed

lang/v0/macro/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ proc-macro2 = "1.0.93"
1616
[dev-dependencies]
1717
bencher = "0.1.5"
1818

19+
[[bench]]
20+
name = "http"
21+
harness = false
22+
1923
[[bench]]
2024
name = "json"
2125
harness = false
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
GET /wp-content/uploads/2010/03/hello-kitty-darth-vader-pink.jpg HTTP/1.1
2+
Host: www.kittyhell.com
3+
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; ja-JP-mac; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3 Pathtraq/0.9
4+
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
5+
Accept-Language: ja,en-us;q=0.7,en;q=0.3
6+
Accept-Encoding: gzip,deflate
7+
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
8+
Keep-Alive: 115
9+
Connection: keep-alive
10+
Cookie: wp_ozh_wsa_visits=2; wp_ozh_wsa_visit_lasttime=xxxxxxxxxx;__utma=xxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.xxxxxxxxxx.x;__utmz=xxxxxxxxx.xxxxxxxxxx.x.x.utmccn=(referral)|utmcsr=reader.livedoor.com|utmcct=/reader/|utmcmd=referral
11+

lang/v0/macro/benches/http.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2019-2025 Didier Plaindoux
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
use bencher::{Bencher, benchmark_group, benchmark_main, black_box};
17+
use celma_v0_core::parser::and::AndOperation;
18+
use celma_v0_core::parser::char::{alpha, digit};
19+
use celma_v0_core::parser::core::eos;
20+
use celma_v0_core::parser::response::Response::{Reject, Success};
21+
use celma_v0_core::parser::specs::Parse;
22+
use celma_v0_core::stream::char_stream::CharStream;
23+
use celma_v0_core::stream::position::Position;
24+
use celma_v0_core::stream::specs::Stream;
25+
use celma_v0_macro::parsec_rules;
26+
27+
parsec_rules!(
28+
let http_header = request (header)* EOL -> {}
29+
let request = VERB S URI S VERSION EOL -> {}
30+
let header = NAME ':' S VALUE EOL -> {}
31+
);
32+
33+
parsec_rules!(
34+
let VERB = ("GET" | "POST" | "PUT" | "DELETE" | "HEAD" | "CONNECT" | "PATCH") -> {}
35+
let URI = ^(' ')+ -> {}
36+
let VERSION = "HTTP/" digit+ ('.' digit+)? -> {}
37+
let S = (' ' | '\t')+ -> {}
38+
let EOL = ('\r'? '\n') -> {}
39+
let NAME = (alpha | '-')+ -> {}
40+
let VALUE = ^EOL+ -> {} // Not precise enough
41+
);
42+
43+
// -------------------------------------------------------------------------------------------------
44+
// HTTP benchmarks
45+
// -------------------------------------------------------------------------------------------------
46+
47+
fn http_data(b: &mut Bencher) {
48+
let data = include_str!("data/request.http");
49+
b.bytes = data.len() as u64;
50+
parse(b, data)
51+
}
52+
53+
fn parse(b: &mut Bencher, buffer: &str) {
54+
let stream = CharStream::new_with_position(buffer, <usize>::new());
55+
56+
b.iter(|| {
57+
let response = http_header()
58+
.and_left(eos())
59+
.parse(black_box(stream.clone()));
60+
61+
match response {
62+
Success(_, _, _) => (),
63+
Reject(s, _) => panic!("parse error for {:?} at {:?}", s.next().0, s.position()),
64+
}
65+
});
66+
}
67+
68+
benchmark_group!(benches, http_data,);
69+
70+
benchmark_main!(benches);

lang/v1/ast/src/syntax.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ pub enum ASTParsec<I> {
3838
PAtom(I),
3939
PAtoms(Vec<I>),
4040
PBind(String, Box<ASTParsec<I>>),
41-
PCode(String),
4241
PMap(Box<ASTParsec<I>>, String),
4342
PSequence(Box<ASTParsec<I>>, Box<ASTParsec<I>>),
4443
PChoice(Box<ASTParsec<I>>, Box<ASTParsec<I>>),

lang/v1/normalizer/src/ast.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,31 +20,32 @@ pub enum ASTGrammar<A> {
2020
Bottom(),
2121
Var(String),
2222
Token(A),
23+
TokenChar(char),
2324
Seq(Box<AST<A>>, Box<AST<A>>),
2425
Choice(Box<AST<A>>, Box<AST<A>>),
2526
Rec(String, Box<AST<A>>),
2627
}
2728

2829
/*
29-
PAtom(char), // Single char
30-
PAtoms(Vec<char>), // Char sequence
3130
PBind(String, Box<ASTParsec>), // Variable
32-
PCode(String), // Production
33-
PMap(Box<ASTParsec>, String), // Remove?
34-
PNot(Box<ASTParsec>), // ?
35-
PCheck(Box<ASTParsec>), // No capture
31+
PMap(Box<ASTParsec>, String), // Map
32+
PNot(Box<ASTParsec>), // Negation
3633
3734
-- Pre-normalization
3835
3936
PN : ASTParsec -> (string -> ASTParsec) -> string list -> ASTGrammar
4037
41-
/ Var(n) if n in l
42-
PN[PIdent(n)]gl = {
43-
\ mu(n,PN[g(n)]g(n::l) otherwise
38+
/ Var(n) if n in l
39+
PN[PIdent(n)]gl = {
40+
\ mu(n,PN[g(n)]g(n::l) otherwise
4441
45-
PN[PEpsilon()]gl = Epsilon()
46-
PN[PSequence(T1,T2]]gl = Seq(PN[T1]gl,PN[T2]gl)
47-
PN[PChoice(T1,T2)]gl = Choice(PN[T1]gl,PN[T2]gl)
48-
PN[PRepeat(T)]gl = PN[T]gl | mu(n,Choice(Seq(PN[T]gl,Var(n)),Epsilon()))
49-
PN[PTry(T)gl] = PN[T]gl
42+
PN[PAtom(c)]gl = TokenChar(c)
43+
PN[PAtoms([])]gl = Epsilon()
44+
PN[PAtoms(c::l)]gl = Seq(TokenChar(v),PN[PAtoms(c::l)]gl)
45+
PN[PEpsilon()]gl = Epsilon()
46+
PN[PSequence(T1,T2]]gl = Seq(PN[T1]gl,PN[T2]gl)
47+
PN[PChoice(T1,T2)]gl = Choice(PN[T1]gl,PN[T2]gl)
48+
PN[PRepeat(T)]gl = PN[T]gl | mu(n,Choice(Seq(PN[T]gl,Var(n)),Epsilon()))
49+
PN[PTry(T)gl] = PN[T]gl
50+
PN[PCheck(T]gl] = PN[T]gl
5051
*/

lang/v1/parser/src/parser.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ use celma_v0_core::parser::literal::{delimited_char, delimited_string};
1919

2020
use celma_v0_macro::parsec_rules;
2121
use celma_v1_ast::syntax::ASTParsec::{
22-
PAtom, PAtoms, PBind, PCheck, PChoice, PCode, PEpsilon, PIdent, PMap, PNot, PRepeat, PSequence,
23-
PTry,
22+
PAtom, PAtoms, PBind, PCheck, PChoice, PEpsilon, PIdent, PMap, PNot, PRepeat, PSequence, PTry,
2423
};
2524
use celma_v1_ast::syntax::{ASTParsec, ASTParsecRule};
2625

@@ -117,14 +116,13 @@ parsec_rules!(
117116
let additional:{(bool,ASTParsec<char>)} = (skip c='|'? skip p=parsec) -> { (c.is_some(), p) }
118117

119118
let atom:{ASTParsec<char>} = (
120-
skip o=('^'|'!'|'#')? skip p=(atom_block|atom_ident|atom_char|atom_string|atom_code) skip
119+
skip o=('^'|'!'|'#')? skip p=(atom_block|atom_ident|atom_char|atom_string) skip
121120
) -> { mk_atom(o, p) }
122121

123122
let atom_block:{ASTParsec<char>} = ('(' p=parsec? ')') -> { p.unwrap_or_else(PEpsilon) }
124123
let atom_ident:{ASTParsec<char>} = c=ident -> { PIdent(c) }
125124
let atom_char:{ASTParsec<char>} = c=delimited_char -> { PAtom(c) }
126125
let atom_string:{ASTParsec<char>} = c=delimited_string -> { PAtoms(c.chars().collect()) }
127-
let atom_code:{ASTParsec<char>} = c=code -> { PCode(c) }
128126

129127
let transform:{String} = (skip "->" skip _=code)
130128

lang/v1/parser/tests/parser_tests.rs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,10 @@ mod parser_tests {
2020
use celma_v0_core::stream::char_stream::CharStream;
2121
use celma_v0_core::stream::specs::Len;
2222
use celma_v1::parser::{
23-
atom_char, atom_code, atom_ident, atom_string, code, code_content, kind, parsec, rule,
23+
atom_char, atom_ident, atom_string, code, code_content, kind, parsec, rule,
2424
};
2525
use celma_v1_ast::syntax::ASTParsec::{
26-
PAtom, PAtoms, PBind, PCheck, PChoice, PCode, PEpsilon, PIdent, PNot, PRepeat, PSequence,
27-
PTry,
26+
PAtom, PAtoms, PBind, PCheck, PChoice, PEpsilon, PIdent, PNot, PRepeat, PSequence, PTry,
2827
};
2928
use celma_v1_ast::syntax::ASTParsecRule;
3029
use celma_v1_ast::syntax::ASTType::{PChar, PUnit};
@@ -46,16 +45,6 @@ mod parser_tests {
4645
);
4746
}
4847

49-
#[test]
50-
fn should_parse_atom_code() {
51-
let response = atom_code().parse(CharStream::new("{hello()}"));
52-
53-
assert_eq!(
54-
response.fold(|v, _, _| v == PCode(String::from("hello()")), |_, _| false),
55-
true
56-
);
57-
}
58-
5948
#[test]
6049
fn should_parse_atom_char() {
6150
let response = atom_char().parse(CharStream::new("'a'"));

0 commit comments

Comments
 (0)