working initial interpreter

parent 434ecfc0
......@@ -17,10 +17,11 @@ version = "0.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "phuncomp"
version = "0.1.0"
name = "lazy_static"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"plex 0.2.3 (git+https://github.com/goffrie/plex)",
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
......@@ -35,6 +36,15 @@ dependencies = [
"syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "prakda-compiler"
version = "0.1.0"
dependencies = [
"lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"plex 0.2.3 (git+https://github.com/goffrie/plex)",
"text_io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "proc-macro2"
version = "0.4.20"
......@@ -70,6 +80,11 @@ dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "text_io"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicode-xid"
version = "0.1.0"
......@@ -80,14 +95,22 @@ name = "vec_map"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "version_check"
version = "0.1.5"
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 lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7"
"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 text_io 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9658b61ebd1d2a40c276ba2335890b9eb6550b67458a6fbce2022e58c3350a50"
"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"
"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
[package]
name = "phuncomp"
name = "prakda-compiler"
version = "0.1.0"
authors = ["Phuntsok Drak-pa <phundrak@phundrak.fr>"]
edition = "2018"
[dependencies]
text_io = "0.1.7"
lazy_static = "1.1.0"
plex = {git = "https://github.com/goffrie/plex"}
#![feature(proc_macro_gen)]
extern crate plex;
#[macro_use]
extern crate text_io;
use std::io::Read;
use std::collections::HashMap;
mod lexer {
use plex::lexer;
......@@ -11,32 +13,47 @@ mod lexer {
Ident(String), // string
Print, // print
Make, // make
Exit, // exit // TODO: make it interpreter only
Integer(i64), // int
Equals, // =
Plus, // +
Minus, // -
Star, // *
Slash, // /
LParen, // (
RParen, // )
Semi, // ;
Int, // int type
Integer(i64), // litteral integer
Equals, // =
Plus, // +
Minus, // -
Star, // *
Slash, // /
LParen, // (
RParen, // )
Semi, // ;
Assign, // <-
Fargs, // :
Whitespace, // self-described
Comment, // /* */ w/o nest
Comment, // /* */ w/o nest
}
lexer! {
fn next_token(text: 'a) -> (Token, &'a str);
// detects whitespace
// whitespace /////////////////////////////////////////////////////////
r#"[ \t\r\n]+"# => (Token::Whitespace, text),
// comments ///////////////////////////////////////////////////////////
// "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
// native keywords ////////////////////////////////////////////////////
r#"print"# => (Token::Print, text), // `print`
r#"make"# => (Token::Make, text), // `make`
r#"int"# => (Token::Int, text), // `int`
r#"exit"# => (Token::Exit, text), // `exit`
// numbers ////////////////////////////////////////////////////////////
// detects a litteral integer
// can end with an `i`
r#"[0-9]+"# => {
(if let Ok(i) = text.parse() {
Token::Integer(i)
......@@ -44,25 +61,24 @@ mod lexer {
panic!("integer {} is out of range", text)
}, text)
}
// strings ////////////////////////////////////////////////////////////
// detects a string
r#"[a-zA-Z_][a-zA-Z0-9_]*"# => (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
// symbols ////////////////////////////////////////////////////////////
r#"<-"# => (Token::Assign, text), // <-
r#":"# => (Token::Fargs, text), // :
r#"="# => (Token::Equals, text), // =
r#"\+"# => (Token::Plus, text), // +
r#"-"# => (Token::Minus, text), // -
r#"\*"# => (Token::Star, text), // *
r#"/"# => (Token::Slash, text), // /
r#"\("# => (Token::LParen, text), // (
r#"\)"# => (Token::RParen, text), // )
r#";"# => (Token::Semi, text), // ;
// if any other char //////////////////////////////////////////////////
r#"."# => panic!("unexpected character: {}", text),
}
......@@ -144,6 +160,8 @@ mod ast {
Assign(String, Box<Expr>),
Print(Box<Expr>),
Literal(i64),
#[allow(dead_code)]
Exit,
}
}
......@@ -176,11 +194,11 @@ mod parser {
}
assign: Expr {
Print assign[a] => Expr {
Print Fargs assign[a] => Expr {
span: span!(),
node: Expr_::Print(Box::new(a)),
},
Ident(var) Equals assign[rhs] => Expr {
Make Ident(var) Assign assign[rhs] => Expr {
span: span!(),
node: Expr_::Assign(var, Box::new(rhs)),
},
......@@ -236,13 +254,12 @@ mod interp {
use crate::ast::*;
use std::collections::HashMap;
pub fn interp<'a>(p: &'a Program) {
let mut env = HashMap::new();
pub fn interp(p: Program, mut env: &mut HashMap<String, i64>) {
for expr in &p.stmts {
interp_expr(&mut env, expr);
}
}
fn interp_expr<'a>(env: &mut HashMap<&'a str, i64>, expr: &'a Expr) -> i64 {
fn interp_expr(env: &mut HashMap<String, i64>, expr: &Expr) -> i64 {
use crate::ast::Expr_::*;
match expr.node {
Add(ref a, ref b) => interp_expr(env, a) + interp_expr(env, b),
......@@ -251,7 +268,7 @@ mod interp {
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);
env.insert(var.to_string(), val);
val
}
Var(ref var) => *env.get(&var[..]).unwrap(),
......@@ -260,15 +277,29 @@ mod interp {
let val = interp_expr(env, e);
println!("{}", val);
val
},
Exit => {
::std::process::exit(0);
}
}
}
}
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);
use std::io::{self, Write};
let mut env // : HashMap<&str, i64>
= HashMap::new();
let mut i: usize = 0;
loop {
i += 1;
print!("{:5} > ", i);
io::stdout().flush().unwrap();
let s: String = read!("{}\n");
if s == "exit;" {
println!("Goodbye!");
break;
}
let lexer = lexer::Lexer::new(&s).inspect(|tok| eprintln!("tok: {:?}", tok));
interp::interp(parser::parse(lexer).unwrap(), &mut env);
}
}
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