Files @ fc987660fdee
Branch filter:

Location: CSY/reowolf/src/protocol/inputsource.rs - annotation

fc987660fdee 8.5 KiB application/rls-services+xml Show Source Show as Raw Download as Raw
MH
WIP on compiler rearchitecting
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
03af3095927d
06f259bf8031
33ea10021de4
33ea10021de4
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
4c844c3751d1
a22ee3898fc1
6717437470eb
4c844c3751d1
a22ee3898fc1
6717437470eb
4c844c3751d1
a22ee3898fc1
4c844c3751d1
6717437470eb
6717437470eb
4c844c3751d1
4c844c3751d1
a22ee3898fc1
b972060a1f92
b972060a1f92
b972060a1f92
b972060a1f92
b972060a1f92
b972060a1f92
4c844c3751d1
4c844c3751d1
a22ee3898fc1
4c844c3751d1
7f75e1f23836
7f75e1f23836
4c844c3751d1
fbd1526bae2c
fbd1526bae2c
4c844c3751d1
06f259bf8031
06f259bf8031
dedf89df1602
fbd1526bae2c
06f259bf8031
ddacf35e9373
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
06f259bf8031
06f259bf8031
06f259bf8031
36d5a586a102
06f259bf8031
06f259bf8031
36d5a586a102
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
36d5a586a102
06f259bf8031
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
06f259bf8031
36d5a586a102
36d5a586a102
36d5a586a102
36d5a586a102
06f259bf8031
06f259bf8031
36d5a586a102
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
03af3095927d
06f259bf8031
33aa370aeb00
33aa370aeb00
33aa370aeb00
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
aaeaf5986496
aaeaf5986496
aaeaf5986496
aaeaf5986496
aaeaf5986496
06f259bf8031
06f259bf8031
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
06f259bf8031
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
6ec2e0261a03
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
06f259bf8031
33ea10021de4
06f259bf8031
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
06f259bf8031
33ea10021de4
06f259bf8031
33ea10021de4
33ea10021de4
06f259bf8031
33ea10021de4
33ea10021de4
06f259bf8031
33ea10021de4
06f259bf8031
06f259bf8031
06f259bf8031
33ea10021de4
c87205ed6292
aaeaf5986496
06f259bf8031
06f259bf8031
c87205ed6292
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
06f259bf8031
06f259bf8031
06f259bf8031
c87205ed6292
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
06f259bf8031
06f259bf8031
use std::fmt;
use std::fs::File;
use std::io;
use std::path::Path;

use backtrace::Backtrace;

#[derive(Debug, Clone)]
pub struct InputSource {
    pub(crate) filename: String,
    pub(crate) input: Vec<u8>,
    line: usize,
    column: usize,
    offset: usize,
}

static STD_LIB_PDL: &'static [u8] = b"
primitive forward(in<msg> i, out<msg> o) {
    while(true) synchronous put(o, get(i));
}
primitive sync(in<msg> i, out<msg> o) {
    while(true) synchronous if(fires(i)) put(o, get(i));
}
primitive alternator(in<msg> i, out<msg> l, out<msg> r) {
    while(true) {
        synchronous if(fires(i)) put(l, get(i));
        synchronous if(fires(i)) put(r, get(i));
    }
}
primitive replicator(in<msg> i, out<msg> l, out<msg> r) {
    while(true) synchronous {
        if(fires(i)) {
            msg m = get(i);
            put(l, m);
            put(r, m);
        }
    }
}
primitive merger(in<msg> l, in<msg> r, out<msg> o) {
    while(true) synchronous {
        if(fires(l))      put(o, get(l));
        else if(fires(r)) put(o, get(r));
    }
}
";

impl InputSource {
    // Constructors
    pub fn new<R: io::Read, S: ToString>(filename: S, reader: &mut R) -> io::Result<InputSource> {
        let mut vec = Vec::new();
        reader.read_to_end(&mut vec)?;
        vec.extend(STD_LIB_PDL.to_vec());
        Ok(InputSource {
            filename: filename.to_string(),
            input: vec,
            line: 1,
            column: 1,
            offset: 0,
        })
    }
    // Constructor helpers
    pub fn from_file(path: &Path) -> io::Result<InputSource> {
        let filename = path.file_name();
        match filename {
            Some(filename) => {
                let mut f = File::open(path)?;
                InputSource::new(filename.to_string_lossy(), &mut f)
            }
            None => Err(io::Error::new(io::ErrorKind::NotFound, "Invalid path")),
        }
    }
    pub fn from_string(string: &str) -> io::Result<InputSource> {
        let buffer = Box::new(string);
        let mut bytes = buffer.as_bytes();
        InputSource::new(String::new(), &mut bytes)
    }
    pub fn from_buffer(buffer: &[u8]) -> io::Result<InputSource> {
        InputSource::new(String::new(), &mut Box::new(buffer))
    }
    // Internal methods
    pub fn pos(&self) -> InputPosition {
        InputPosition { line: self.line, column: self.column, offset: self.offset }
    }
    pub fn seek(&mut self, pos: InputPosition) {
        debug_assert!(pos.offset < self.input.len());
        self.line = pos.line;
        self.column = pos.column;
        self.offset = pos.offset;
    }
    pub fn is_eof(&self) -> bool {
        self.next() == None
    }

    pub fn next(&self) -> Option<u8> {
        if self.offset < self.input.len() {
            Some(self.input[self.offset])
        } else {
            None
        }
    }

    pub fn lookahead(&self, pos: usize) -> Option<u8> {
        let offset_pos = self.offset + pos;
        if offset_pos < self.input.len() {
            Some(self.input[offset_pos])
        } else {
            None
        }
    }

    pub fn has(&self, to_compare: &[u8]) -> bool {
        if self.offset + to_compare.len() <= self.input.len() {
            for idx in 0..to_compare.len() {
                if to_compare[idx] != self.input[self.offset + idx] {
                    return false;
                }
            }

            true
        } else {
            false
        }
    }

    pub fn consume(&mut self) {
        match self.next() {
            Some(x) if x == b'\r' && self.lookahead(1) != Some(b'\n') || x == b'\n' => {
                self.line += 1;
                self.offset += 1;
                self.column = 1;
            }
            Some(_) => {
                self.offset += 1;
                self.column += 1;
            }
            None => {}
        }
    }
}

impl fmt::Display for InputSource {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.pos().fmt(f)
    }
}

#[derive(Debug, Clone, Copy)]
pub struct InputPosition {
    pub line: usize,
    pub column: usize,
    pub offset: usize,
}

impl InputPosition {
    fn context<'a>(&self, source: &'a InputSource) -> &'a [u8] {
        let start = self.offset - (self.column - 1);
        let mut end = self.offset;
        while end < source.input.len() {
            let cur = (*source.input)[end];
            if cur == b'\n' || cur == b'\r' {
                break;
            }
            end += 1;
        }
        &source.input[start..end]
    }
}

impl Default for InputPosition {
    fn default() -> Self {
        Self{ line: 1, column: 1, offset: 0 }
    }
}

impl fmt::Display for InputPosition {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}:{}", self.line, self.column)
    }
}

#[derive(Debug)]
pub enum ParseErrorType {
    Info,
    Error
}

#[derive(Debug)]
pub struct ParseErrorStatement {
    pub(crate) error_type: ParseErrorType,
    pub(crate) position: InputPosition,
    pub(crate) filename: String,
    pub(crate) context: String,
    pub(crate) message: String,
}

impl ParseErrorStatement {
    fn from_source(error_type: ParseErrorType, source: &InputSource, position: InputPosition, msg: &str) -> Self {
        // Seek line start and end
        let line_start = position.offset - (position.column - 1);
        let mut line_end = position.offset;
        while line_end < source.input.len() && source.input[line_end] != b'\n' {
            line_end += 1;
        }

        // Compensate for '\r\n'
        if line_end > line_start && source.input[line_end - 1] == b'\r' {
            line_end -= 1;
        }

        Self{
            error_type,
            position,
            filename: source.filename.clone(),
            context: String::from_utf8_lossy(&source.input[line_start..line_end]).to_string(),
            message: msg.to_string()
        }
    }
}

impl fmt::Display for ParseErrorStatement {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Write message
        match self.error_type {
            ParseErrorType::Info => write!(f, " INFO: ")?,
            ParseErrorType::Error => write!(f, "ERROR: ")?,
        }
        writeln!(f, "{}", &self.message)?;

        // Write originating file/line/column
        if self.filename.is_empty() {
            writeln!(f, " +- at {}:{}", self.position.line, self.position.column)?;
        } else {
            writeln!(f, " +- at {}:{}:{}", self.filename, self.position.line, self.position.column)?;
        }

        // Write source context
        writeln!(f, " | ")?;
        writeln!(f, " | {}", self.context)?;

        // Write underline indicating where the error ocurred
        debug_assert!(self.position.column <= self.context.chars().count());
        let mut arrow = String::with_capacity(self.context.len() + 3);
        arrow.push_str(" | ");
        let mut char_col = 1;
        for char in self.context.chars() {
            if char_col == self.position.column { break; }
            if char == '\t' {
                arrow.push('\t');
            } else {
                arrow.push(' ');
            }

            char_col += 1;
        }
        arrow.push('^');
        writeln!(f, "{}", arrow)?;

        Ok(())
    }
}

#[derive(Debug)]
pub struct ParseError {
    pub(crate) statements: Vec<ParseErrorStatement>
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if self.statements.is_empty() {
            return Ok(())
        }

        self.statements[0].fmt(f)?;
        for statement in self.statements.iter().skip(1) {
            writeln!(f)?;
            statement.fmt(f)?;
        }

        Ok(())
    }
}

impl ParseError {
    pub fn empty() -> Self {
        Self{ statements: Vec::new() }
    }

    pub fn new_error(source: &InputSource, position: InputPosition, msg: &str) -> Self {
        Self{ statements: vec!(ParseErrorStatement::from_source(ParseErrorType::Error, source, position, msg))}
    }

    pub fn with_prefixed(mut self, error_type: ParseErrorType, source: &InputSource, position: InputPosition, msg: &str) -> Self {
        self.statements.insert(0, ParseErrorStatement::from_source(error_type, source, position, msg));
        self
    }

    pub fn with_postfixed(mut self, error_type: ParseErrorType, source: &InputSource, position: InputPosition, msg: &str) -> Self {
        self.statements.push(ParseErrorStatement::from_source(error_type, source, position, msg));
        self
    }

    pub fn with_postfixed_info(self, source: &InputSource, position: InputPosition, msg: &str) -> Self {
        self.with_postfixed(ParseErrorType::Info, source, position, msg)
    }
}