ๆฑใใใใใฎใใใซใๅ
ฅๅใจใชใๆๅญๅใๅ
จใฆ Vec<char>
ใจไปฎๅฎใใ.
ใใผใถใฏใ Vec<char>
ใๅ
ฅๅใจใใฆๅใๅใใๆถ่ฒปใใ (่ชญใใ ) ๅใจใใพใ ่ชญใใงใชใๅใฎใใข (Vec<char>, Vec<char>)
ใ่ฟใ้ขๆฐใงใใ.
ใใ ใใใใผในใฏๅธธใซๆๅใใใจใฏ้ใใชใใฎใงใใใใๆดใซ Option
ใงๅ
ใ. ใใฎ่ฟใๅใ ParseResult
ใจใใ.
ใใใใฃใฆใใใผใถใฏ Vec<char>
ใๅใฃใฆ ParseResult
ใ่ฟใ้ขๆฐใงใใใใ้ฝๅไธใใใใ Box
ใซๅ
ใใงใใใ Parser
ใจๅไปใใ struct ใงๅ
ใ.
type ParseResult = Option<(Vec<char>, Vec<char>)>;
struct Parser(Box<Fn(&Vec<char>) -> ParseResult>);
้ขๆฐๅใฃใฝใๆธใๅ ดๅใฏใๅ
ฅๅใฏๅ็
ง &
ไปใใฆ่ชญใใฐๅคงไฝใใๆฐใใใ.
ๅ่ในใฉใคใใซใใใใฃใฆใ1ๆๅญใ ใใ่ชญใใใผใถ (one_of
) ใจ้ ญใฎไฝๆๅญๅใ่ชญใใใผใถ (string
) ใๅฎ่ฃ
ใใ.
้ ญใฎไธๆๅญใไธใใฆใๆถ่ฒปใใใใใผใถใไฝใ.
fn one_of(c: char) -> Parser {
Parser(Box::new(move |cs: &Vec<char>| {
if cs.len() == 0 || cs[0] != c {
None
} else {
Some((vec![c], cs[1..].to_owned()))
}
}))
}
ๆๅญ c
ใๅใๅใฃใฆๆฌกใฎใใใชใใผใถ (Parser) ใ่ฟใ. ใใผใถใฏๆๅญๅ cs
ใๅใๅใฃใฆใ้ ญใฎไธๆๅญใ c
ใจไธ่ดใใใใใใใๆถ่ฒปใใฆใๆฎใ (cs[1..]
) ใๆถ่ฒปใใใซ่ฟใ. ้ ญใไธ่ดใใชใใใใใใใ cs
ใ้ทใ0ใฎๅ ดๅใฏ้ ญใ็กใใฎใงๅคฑๆ None
ใ่ฟใ.
ไฝใฃใใใผใถใๆญฃใใๅไฝใใใใ็ขบ่ชใใใใฎใงใๅ ใซใใใผใถใๆๅญๅใซ้ฉ็จใใใกใฝใใใๅฎ่ฃ ใใ.
impl Parser {
fn call(&self, s: String) -> ParseResult {
let Parser(ref f) = *self;
let chars = s.chars().collect::<Vec<_>>();
f(&chars)
}
}
ใใผใถ (self) ใฎไธญ่บซใ let Parser(ref f) = ...
ใฎ้จๅใง f
ใจใใๅๅใไปใใฆๅใๅบใ. Boxใซๅ
ใใงใใใใใฎใพใพ้ขๆฐใจใใฆไฝฟใใฐ่ฏใ. ใใใใ ref
ใง้ขๆฐใๅ็
งใใฆใใฎใฏใparser
ใ็นฐใ่ฟใไฝๅบฆใๅฉ็จใใใใ (ๅ็จใฎใขใฌ).
ๅ
ใปใฉใฎ one_of
ใไฝฟใฃใฆใฟใ.
let parser = one_of('a');
let s = String::from("abc");
println!("{:?}", parser.call(s));
=>
Some((['a'], ['b', 'c']))
fn string(s: String) -> Parser {
let ds: Vec<char> = s.chars().collect();
Parser(Box::new(move |cs: &Vec<char>| {
let n = ds.len();
if cs.len() < n { return None }
for i in 0..n {
if ds[i] != cs[i] { return None }
}
Some((ds.to_owned(), cs[n..].to_owned()))
}))
}
ๅบๆฌ็ใซ one_of
ใจๅใ.
choose
/
2ใคใฎใใผใถใไธใใฆใ1ใคใใ่ฉฆใใฆๆๅใใใใใใ่ฟใ. ๅคฑๆใใใ2ใค็ฎใ่ฟใใใจใใใใผใถใ็ๆใใใณใณใใใผใฟใๅฎ่ฃ ใใ.
ๅ ใซไฝฟใๆนใ่ฟฐในใใจ
let parser = one_of('a') / one_of('b'); // 'a' ใ่ชญใ. ๅคฑๆใใใใ'b' ใ่ชญใ
{
let s = String::from("abc");
println!("{:?}", parser.call(s));
}
{
let s = String::from("bbc");
println!("{:?}", parser.call(s));
}
{
let s = String::from("cbc"); // fails
println!("{:?}", parser.call(s));
}
็ตๆใฏ้ ใซ
Some((['a'], ['b', 'c']))
Some((['b'], ['b', 'c']))
None
้ฉ็จใใ้ขๆฐใๅ
ใซ่ฟฐในใใฎใงใใใใไฝฟใใฐใใใ ใ. 1ใคใใ้ฉ็จใใฆใ None ใ่ฟใใใ2ใคใใฎ้ฉ็จใใ็ตๆใ่ฟใ. choose
ใจใใๅๅใฎ้ขๆฐใจใใฆๅฎ่ฃ
ใใ.
fn choice(p1: Parser, p2: Parser) -> Parser {
let Parser(f1) = p1;
let Parser(f2) = p2;
Parser(Box::new(move |cs: &Vec<char>| {
if let Some(a) = f1(&cs) {
Some(a)
} else {
f2(&cs)
}
}))
}
ใกใใฃใจ่ฉฐใพใใใคใณใใจใใฆใฏใf1(cs)
ใง cs
ใใใฃใกใซ่กใฃใกใใฃใฆไฝฟใใชใใชใใฎใง clone
ใๆธกใ. ใฆใๆฎ้ใซใๅ
ฅๅใๅ็
งใงๅใๅใใใใซใใผใถใๅฎ็พฉใใใฐใใใฃใใชใ. ไปๆดใใฃใ.
ๆผ็ฎๅญ /
ใงๆธใใใปใใใกใใฃใจใใฃใใใใฎใงใๆผ็ฎๅญใชใผใใผใญใผใใใ.
use std::ops::Div;
impl Div for Parser {
type Output = Parser;
fn div(self, rhs: Parser) -> Parser { choice(self, rhs) }
}
then
+
ไปๅบฆใฏใ2ใคใฎใใผใถใ้ ใซ้ฉ็จใใใจใใใใผใถใ็ๆใใ. ใฉใฃใกใใงใใผในใซๅคฑๆใใใฐใๅ จไฝใจใใฆใๅคฑๆใจใใ.
choose
ใใกใใฃใจๆธใ็ดใใ ใใงใใ.
fn then(p1: Parser, p2: Parser) -> Parser {
let Parser(f1) = p1;
let Parser(f2) = p2;
Parser(Box::new(move |cs: &Vec<char>| {
if let Some((xs, ys)) = f1(&cs) {
if let Some((xs2, ys2)) = f2(&ys) {
let mut mxs = xs.clone();
let mut mxs2 = xs2.clone();
mxs.append(&mut mxs2);
return Some((mxs.to_owned(), ys2))
}
}
None
}))
}
use std::ops::Add;
impl Add for Parser {
type Output = Parser;
fn add(self, rhs: Parser) -> Parser { then(self, rhs) }
}
let parser = (string(String::from("A")) / string(String::from("The"))) + one_of(' ') + string(String::from("cat"));
{
let s = String::from("My cat"); // fails
println!("{:?}", parser.call(s));
}
{
let s = String::from("The cat");
println!("{:?}", parser.call(s));
}
}
None
Some((['T', 'h', 'e', ' ', 'c', 'a', 't'], []))
ใฆใใใๆฏๅ String::from ใคใใใฎใ ใใ.