Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- use std::error::Error;
- use std::io::{self, Read, Write};
- #[allow(unused_imports)] use std::time::Instant;
- const ESC_DEFAULT: &[u8] = b"\x1b[0m";
- const ESC_COMMENT: &[u8] = b"\x1b[90m";
- const ESC_SYMBOL: &[u8] = b"\x1b[36m";
- const ESC_STR: &[u8] = b"\x1b[32m";
- const ESC_NUM: &[u8] = b"\x1b[35m";
- const ESC_KEYWORD: &[u8] = b"\x1b[33m";
- fn main() -> Result<(), Box<dyn Error>> {
- // let start = Instant::now();
- // let mut tick = Instant::now();
- let mut input_buf = Vec::with_capacity(8 * 1024);
- io::stdin().read_to_end(&mut input_buf).unwrap();
- let mut input = &input_buf[..];
- let mut output = Vec::with_capacity(input.len() * 2);
- let mut cur_col = ESC_DEFAULT;
- let mut set_color = move |col: &'static [u8], output: &mut Vec<u8>| {
- if col.as_ptr() != cur_col.as_ptr() {
- output.write_all(col).unwrap();
- cur_col = col;
- }
- };
- // eprintln!("Read: {:.2}ms", tick.elapsed().as_nanos() as f32 / 1000.0); tick = Instant::now();
- loop {
- match input {
- &[b'\t' | b'\n' | b'\r' | b' ', ..] => {
- input = split_and_output(input, |c| !matches!(c, b'\t' | b'\n' | b'\r' | b' '), false, &mut output);
- },
- &[terminator @ (b'"' | b'\''), ..] => {
- set_color(ESC_STR, &mut output);
- let mut escape = true;
- input = split_and_output(input, move |c| {
- if escape {
- escape = false;
- false
- } else if c == b'\\' {
- escape = true;
- false
- } else {
- c == terminator
- }
- }, true, &mut output);
- }
- &[b'0', b'x' | b'X', ..] => {
- set_color(ESC_NUM, &mut output);
- output.write_all(&input[0..2]).unwrap();
- input = &input[2..];
- input = split_and_output(input, |c| !matches!(c, b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'), false, &mut output);
- },
- &[b'0', ..] => {
- set_color(ESC_NUM, &mut output);
- input = split_and_output(input, |c| !matches!(c, b'0'..=b'7'), false, &mut output);
- },
- &[b'1'..=b'9', ..] => {
- set_color(ESC_NUM, &mut output);
- input = split_and_output(input, |c| !matches!(c, b'0'..=b'9'), false, &mut output);
- },
- &[b'/', b'/', ..] => {
- set_color(ESC_COMMENT, &mut output);
- input = split_and_output(input, |c| c == b'\n', false, &mut output);
- },
- &[b'/', b'*', ..] => {
- set_color(ESC_COMMENT, &mut output);
- let mut last = b'/';
- input = split_and_output(input, move |c| if last == b'*' && c == b'/' { true } else { last = c; false }, true, &mut output);
- },
- &[b'a'..=b'z' | b'A'..=b'Z' | b'_', ..] => {
- let (token, rest) = input.split_at(input.iter()
- .position(|&c| !matches!(c, b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_'))
- .unwrap_or(input.len()));
- match token {
- b"auto" | b"double" | b"int" | b"struct" |
- b"break" | b"else" | b"long" | b"switch" |
- b"case" | b"enum" | b"register" | b"typedef" |
- b"char" | b"extern" | b"return" | b"union" |
- b"const" | b"float" | b"short" | b"unsigned" |
- b"continue" | b"for" | b"signed" | b"void" |
- b"default" | b"goto" | b"sizeof" | b"volatile" |
- b"do" | b"if" | b"static" | b"while" => {
- set_color(ESC_KEYWORD, &mut output);
- }
- _ => {
- set_color(ESC_DEFAULT, &mut output);
- }
- }
- output.write_all(token).unwrap();
- input = rest;
- },
- [c, rest @ ..] => {
- set_color(ESC_SYMBOL, &mut output);
- output.write_all(&[*c]).unwrap();
- input = rest;
- },
- &[] => break,
- }
- }
- // eprintln!("Parse: {:.2}ms", tick.elapsed().as_nanos() as f32 / 1000.0); tick = Instant::now();
- io::stdout().write_all(&output).unwrap();
- // eprintln!("Out: {:.2}ms", tick.elapsed().as_nanos() as f32 / 1000.0);
- // eprintln!("Total: {:.2}ms", start.elapsed().as_nanos() as f32 / 1000.0);
- Ok(())
- }
- #[inline(always)]
- fn split_and_output<F>(slice: &[u8], pred: F, inclusive: bool, mut output: impl Write) -> &[u8]
- where F: FnMut(u8) -> bool {
- let (token, rest) = slice.split_at(slice.iter()
- .copied()
- .position(pred)
- .map(|pos| if inclusive { pos + 1 } else { pos })
- .unwrap_or(slice.len()));
- debug_assert!(!token.is_empty());
- output.write_all(token).unwrap();
- rest
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement