Advertisement
funmaker

Untitled

Dec 5th, 2024
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 5.40 KB | None | 0 0
  1. use std::error::Error;
  2. use std::io::{self, Read, Write};
  3. #[allow(unused_imports)] use std::time::Instant;
  4.  
  5. const ESC_DEFAULT: &[u8] = b"\x1b[0m";
  6. const ESC_COMMENT: &[u8] = b"\x1b[90m";
  7. const ESC_SYMBOL: &[u8] = b"\x1b[36m";
  8. const ESC_STR: &[u8] = b"\x1b[32m";
  9. const ESC_NUM: &[u8] = b"\x1b[35m";
  10. const ESC_KEYWORD: &[u8] = b"\x1b[33m";
  11.  
  12. fn main() -> Result<(), Box<dyn Error>> {
  13.     // let start = Instant::now();
  14.     // let mut tick = Instant::now();
  15.    
  16.     let mut input_buf = Vec::with_capacity(8 * 1024);
  17.     io::stdin().read_to_end(&mut input_buf).unwrap();
  18.     let mut input = &input_buf[..];
  19.     let mut output = Vec::with_capacity(input.len() * 2);
  20.    
  21.     let mut cur_col = ESC_DEFAULT;
  22.     let mut set_color = move |col: &'static [u8], output: &mut Vec<u8>| {
  23.        if col.as_ptr() != cur_col.as_ptr() {
  24.            output.write_all(col).unwrap();
  25.            cur_col = col;
  26.        }
  27.    };
  28.    
  29.    // eprintln!("Read: {:.2}ms", tick.elapsed().as_nanos() as f32 / 1000.0); tick = Instant::now();
  30.    
  31.    loop {
  32.        match input {
  33.            &[b'\t' | b'\n' | b'\r' | b' ', ..] => {
  34.                input = split_and_output(input, |c| !matches!(c, b'\t' | b'\n' | b'\r' | b' '), false, &mut output);
  35.            },
  36.            &[terminator @ (b'"' | b'\''), ..] => {
  37.                set_color(ESC_STR, &mut output);
  38.                let mut escape = true;
  39.                input = split_and_output(input, move |c| {
  40.                    if escape {
  41.                        escape = false;
  42.                        false
  43.                    } else if c == b'\\' {
  44.                        escape = true;
  45.                        false
  46.                    } else {
  47.                        c == terminator
  48.                    }
  49.                }, true, &mut output);
  50.            }
  51.            &[b'0', b'x' | b'X', ..] => {
  52.                set_color(ESC_NUM, &mut output);
  53.                output.write_all(&input[0..2]).unwrap();
  54.                input = &input[2..];
  55.                input = split_and_output(input, |c| !matches!(c, b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F'), false, &mut output);
  56.            },
  57.            &[b'0', ..] => {
  58.                set_color(ESC_NUM, &mut output);
  59.                input = split_and_output(input, |c| !matches!(c, b'0'..=b'7'), false, &mut output);
  60.            },
  61.            &[b'1'..=b'9', ..] => {
  62.                set_color(ESC_NUM, &mut output);
  63.                input = split_and_output(input, |c| !matches!(c, b'0'..=b'9'), false, &mut output);
  64.            },
  65.            &[b'/', b'/', ..] => {
  66.                set_color(ESC_COMMENT, &mut output);
  67.                input = split_and_output(input, |c| c == b'\n', false, &mut output);
  68.            },
  69.            &[b'/', b'*', ..] => {
  70.                set_color(ESC_COMMENT, &mut output);
  71.                let mut last = b'/';
  72.                input = split_and_output(input, move |c| if last == b'*' && c == b'/' { true } else { last = c; false }, true, &mut output);
  73.            },
  74.            &[b'a'..=b'z' | b'A'..=b'Z' | b'_', ..] => {
  75.                let (token, rest) = input.split_at(input.iter()
  76.                                                        .position(|&c| !matches!(c, b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_'))
  77.                                                        .unwrap_or(input.len()));
  78.                
  79.                match token {
  80.                    b"auto"     | b"double" | b"int"      | b"struct"   |
  81.                    b"break"    | b"else"   | b"long"     | b"switch"   |
  82.                    b"case"     | b"enum"   | b"register" | b"typedef"  |
  83.                    b"char"     | b"extern" | b"return"   | b"union"    |
  84.                    b"const"    | b"float"  | b"short"    | b"unsigned" |
  85.                    b"continue" | b"for"    | b"signed"   | b"void"     |
  86.                    b"default"  | b"goto"   | b"sizeof"   | b"volatile" |
  87.                    b"do"       | b"if"     | b"static"   | b"while"    => {
  88.                        set_color(ESC_KEYWORD, &mut output);
  89.                    }
  90.                    _ => {
  91.                        set_color(ESC_DEFAULT, &mut output);
  92.                    }
  93.                }
  94.                
  95.                output.write_all(token).unwrap();
  96.                input = rest;
  97.            },
  98.            [c, rest @ ..] => {
  99.                set_color(ESC_SYMBOL, &mut output);
  100.                output.write_all(&[*c]).unwrap();
  101.                input = rest;
  102.            },
  103.            &[] => break,
  104.        }
  105.    }
  106.    
  107.    // eprintln!("Parse: {:.2}ms", tick.elapsed().as_nanos() as f32 / 1000.0); tick = Instant::now();
  108.    
  109.    io::stdout().write_all(&output).unwrap();
  110.    
  111.    // eprintln!("Out: {:.2}ms", tick.elapsed().as_nanos() as f32 / 1000.0);
  112.    // eprintln!("Total: {:.2}ms", start.elapsed().as_nanos() as f32 / 1000.0);
  113.    
  114.    Ok(())
  115. }
  116.  
  117. #[inline(always)]
  118. fn split_and_output<F>(slice: &[u8], pred: F, inclusive: bool, mut output: impl Write) -> &[u8]
  119. where F: FnMut(u8) -> bool {
  120.    let (token, rest) = slice.split_at(slice.iter()
  121.                                            .copied()
  122.                                            .position(pred)
  123.                                            .map(|pos| if inclusive { pos + 1 } else { pos })
  124.                                            .unwrap_or(slice.len()));
  125.    debug_assert!(!token.is_empty());
  126.    output.write_all(token).unwrap();
  127.    rest
  128. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement