combine: ãã¯ãã®ãããªãRustã®ãã¼ãµã¼ã³ã³ããã¼ã¿ã¼
ã¯ããã«
Rustã«ã¯æåãªnom
ã¨ãããã¼ãµã¼ã³ã³ããã¼ã¿ã¼ã©ã¤ãã©ãªããããããã£ããé«ç´ãªåã·ã¹ãã ã¨æé©åãããã®ã«ãã¯ãã§ä½ã¨ããããã¨ããã®ã¯å¿ä½ç¡ãã¨æãã®ã§ããã¯ãã«æ·±ãä¾åããªãcombine
ã使ã£ã¦ã¿ãã
combineã®ä¸»ãªç¹å¾´
parsec
ãªã¹ãã¯ãã®ãã¼ãµã¼ã³ã³ããã¼ã¿ã¼- ã³ã³ããã¼ã¿ã¼ã¯ãã¯ãã§ã¯ãªãã
Parser
traitãå®è£ ããå¤ã§è¡¨ã - ãã¤ãã¹ããªã¼ã ãæå(Unicodeã³ã¼ããã¤ã³ã)ã¹ããªã¼ã ããã¼ã¯ã³ã¹ããªã¼ã ã®å ¨ã¦ã«å¯¾å¿
- ã¡ã¢ãªä¸ã®æååã ãã§ã¯ãªããå ¥åã¹ããªã¼ã ããã®ç´æ¥ã®ãã¼ã¹ã«ã対å¿
ã¾ã è¨æ¸¬ã¯ãã¦ããªããã Box
ãå¤ç¨ãã¦ãããã¯ããªãã®ã§ãé度çã«å¤§ããé
ããã¨ããããªãã¨ã¯ãªãã®ã§ã¯ãªããã¨æãã
以ä¸ãparsecã«ã¤ãã¦ç¥ã£ã¦ããã»ããèªã¿ãããæ§æã«ãªã£ã¦ããã®ã§ãå¿ è¦ãªãparsecã®è³æãæ¢ãã¦èªãã¨ãããããããªãã大éæã«è¨ãã¨ã1ã¤ã®æ§æè¦ç´ ã1ã¤ã®é¢æ°(ç¾å¨ä½ç½®ãåãåã£ã¦ãæå/失æã¨æ¬¡ã®ä½ç½®ãè¿ã)ã§ããããå帰ä¸éãã¼ãµã¼ã¨ããã®ããã¼ã¹ã«ãªã£ã¦ããããã®æ§æ解æé¢æ°ãèªåã§æ¸ããªãã¦ããæ¢åã®é«éé¢æ°ãçµã¿åããã¦æ軽ã«æ¸ããããã«ããã®ããã¼ãµã¼ã³ã³ããã¼ã¿ã¼ã§ããã
åºæ¬çãªä½¿ãæ¹
Cargo.toml
ã®ä¸èº«
[dependencies] combine = "2.2.2" # ããã¯å¿ è¦ãªããã°åé¤ãã¦ããã combine-language = "2.0.0"
src/main.rs
ã®ä¸èº«
extern crate combine; use combine::{Parser, many1}; use combine::char::digit; fn main() { let mut parser = many1::<Vec<_>, _>(digit()); println!("{:?}", parser.parse("123")); println!("{:?}", parser.parse("123ABC")); println!("{:?}", parser.parse("ABC123")); }
å®è¡çµæ
Ok((['1', '2', '3'], "")) Ok((['1', '2', '3'], "ABC")) Err(ParseError { position: 94191262981061, errors: [Unexpected(Token('A')), Expected(Borrowed("digit"))] })
æåããå ´åã¯ããã¼ã¹çµæã¨ãæ®ãæååãè¿ãããã
ãã¤ã³ã
次ã®ããã«ãã¦ãã¼ãµã¼ãçæãããããã¯ååãããããããã«æ°åã®1å以ä¸ã®ä¸¦ã³ãåå¾ããã
let mut parser = many1(digit());
ããã§ã digit()
ã¯é¢æ°å¼ã³åºãã ããããã§ã¯ãã¼ãµã¼ã®çæãè¡ããã¦ããã ãã§ããã®æç¹ã§ãã¼ãµã¼ãå®è¡ããã¦ããããã§ã¯ãªãã
many1
ã¯ä»»æã® FromIterator
ã«å¤æã§ãããããã§ã¯ Vec<_>
ã使ãããããããæ示ãã¦ããã
parser
㯠mut
ã§ãªãã¨ãããªããããã¯å¿è« parse(&mut self, ...
ã ããã ããããã¯çªãè©°ããã°ã¹ãã¼ããã«ãªãã¼ãµã¼ãæ¸ãããã ã¨æãããã
è²ã çµã¿åããã
parsecã® (>>=)
㨠return
ã¯ãããã .then
㨠value
ã¨ããååã«ãªã£ã¦ããã
// ä½ãèªã¾ãã«1ãè¿ã let mut parser = value(1); assert_eq!(parser.parse("123"), Ok((1, "123")));
// åãæå2ã¤ã®ä¸¦ã³ãèªã let mut parser = letter().then(|c| token(c)); assert_eq!(parser.parse("aa"), Ok(('a', ""))); assert!(parser.parse("11").is_err()); assert!(parser.parse("ab").is_err());
åã«ããã¼ã¹ããçµæãå¤æãããå ´åã¯ã .map
ã使ãã(parsecã§ããã¨ããã® fmap
, (<$>)
)
// æ°åã®1ã¤ä»¥ä¸ã®ä¸¦ã³ããã¼ã¹ãã¦ãæ°å¤ã¨ãã¦è¿ã let mut parser = many1::<String, _>(digit()).map(|s| s.parse::<u32>().unwrap()); assert_eq!(parser.parse("123"), Ok((123, "")));
å·¦ã試ãã¦ã失æãããå³ã試ãã«ã¯ã.or
ã使ãã (parsecã® (<|>)
ã¨åæ§ãå·¦ã§1æå以ä¸æ¶è²»ãã¦å¤±æãããå³ã¯è©¦ããªãã)
// æ´æ°ããã¼ã¹ let mut parser = token('-') .with(many1::<String, _>(digit()).map(|s| -s.parse::<i32>().unwrap())) .or(many1::<String, _>(digit()).map(|s| s.parse::<i32>().unwrap())); assert_eq!(parser.parse("123"), Ok((123, ""))); assert_eq!(parser.parse("-123"), Ok((-123, "")));
ä¸ã§ä½¿ããã¦ãã .with
ã¯å·¦ã®çµæãæ¨ã¦ã¦ç¶ãã¦å³ãèªã (parsecã® (*>)
) ãéã«ãå³ã®çµæãæ¨ã¦ã (parsecã® (<*)
) ã¨ã㯠.skip
ã使ãã使ãæ¹ã¯ã»ã¼åãã
ãã¤ã³ã
æ±ç¨ã®ã³ã³ããã¼ã¿ã¼ã¯ combine::combinator
ã«ãããã¾ããæåç¨ã¨å¾è¿°ãããã¤ãç¨ã®ã³ã³ããã¼ã¿ã¼ã¯ãããã combine::char
㨠combine::byte
ã«ããã
combine::combinator
ã«ããã³ã³ããã¼ã¿ã¼ã¯ä»¥ä¸ã®æ¹æ³ã§ãå©ç¨ã§ããã
combine
ã®ç´ä¸ã«åããã®ãuseããã¦ãããã¨ããããcombine::Parser
ã«ã¡ã½ããã¨ãã¦å®è£ ããã¦ãããã¨ããããã¡ã½ãããã§ã¼ã³ã¨ãã¦æ¸ãã®ã«ã使ããã
combineã®ã³ã³ããã¼ã¿ã¼ã¯parsecã¨åããããªæè¦ã§ä½¿ããããã«ãªã£ã¦ãããã大ããªéãã1ã¤ãããparsecã®ãã¼ãµã¼ ParsecT s u m a
ã¯åã³ã³ã¹ãã©ã¯ã¿ã§ããããããã£ã¦ãä¾ãã°ã [Char]
ãèªã㧠Int
ãè¿ããã¼ãµã¼ããªããä¸èº«ã«ãããåãå Parsec [Char] () Int
ããã¤ã
ä¸æ¹ãcombineã®ãã¼ãµã¼ Parser
ã¯trait(åã¯ã©ã¹ã®ãããªãã®)ã§ãããåãã &str
ãèªã㧠i32
ãè¿ããã¼ãµã¼ãã§ãããã¼ãµã¼ã®å®è£
ãã¨ã«ç°ãªãåããã¤ã
ç°ãªãå®è£
ã®ãã¼ãµã¼ãåãããã«æ±ãããã¨ãããã¨ããããããªãã°ãtrait objectã使ã£ã¦ Box<Parser<Input=&'a str, Output=i32>>
ã®ããã«æ¸ããã¨ã¯å¯è½ã§ããã
åå©ç¨ã¨å帰
åå©ç¨å¯è½ãªãã¼ãµã¼ãæ¸ãã¨ãã¯ãæ £ç¿çã«ã¯ä»¥ä¸ã®æé ãè¸ãã
- ãã®ãã¼ãµã¼ãããããåã
struct
ã§ä½ãã - ãã®å®è£
ã
impl
ã§æ¸ãã - ãã®ãã¼ãµã¼ãçæããé¢æ°ã
fn
ã§æ¸ãã
ä¾ãã°ãå ã»ã©ä½æããéè² æ´æ°ãã¼ãµã¼ã¯ä»¥ä¸ã®ããã«æ¸ãã
// éè² æ´æ°ãã¼ãµã¼ãããããå struct Unsigned<I>(PhantomData<fn(I) -> I>); // éè² æ´æ°ãã¼ãµã¼ã®å®è£ impl<I> Parser for Unsigned<I> where I: Stream<Item=char> { type Input = I; type Output = u32; #[inline] fn parse_stream(&mut self, input: I) -> ParseResult<Self::Output, Self::Input> { // åºæ¬çãªæ¸ãæ¹: ã©ããããããã¼ãµã¼ããã®å ´ã§çæããparse_streamã移è²ããã ãã let mut parser = many1::<String, _>(digit()).map(|s| s.parse::<u32>().unwrap()); parser.parse_stream(input) } } // éè² æ´æ°ãã¼ãµã¼ãè¿ãé¢æ° fn unsigned<I>() -> Unsigned<I> where I: Stream<Item=char> { Unsigned(PhantomData) }
ããã使ãã¨ä»¥ä¸ã®ããã«æ´æ°ãã¼ãµã¼ãæ¸ããã
// æ´æ°ããã¼ã¹ let mut parser = token('-').with(unsigned()).map(|x| -(x as i32)) .or(unsigned().map(|x| x as i32)); assert_eq!(parser.parse("123"), Ok((123, ""))); assert_eq!(parser.parse("-123"), Ok((-123, "")));
ä¸ã®ãããªæ¹æ³ã使ãã°ãå帰çãªãã¼ãµã¼ãæ¸ããã¨ãã§ããããã ããåã«å帰çãªãã¼ãµã¼ãã»ããã ããªããããç°¡åãªæ¹æ³ãããã
parser
é¢æ°ã使ãã¨ãé¢æ°ãã¯ãã¼ã¸ã£ããã¼ãµã¼ã«å¤æã§ãããããã使ãã°ãä¾ãã°æ¬å¼§ã®å¯¾å¿ãã¨ãã¦ããæååããã¼ã¹ãã以ä¸ã®ãããªãã¼ãµã¼ãæ¸ããã
// æ¬å¼§ã®å¯¾å¿ fn paren<I>(input: I) -> ParseResult<(), I> where I: Stream<Item=char> { let mut parser = token('(').with(parser(paren::<I>)).skip(token(')')) .or(token('[').with(parser(paren::<I>)).skip(token(']'))) .or(value(())); parser.parse_stream(input) }
ããã¯ä»¥ä¸ã®ããã«ä½¿ããã
let mut parser = parser(paren); assert_eq!(parser.parse("[()]"), Ok(((), ""))); assert!(parser.parse("[(])").is_err());
ã¨ã©ã¼å¦ç
combineã¯parsecã¨ä¼¼ãããã¯ãã©ãã¯è¦åãæ¡ç¨ãã¦ãããã¤ã¾ãã
- 1æåãæ¶è²»ããã«å¤±æããããããã¯ãã©ãã¯ããã
- 1æå以ä¸æ¶è²»ãã¦å¤±æããããããã¯ãã©ãã¯ãããã«å ¨ä½ã失æã¨ããã
ãããã£ã¦ä»¥ä¸ã¯å¤±æããã
// 2AHã®ãããª16é²æ°ãã20Dã®ãããªåé²æ°ãåçãããã¨ãã¦ãã let mut parser = many1::<String, _>(hex_digit()).skip(char('H')) .or(many1::<String, _>(digit()).skip(char('D'))); // ããã¯ãã©ãã¯ããªãããããããããªã println!("{:?}", parser.parse("123D"));
Err(ParseError { position: 94623997271456, errors: [Unexpected(Borrowed("end of input")), Expected(Token('H'))] })
ãã®è¦åã®ä¾å¤ãå¿
è¦ãªå ´åã¯ã try
ã使ãã try
ã§å
ã¾ãããã¼ãµã¼ã¯å¤±æããå ´åã¯1æåãæ¶è²»ããªãã£ããã¨ã«ãªãã
// 2AHã®ãããª16é²æ°ãã20Dã®ãããªåé²æ°ãåçãã let mut parser = try(many1::<String, _>(hex_digit()).skip(char('H'))) .or(try(many1::<String, _>(digit()).skip(char('D')))); println!("{:?}", parser.parse("123D"));
Ok(("123", ""))
.expected
ã使ãã¨ãããã¯ãã©ãã¯æã« “Expected …” ã¨ããå½¢ã®ã¨ã©ã¼ã¡ãã»ã¼ã¸ãä»ä¸ã§ããããã°ãã° try
ã¨ä½µç¨ããã (ã¨æãããã)
// 2AHã®ãããª16é²æ°ãã20Dã®ãããªåé²æ°ãåçãã let mut parser = try(many1::<String, _>(hex_digit()).skip(char('H'))).expected("hexadecimal number") .or(try(many1::<String, _>(digit()).skip(char('D'))).expected("decimal number")); println!("{:?}", parser.parse("123"));
Err(ParseError { position: 94647351694019, errors: [Unexpected(Borrowed("end of input")), Expected(Token('H')), Expected(Token('D')), Unexpected(Token('1')), Expected(Borrowed("hexadecimal number")), Expected(Borrowed("decimal number"))] })
å½ããåã ã try
ãå¢ããã°ããã¯ãã©ãã¯ãå¢ããã®ã§ããã©ã¼ãã³ã¹ãè½ã¡ãå¯è½æ§ããããããã¾ã§ãã§ããã ãå
èªã¿ã®ãããªãå½¢ã§ãã¼ã¹ããã®ãæã¾ããã ããã try
ã®å
¸åçãªå©ç¨æ¹æ³ã®1ã¤ã¯ãåå¥è§£æã¨æ§æ解æããããã¦ãããããªè¨èªã«ããããåå¥ãã®ãã¼ãµã¼ã§ããã¨èããããã
ãã¤ããã¼ãµã¼
ããã¾ã§ã¯ãUnicodeã®ã³ã¼ããã¤ã³ããã¨ã«å¦çããããã¼ãµã¼ãæ±ã£ããcombineã§ã¯ãæåã«éãããä½ãã並ãã§ããã°ããããã¼ã¹ãããã¨ãã§ãããä½ãã®ä¸¦ã³ã¯ Stream
ã¨ããtraitã§ãããããããæåã®ä¸¦ã³ã¯ Stream<Item=char>
, ãã¤ãã®ä¸¦ã³ã¯ Stream<Item=u8>
ã§ããã
ä¾ãã°ä»¥ä¸ã®ããã« &[u8]
ã«å¯¾ãã¦æ§æ解æãå®è¡ã§ããã
let mut parser = many1::<Vec<_>, _>(combine::byte::digit()); assert_eq!(parser.parse(&b"123ABC"[..]), Ok((vec![49, 50, 51], &[65, 66, 67][..])));
ã¹ããªã¼ã ãã¼ãµã¼
combineã§ã¯&[u8]
ã&str
ã®ããã«æ¢ã«å
¨ä½ãã¡ã¢ãªä¸ã«èªã¿è¾¼ã¾ãã¦ãããã®ä»¥å¤ã«ããç¹å®ã®å
¥åã¹ããªã¼ã ããå¿
è¦ã«å¿ãã¦ãã¼ã¯ã³ãèªã¿è¾¼ããããªãã¼ãµã¼ãæ¸ããã¨ãã§ãããããã«ã¯ Stream
ãå®è£
ããä»ã®åã使ãã°ããã
ä¾ãã°ãæ¨æºå
¥åã®ããã« Read
ãå®è£
ãããã®ã«å¯¾ãã¦ãã¤ãåä½ã§æ§æ解æãããã«ã¯ãfrom_read
㨠BufferedStream
ã使ããã¨ãã§ããã
let stdin = std::io::stdin(); let stdin = stdin.lock(); // å èªã¿10æå let stdin_stream = BufferedStream::new(from_read(stdin), 10); let stdin_stream = stdin_stream.as_stream(); // è±æ°åã¨ç©ºç½ä»¥å¤ãããã¾ã§èªã¿ç¶ãã let mut parser = many1::<Vec<_>, _>(combine::byte::alpha_num().or(combine::byte::space())); println!("{:?}", parser.parse(stdin_stream));
å®è¡ããã¨ãè±æ°åã¨ç©ºç½(æ¹è¡ãå«ã)ãããéã¯ã¹ããªã¼ã ããèªã¿ç¶ããããã以å¤ã®æåãæ¥ãæç¹ã§èªã¿è¾¼ã¿ãåæ¢ãããã
ãã¤ã³ã
Stream
èªä½ã¯ç°¡åã§ãã¤ã³ã¿ã¼ãã§ã¼ã¹ãè¦ãã°ä¸ç®çç¶ã§ããããããå®éã®ã¹ããªã¼ã ãã¼ãµã¼ã®å®è£
ã¯ããå°ãè¤éã§ããã
ã¾ãã Stream
ãåã« StreamOnce + Clone
ã§ãããã¨ã«æ³¨æãããã¾ã StreamOnce
㯠Iterator
ã«ä½ç½®è¨æ¶æ©è½ãã¤ãããã®ã«éããªãã
StreamOnce
㯠Read
ãã©ãããã (from_read
) ãã¨ã§ç°¡åã«å®ç¾ã§ããããããããã§ã¯ Clone
ã足ããªãã Clone
ãå¿
è¦ãªã®ã¯ãã¡ãããããã¯ãã©ãã¯ã®ããã§ããã
ãã®ããã«ãStreamOnce
ãã©ããã㦠Stream
ãä½æããä¸è¬çãªä»çµã¿ãæä¾ããã¦ãããããã BufferedStream
ã§ããã
ã¹ããªã¼ã æ¬ä½ã¯ãã¡ããè¤è£½ã§ããªãã®ã§ã BufferedStream
ã¯ã¹ããªã¼ã æ¬ä½ã®ç¹å®ä½ç½®ãåç
§ããã ãã®ç°¡åãªãã¼ã¿æ§é ã¨ãã¦ãµãã¾ããä¾ãã°ã3ã¤ã® BufferedStream
ãåãã¹ããªã¼ã ã®ä½ç½®50, ä½ç½®80, ä½ç½®110ãåç
§ããã¨ãã£ããã¨ãèããããããã®ã¨ããã¹ããªã¼ã æ¬ä½ã¯ä½ç½®110ã¾ã§èªã¿è¾¼ã¿æ¸ã¿ã®ç¶æ
ã§ããã
ãã®ã¨ãä½ç½®50ã®ã¹ããªã¼ã ããèªã¿ç´ãããã¨ãããã¨ãããããããã®ããã«ãã¹ããªã¼ã æ¬ä½ããèªã¿åºãããã¼ã¿ã¯å ±æã®å èªã¿ãããã¡ã«ä¿åããããå èªã¿ãããã¡ã®èªå解æ¾ãããã«ã¯ããè¤éãªä»çµã¿ãå¿ è¦ãªã®ã§ãããã§ã¯åºå®ãµã¤ãºã®ãããã¡ã確ä¿ãã¦ãããå èªã¿ãããã¡ãã溢ããé¨åãèªã¿åºããã¨ããå ´åã¯ã¨ã©ã¼ã¨ãªãã
Read
ã使ã£ã¦ãã¤ãã¹ããªã¼ã ã§ã¯ãªãæåã¹ããªã¼ã Stream<Item=char>
ãå¾ãã®ã¯å°ãé¢åããã ã Read::chars()
ãåèã«èªåã§å®è£
ãã¦ãã¾ãã»ãã楽ãããããªãã
ãã¼ã¯ã³ãã¼ãµã¼
parsecåæ§ããã¾ãçé¢ç®ã«ãµãã¼ãããã¦ãããã¨ããã¨å¾®å¦ã ããä¸åº¦åå¥è§£æå¨ããã¼ã¯ã³åãçæãããã®å¾ã§æ§æ解æå¨ããã¼ã¯ã³åã解æãããã¨ãããããªå®è£ ãå¯è½ã§ããã
ãããå®è£ æ¹æ³ã«ãã£ã¦é£æ度ãç°ãªããããã¼ã¯ã³åãä¸åº¦ã¡ã¢ãªä¸ã«å ¨é¨å±éããããä½ç½®æ å ±ãä¿æããªããã¨ããæ¡ä»¶ãªãããã»ã©é£ãããªãã
extern crate combine; use combine::char::{char, digit, spaces}; use combine::{many, many1, Parser, eof, sep_by1, satisfy_map}; #[derive(Debug, Copy, Clone, PartialEq, Eq)] enum Token { Number(u32), Plus, } fn lex(s: &str) -> Vec<Token> { let number = many1::<String, _>(digit()).map(|s| Token::Number(s.parse::<u32>().unwrap())); let plus = char('+').map(|_| Token::Plus); let mut parser = spaces().with(many(number.or(plus).skip(spaces()))).skip(eof()); parser.parse(s).map(|x| x.0).unwrap() } fn eval(s: &str) -> u32 { let tokens = lex(s); let number = satisfy_map(|t| match t { Token::Number(x) => Some(x), _ => None, }); let plus = satisfy_map(|t| match t { Token::Plus => Some(()), _ => None, }); let mut parser = sep_by1::<Vec<_>, _, _>(number, plus).map(|v| v.iter().sum()); parser.parse(&tokens[..]).unwrap().0 } fn main() { println!("{:?}", lex("1")); println!("{:?}", lex(" 1 + 2 ")); println!("{:?}", lex("100 + 200+323")); println!("{:?}", eval("1")); println!("{:?}", eval(" 1 + 2 ")); println!("{:?}", eval("100 + 200+323")); }
combine-language
combine-language
ã使ãã¨ãå
¸åçãªããã°ã©ãã³ã°è¨èªã®lexerãèªåã§çæã§ããããããparsecã®Text.Parsec.Token
ã¨ä¼¼ãæ©è½ãæä¾ãããã®ã§ããã
combine-languageã使ã£ã¦ç°¡æçãªé»åããã°ã©ã (ååæ¼ç®ãã¼ãµã¼)ãæ¸ãã¨ä»¥ä¸ã®ããã«ãªãã
extern crate combine; extern crate combine_language; use combine::char::{string, letter, alpha_num}; use combine::{Parser, satisfy, Stream, ParseResult, parser, chainl1}; use combine_language::{LanguageEnv, LanguageDef, Identifier}; #[derive(Debug, Clone, PartialEq, Eq)] enum Expr { Number(i64), Plus(Box<Expr>, Box<Expr>), Minus(Box<Expr>, Box<Expr>), Times(Box<Expr>, Box<Expr>), Divides(Box<Expr>, Box<Expr>), } fn calc_env<'a, I>() -> LanguageEnv<'a, I> where I: Stream<Item=char>, I: 'a { LanguageEnv::new(LanguageDef { ident: Identifier { start: letter(), rest: alpha_num(), reserved: ["if", "then", "else", "let", "in", "type"].iter() .map(|x| (*x).into()) .collect(), }, op: Identifier { start: satisfy(|c| "+-*/".chars().any(|x| x == c)), rest: satisfy(|c| "+-*/".chars().any(|x| x == c)), reserved: ["+", "-", "*", "/"].iter().map(|x| (*x).into()).collect() }, comment_start: string("/*").map(|_| ()), comment_end: string("*/").map(|_| ()), comment_line: string("//").map(|_| ()), }) } // æ´æ°ã¾ãã¯æ¬å¼§ã§æ¬ãããå¼ fn factor<I>(input: I) -> ParseResult<Box<Expr>, I> where I: Stream<Item=char> { let env = calc_env(); let number = env.integer().map(|x| Box::new(Expr::Number(x))); let parenthesized = env.parens(parser(expr)); number.or(parenthesized).parse_stream(input) } // æãç®ã»å²ãç®ã¾ãã¯factor fn term<I>(input: I) -> ParseResult<Box<Expr>, I> where I: Stream<Item=char> { let env = calc_env(); let op = env.reserved_op("*").or(env.reserved_op("/")) .map(|op| move |lhs, rhs| { if op == "*" { Box::new(Expr::Times(lhs, rhs)) } else if op == "/" { Box::new(Expr::Divides(lhs, rhs)) } else { unreachable!() } }); chainl1(parser(factor), op) .parse_stream(input) } // å ¨ã¦ã®å¼ fn expr<I>(input: I) -> ParseResult<Box<Expr>, I> where I: Stream<Item=char> { let env = calc_env(); let op = env.reserved_op("+").or(env.reserved_op("-")) .map(|op| move |lhs, rhs| { if op == "+" { Box::new(Expr::Plus(lhs, rhs)) } else if op == "-" { Box::new(Expr::Minus(lhs, rhs)) } else { unreachable!() } }); chainl1(parser(term), op) .parse_stream(input) } fn main() { let mut parser = parser(expr); println!("{:?}", parser.parse("1 + 2 * 3")); }
è¡çªå·ã¨åçªå·
è¡çªå·ãåçªå·ãåå¾ããã«ã¯ãã¹ãã¼ããã«ãªåå¥è§£æå¨ãç¨æããã¨ããæ¹æ³ãèããããããã®ä»ã«ã以ä¸ã®ããã«ã㦠Stream
ã«1æåã¾ãã¦ãå®è£
ã§ããã
extern crate combine; use combine::char::{string, letter, alpha_num, space}; use combine::{Parser, satisfy, Stream, ParseResult, parser, chainl1, StreamOnce, many1, eof}; #[derive(Debug, Clone)] pub struct CRStream<I> { inner: I, rownum: usize, rowpos: usize, } impl<I> CRStream<I> where I: Stream<Item=char, Position=usize> { pub fn new(inner: I) -> Self { let rowpos = inner.position(); CRStream { inner: inner, rownum: 0, rowpos: rowpos, } } } impl<I> StreamOnce for CRStream<I> where I: Stream<Item=char, Position=usize> { type Item = I::Item; type Range = I::Range; type Position = (usize, usize); fn uncons(&mut self) -> Result<Self::Item, combine::primitives::Error<Self::Item, Self::Range>> { let c = try!(self.inner.uncons()); if c == '\n' { self.rownum += 1; self.rowpos = self.inner.position(); } Ok(c) } fn position(&self) -> Self::Position { (self.rownum, self.inner.position() - self.rowpos) } } fn main() { // è±æ°åã¨ç©ºç½ã®ã¿ãããªãæååãåçãã let mut parser = many1::<Vec<_>, _>(alpha_num().or(space())).skip(eof()); println!("{:?}", parser.parse("hoge")); println!("{:?}", parser.parse("hoge+fuga")); println!("{:?}", parser.parse("h\nge+fuga")); // è±æ°åã¨ç©ºç½ã®ã¿ãããªãæååãåçãã let mut parser = many1::<Vec<_>, _>(alpha_num().or(space())).skip(eof()); println!("{:?}", parser.parse(CRStream::new("hoge"))); println!("{:?}", parser.parse(CRStream::new("hoge+fuga"))); println!("{:?}", parser.parse(CRStream::new("h\nge+fuga"))); }
Position
㯠Ord
ãå®è£
ãããã¨ã«æ³¨æãããã¨ãããã§ã¯ (row, column)
ãè¿ãã¦ããããã¿ãã«ã®é åºã¯è¾æ¸é ã§ããããããã® Ord
æ§é ã¯æ§æ解æã®åãã¨æ´åãã¦ããã
ã¾ã¨ã
combineã¯ãparsecã®ãããªå©ä¾¿æ§ã»æ±ç¨æ§ã¨ãRustã®ã©ã¤ãã©ãªã«æ±ããããã¼ãæ½è±¡åã両ç«ãããã¨ãã¦ãããRustã®å¼·åãªåã·ã¹ãã ããã¾ãæ´»ç¨ãããã¨ã§ããããã¯ååã«å®ç¾ã§ãã¦ããããã«æãã
ä¸æ¹ã§ãparsecã«æ¯ã¹ã¦ä¸ä¾¿ãªç¹ããç¾æç¹ã§å¿ è¦ãªã¤ã³ã¿ã¼ãã§ã¼ã¹ãä¸è¶³ãã¦ããç¹ãæãããããã¾ããåã¨ã©ã¼ã®è§£æ±ºã¯æ±ºãã¦ç°¡åã§ã¯ãªããRustã®åã·ã¹ãã ã«æ £ãã¦ããªããã°ãªãããèºãããããããããªãã
å人çã«ã¯ããã¯ããé§ä½¿ãã¦ãã nom
ããã好å°è±¡ã§ãã£ãã