initial commit

parents
*~
/target
**/*.rs.bk
[[package]]
name = "bit-set"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bit-vec"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lalr"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "phuncomp"
version = "0.1.0"
dependencies = [
"plex 0.2.3 (git+https://github.com/goffrie/plex)",
]
[[package]]
name = "plex"
version = "0.2.3"
source = "git+https://github.com/goffrie/plex#b05babde6a60a45bae7e06a10a84487caa734be1"
dependencies = [
"lalr 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"redfa 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro2"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "redfa"
version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.14.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "vec_map"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c"
"checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
"checksum lalr 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "106d7548f95adbe3019b4fc4954554d7b72535867aa9ce326d2f766b68958de7"
"checksum plex 0.2.3 (git+https://github.com/goffrie/plex)" = "<none>"
"checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee"
"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5"
"checksum redfa 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "29cc2771cc9f5fb0061cdedc05a37170254694dffec6b89920a6e767f08c4220"
"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum vec_map 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cac5efe5cb0fa14ec2f84f83c701c562ee63f6dcc680861b21d65c682adfb05f"
[package]
name = "phuncomp"
version = "0.1.0"
authors = ["Phuntsok Drak-pa <phundrak@phundrak.fr>"]
edition = "2018"
[dependencies]
plex = {git = "https://github.com/goffrie/plex"}
#![feature(proc_macro_gen)]
extern crate plex;
use std::io::Read;
mod lexer {
use plex::lexer;
#[derive(Debug, Clone)]
pub enum Token {
Ident(String), // string
Print, // print
Integer(i64), // int
Equals, // =
Plus, // +
Minus, // -
Star, // *
Slash, // /
LParen, // (
RParen, // )
Semi, // ;
Whitespace, // self-described
Comment, // /* */ w/o nest
}
lexer! {
fn next_token(text: 'a) -> (Token, &'a str);
// detects whitespace
r#"[ \t\r\n]+"# => (Token::Whitespace, text),
// "C-style" comments (/* .. */) - can't contain "*/"
r#"/[*](~(.*[*]/.*))[*]/"# => (Token::Comment, text),
// "C++-style" comments (// ...)
r#"//[^\n]*"# => (Token::Comment, text),
// detects the "print" token
r#"print"# => (Token::Print, text),
// detects an int
r#"[0-9]+"# => {
(if let Ok(i) = text.parse() {
Token::Integer(i)
} else {
panic!("integer {} is out of range", text)
}, text)
}
// detects a string
r#"[a-zA-Z\u00C0-\u017F_][a-zA-Z0-9\u00C0-\u017F_]*"# => (Token::Ident(text.to_owned()), text),
// detects a =
r#"="# => (Token::Equals, text),
// detects a +
r#"\+"# => (Token::Plus, text),
// detects a -
r#"-"# => (Token::Minus, text),
// detects a *
r#"\*"# => (Token::Star, text),
// detects a /
r#"/"# => (Token::Slash, text),
// detects a (
r#"\("# => (Token::LParen, text),
// detects a )
r#"\)"# => (Token::RParen, text),
// detects a ;
r#";"# => (Token::Semi, text),
// if any other char
r#"."# => panic!("unexpected character: {}", text),
}
pub struct Lexer<'a> {
original: &'a str,
remaining: &'a str,
}
impl<'a> Lexer<'a> {
pub fn new(s: &'a str) -> Lexer<'a> {
Lexer {
original: s,
remaining: s,
}
}
}
// source location
#[derive(Debug, Clone, Copy)]
pub struct Span {
pub lo: usize,
pub hi: usize,
}
fn span_in(s: &str, t: &str) -> Span {
let lo = s.as_ptr() as usize - t.as_ptr() as usize;
Span {
lo: lo,
hi: lo + s.len(),
}
}
impl<'a> Iterator for Lexer<'a> {
type Item = (Token, Span);
fn next(&mut self) -> Option<(Token, Span)> {
loop {
let tok = if let Some((tok, new_remaining)) = next_token(self.remaining) {
self.remaining = new_remaining;
tok
} else {
return None;
};
match tok {
(Token::Whitespace, _) | (Token::Comment, _) => {
continue;
}
(tok, span) => {
return Some((tok, span_in(span, self.original)));
}
}
}
}
}
}
mod ast {
use lexer::Span;
// un Program est un vecteur d'expressions
#[derive(Debug)]
pub struct Program {
pub stmts: Vec<Expr>,
}
// Une expression est sa position et l'expression en elle-même
#[derive(Debug)]
pub struct Expr {
pub span: Span,
pub node: Expr_,
}
#[derive(Debug)]
pub enum Expr_ {
Add(Box<Expr>, Box<Expr>),
Sub(Box<Expr>, Box<Expr>),
Mul(Box<Expr>, Box<Expr>),
Div(Box<Expr>, Box<Expr>),
Var(String),
Assign(String, Box<Expr>),
Print(Box<Expr>),
Literal(i64),
}
}
mod parser {
use ast::*;
use lexer::Token::*;
use lexer::*;
use plex::parser;
parser! {
fn parse_(Token, Span);
// combine two spans
(a, b) {
Span {
lo: a.lo,
hi: b.hi,
}
}
program: Program {
statements[s] => Program { stmts: s }
}
statements: Vec<Expr> {
=> vec![],
statements[mut st] assign[e] Semi => {
st.push(e);
st
}
}
assign: Expr {
Print assign[a] => Expr {
span: span!(),
node: Expr_::Print(Box::new(a)),
},
Ident(var) Equals assign[rhs] => Expr {
span: span!(),
node: Expr_::Assign(var, Box::new(rhs)),
},
term[t] => t,
}
term: Expr {
term[lhs] Plus fact[rhs] => Expr {
span: span!(),
node: Expr_::Add(Box::new(lhs), Box::new(rhs)),
},
term[lhs] Minus fact[rhs] => Expr {
span: span!(),
node: Expr_::Sub(Box::new(lhs), Box::new(rhs)),
},
fact[x] => x
}
fact: Expr {
fact[lhs] Star atom[rhs] => Expr {
span: span!(),
node: Expr_::Mul(Box::new(lhs), Box::new(rhs)),
},
fact[lhs] Slash atom[rhs] => Expr {
span: span!(),
node: Expr_::Div(Box::new(lhs), Box::new(rhs)),
},
atom[x] => x
}
atom: Expr {
// round brackets to destructure tokens
Ident(i) => Expr {
span: span!(),
node: Expr_::Var(i),
},
Integer(i) => Expr {
span: span!(),
node: Expr_::Literal(i),
},
LParen assign[a] RParen => a
}
}
pub fn parse<I: Iterator<Item = (Token, Span)>>(
i: I,
) -> Result<Program, (Option<(Token, Span)>, &'static str)> {
parse_(i)
}
}
mod interp {
use ast::*;
use std::collections::HashMap;
pub fn interp<'a>(p: &'a Program) {
let mut env = HashMap::new();
for expr in &p.stmts {
interp_expr(&mut env, expr);
}
}
fn interp_expr<'a>(env: &mut HashMap<&'a str, i64>, expr: &'a Expr) -> i64 {
use ast::Expr_::*;
match expr.node {
Add(ref a, ref b) => interp_expr(env, a) + interp_expr(env, b),
Sub(ref a, ref b) => interp_expr(env, a) - interp_expr(env, b),
Mul(ref a, ref b) => interp_expr(env, a) * interp_expr(env, b),
Div(ref a, ref b) => interp_expr(env, a) / interp_expr(env, b),
Assign(ref var, ref b) => {
let val = interp_expr(env, b);
env.insert(var, val);
val
}
Var(ref var) => *env.get(&var[..]).unwrap(),
Literal(lit) => lit,
Print(ref e) => {
let val = interp_expr(env, e);
println!("{}", val);
val
}
}
}
}
fn main() {
let mut s = String::new();
std::io::stdin().read_to_string(&mut s).unwrap();
let lexer = lexer::Lexer::new(&s).inspect(|tok| eprintln!("tok: {:?}", tok));
let program = parser::parse(lexer).unwrap();
interp::interp(&program);
}
fn main() {
println!("Hello, world!");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment