slj 0.6.6

Programski jezik v slovenščini | A programming language in Slovenian
Documentation
pub mod drevo;
pub mod tokenizer;
pub mod tip;
pub mod napaka;

mod loci;
mod operatorji;
mod predprocesiraj;
mod okvir;
mod stavek;
mod funkcija;
mod izraz;
mod argumenti;

use std::{collections::HashMap, rc::Rc, iter};
use rand::{distributions::Alphanumeric, Rng};

use drevo::{Drevo, Vozlišče::{*, self}, VozliščeOption::*};
use tip::Tip;
use tokenizer::{Token::{*, self}, L, Tokenize};
use loci::*;

use self::napaka::{Napake, OznakaNapake::*, Napaka};
use self::operatorji::*;

#[derive(Debug)]
struct Parser<'a> {
    spremenljivke_stack: Vec<HashMap<String, Rc<Vozlišče>>>,
    spremenljivke: HashMap<String, Rc<Vozlišče>>,
    funkcije_stack: Vec<HashMap<String, Rc<Vozlišče>>>,
    funkcije: HashMap<String, Rc<Vozlišče>>,
    št_klicev: HashMap<String, usize>,
    reference_stack: Vec<HashMap<&'a str, Rc<Vozlišče>>>,
    reference: HashMap<&'a str, Rc<Vozlišče>>,
    znotraj_funkcije: bool,
}

pub trait Parse {
    fn parse(&self) -> Result<Drevo, Napake>;
}

impl Parse for Vec<Token<'_>> {
    fn parse(&self) -> Result<Drevo, Napake> {
        Parser::new().parse(self)
    }
}


impl<'a> Parser<'a> {
    fn new() -> Parser<'a> {
        Parser { 
            spremenljivke_stack: vec![],
            funkcije_stack: vec![],
            reference_stack: vec![],
            spremenljivke: HashMap::new(),
            funkcije: HashMap::new(),
            št_klicev: HashMap::new(),
            reference: HashMap::new(),
            znotraj_funkcije: false,
        }
    }

    fn parse(&mut self, izraz: &[Token<'a>]) -> Result<Drevo, Napake> {
        let izraz = [
            Self::standard().as_slice(),
            &[Ločilo("\n", 0, 0)],
            &Parser::predprocesiraj(izraz),
        ].concat();
        let okvir = self.okvir(izraz.as_slice())?;
        Ok(Drevo::new(okvir, self.št_klicev.clone()))
    }

    fn standard() -> Vec<Token<'static>> {
        const MATEMATIKA: &str = include_str!("../../standard/matematika.slj");
        const NATISNI: &str = include_str!("../../standard/natisni.slj");
        const PREBERI: &str = include_str!("../../standard/preberi.slj");
        [
            Parser::predprocesiraj(&MATEMATIKA.tokenize()).as_slice(),
            &[Ločilo("\n", 0, 0)],
            Parser::predprocesiraj(&NATISNI.tokenize()).as_slice(),
            &[Ločilo("\n", 0, 0)],
            &Parser::predprocesiraj(&PREBERI.tokenize()),
            &[Ločilo("\n", 0, 0)],
        ].concat()
    }

    fn dodaj_spremenljivko(&mut self, ime: String, tip: Tip) -> Rc<Vozlišče> {
        let naslov = match self.znotraj_funkcije {
            true  => self.spremenljivke_stack.last().unwrap().values().map(|s| s.sprememba_stacka()).sum(),
            false => self.spremenljivke.values().map(|s| s.sprememba_stacka()).sum(),
        };
        let spr = Spremenljivka { tip, ime: ime.clone(), naslov, z_odmikom: self.znotraj_funkcije }.rc();
        self.spremenljivke_stack.last_mut().unwrap().insert(ime.clone(), spr.clone());
        self.spremenljivke.insert(ime, spr.clone());
        spr
    }

    fn naključno_ime(&self, dolžina: usize) -> String {
        let mut ime = rand::thread_rng()
            .sample_iter(&Alphanumeric)
            .take(dolžina)
            .map(char::from)
            .collect();

        while self.spremenljivke.contains_key(&ime) {
            ime = rand::thread_rng()
                .sample_iter(&Alphanumeric)
                .take(dolžina)
                .map(char::from)
                .collect();
        }

        ime
    }
}