Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
D
D7050E
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
martin
D7050E
Commits
be369876
Commit
be369876
authored
5 years ago
by
Per Lindgren
Browse files
Options
Downloads
Patches
Plain Diff
wip
parent
fee50aa2
No related branches found
No related tags found
No related merge requests found
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
examples/tmp.rs
+19
-3
19 additions, 3 deletions
examples/tmp.rs
src/ast.rs
+4
-3
4 additions, 3 deletions
src/ast.rs
src/interpreter.rs
+332
-0
332 additions, 0 deletions
src/interpreter.rs
src/lib.rs
+1
-0
1 addition, 0 deletions
src/lib.rs
src/parse.rs
+52
-81
52 additions, 81 deletions
src/parse.rs
with
408 additions
and
87 deletions
examples/tmp.rs
+
19
−
3
View file @
be369876
use
crust
::{
use
crust
::{
ast
::
Span
,
ast
::
Span
,
parse
::{
parse_assign
,
test
},
parse
::{
parse_assign
,
parse_expr
},
interpreter
::{
eval_expr
}
};
};
fn
test
(
s
:
&
str
,
v
:
i32
)
{
match
parse_expr
(
Span
::
new
(
s
))
{
Ok
((
Span
{
fragment
:
""
,
..
},
e
))
=>
{
println!
(
"{:?}"
,
&
e
);
println!
(
"eval {} {}"
,
eval_expr
(
&
e
),
v
);
assert_eq!
(
eval_expr
(
&
e
),
v
);
}
Ok
((
s
,
t
))
=>
println!
(
"parse incomplete,
\n
parsed tokens
\t
{:?},
\n
remaining
\t
{:?}"
,
t
,
s
),
Err
(
err
)
=>
println!
(
"{:?}"
,
err
),
}
}
fn
main
()
{
fn
main
()
{
// test("- -1 + + 1", - -1 + 1); // rust does not allow + as a unary op (I do ;)
// test("- -1 + + 1", - -1 + 1); // rust does not allow + as a unary op (I do ;)
// test("(-1-1)+(-1+3)", (-1 - 1) + (-1) + 3);
// test("(-1-1)+(-1+3)", (-1 - 1) + (-1) + 3);
...
@@ -12,6 +28,6 @@ fn main() {
...
@@ -12,6 +28,6 @@ fn main() {
// test("1*2+3", 1 * 2 + 3);
// test("1*2+3", 1 * 2 + 3);
// // just to check that we get a parse error
// // just to check that we get a parse error
// test("1*2+3+3*21-a12+2", 1 * 2 + 3 + 3 * 21 - 12 + 2);
// test("1*2+3+3*21-a12+2", 1 * 2 + 3 + 3 * 21 - 12 + 2);
test
(
"1 +
a
(1
,
2)"
,
1
+
2
);
test
(
"1 + (1
-
2)"
,
1
+
(
1
-
2
)
);
println!
(
"{:?}"
,
parse_assign
(
Span
::
new
(
"3 =
4
"
)));
println!
(
"{:?}"
,
parse_assign
(
Span
::
new
(
"3 =
a(1, 2+3)
"
)));
}
}
This diff is collapsed.
Click to expand it.
src/ast.rs
+
4
−
3
View file @
be369876
...
@@ -26,7 +26,7 @@ pub enum Expr<'a> {
...
@@ -26,7 +26,7 @@ pub enum Expr<'a> {
Bool
(
bool
),
Bool
(
bool
),
Par
(
Box
<
SpanExpr
<
'a
>>
),
Par
(
Box
<
SpanExpr
<
'a
>>
),
Id
(
String
),
Id
(
String
),
Fn
(
String
,
Vec
<
SpanExpr
<
'a
>>
),
Call
(
String
,
Vec
<
SpanExpr
<
'a
>>
),
BinOp
(
Op
,
Box
<
SpanExpr
<
'a
>>
,
Box
<
SpanExpr
<
'a
>>
),
BinOp
(
Op
,
Box
<
SpanExpr
<
'a
>>
,
Box
<
SpanExpr
<
'a
>>
),
UnaryOp
(
Op
,
Box
<
SpanExpr
<
'a
>>
),
UnaryOp
(
Op
,
Box
<
SpanExpr
<
'a
>>
),
}
}
...
@@ -39,8 +39,8 @@ pub enum Cmd<'a> {
...
@@ -39,8 +39,8 @@ pub enum Cmd<'a> {
Let
(
SpanMut
<
'a
>
,
String
,
SpanType
<
'a
>
,
SpanExpr
<
'a
>
),
Let
(
SpanMut
<
'a
>
,
String
,
SpanType
<
'a
>
,
SpanExpr
<
'a
>
),
// id = expr
// id = expr
Assign
(
SpanExpr
<
'a
>
,
SpanExpr
<
'a
>
),
Assign
(
SpanExpr
<
'a
>
,
SpanExpr
<
'a
>
),
//
///
if predicate do-this, and optionally do-that)
// if predicate do-this, and optionally do-that)
// If(Expr,
Block, Option<Block>),
If
(
SpanExpr
<
'a
>
,
Span
Block
<
'a
>
,
Option
<
Span
Block
<
'a
>
>
),
// /// while predicate do-this
// /// while predicate do-this
// While(Expr, Block),
// While(Expr, Block),
// Return(Expr),
// Return(Expr),
...
@@ -70,6 +70,7 @@ pub type SpanMut<'a> = (Span<'a>, Mutability);
...
@@ -70,6 +70,7 @@ pub type SpanMut<'a> = (Span<'a>, Mutability);
// }
// }
pub
type
SpanBlock
<
'a
>
=
(
Span
<
'a
>
,
Vec
<
SpanCmd
<
'a
>>
);
pub
type
SpanBlock
<
'a
>
=
(
Span
<
'a
>
,
Vec
<
SpanCmd
<
'a
>>
);
pub
type
Block
<
'a
>
=
Vec
<
Cmd
<
'a
>>
;
#[derive(Debug,
PartialEq,
Clone)]
#[derive(Debug,
PartialEq,
Clone)]
pub
enum
Type
<
'a
>
{
pub
enum
Type
<
'a
>
{
...
...
This diff is collapsed.
Click to expand it.
src/interpreter.rs
0 → 100644
+
332
−
0
View file @
be369876
// Interpreter
use
crate
::
ast
::{
Expr
,
Op
,
SpanExpr
};
pub
fn
eval_expr
(
e
:
&
SpanExpr
)
->
i32
{
match
e
.clone
()
.1
{
Expr
::
Num
(
i
)
=>
i
,
Expr
::
BinOp
(
op
,
l
,
r
)
=>
{
let
lv
=
eval_expr
(
&
l
);
let
rv
=
eval_expr
(
&
r
);
match
op
{
Op
::
Add
=>
lv
+
rv
,
Op
::
Sub
=>
lv
-
rv
,
Op
::
Mul
=>
lv
*
rv
,
Op
::
Div
=>
lv
/
rv
,
Op
::
Pow
=>
lv
.pow
(
rv
as
u32
),
_
=>
unimplemented!
(),
}
}
Expr
::
UnaryOp
(
op
,
e
)
=>
{
let
e
=
eval_expr
(
&
e
);
match
op
{
Op
::
Add
=>
e
,
Op
::
Sub
=>
-
e
,
_
=>
unimplemented!
(),
}
}
_
=>
unimplemented!
(),
}
}
// use crate::ast::{Binop, Cmd, Constant, Expr, Item, Prog, TypeDecl};
// use crate::check::{check_prog, Fenv, Tenv};
// use crate::parse::parse_prog;
//use std::collections::HashMap;
// pub type Addr = u32;
// #[derive(Debug, PartialEq, Clone)]
// pub enum Data {
// Value(Constant),
// Pointer(Addr),
// }
// pub type Venv = HashMap<String, Addr>;
// pub type Menv = HashMap<Addr, Data>;
// #[derive(Debug, PartialEq, Clone)]
// pub struct Mem {
// pub Addr: u32,
// pub Menv: Menv,
// }
// impl Mem {
// fn new() -> Mem {
// Mem {
// Addr: 0,
// Menv: Menv::new(),
// }
// }
// fn alloc(&mut self) -> Addr {
// // allocate a new address
// self.Addr += 1;
// self.Addr
// }
// }
// pub fn get_bool(d: Data) -> bool {
// if let Data::Value(Constant::Boolean(b)) = d {
// b
// } else {
// panic!("cannot evaluate into Boolean");
// }
// }
// pub fn get_i32(d: Data) -> i32 {
// if let Data::Value(Constant::Num(i)) = d {
// i
// } else {
// panic!("cannot evaluate into i32");
// }
// }
// pub fn eval_expr(exp: &Expr, mem: &mut Mem, venv: &Venv, fenv: &Fenv) -> Data {
// println!("\neval_expr {:?}, mem {:?}, venv {:?}", exp, mem, venv);
// match exp {
// Expr::Constant(c) => Data::Value(c.clone()),
// Expr::Binop(e1, op, e2) => {
// let ev1 = eval_expr(e1, mem, venv, fenv);
// let ev2 = eval_expr(e2, mem, venv, fenv);
// Data::Value(match op {
// Binop::And => Constant::Boolean(get_bool(ev1) && get_bool(ev2)),
// Binop::Or => Constant::Boolean(get_bool(ev1) && get_bool(ev2)),
// Binop::Equal => Constant::Boolean(ev1 == ev2),
// Binop::Less => Constant::Boolean(get_i32(ev1) < get_i32(ev2)),
// Binop::LessEqual => Constant::Boolean(get_i32(ev1) <= get_i32(ev2)),
// Binop::Greater => Constant::Boolean(get_i32(ev1) > get_i32(ev2)),
// Binop::GreaterEqual => Constant::Boolean(get_i32(ev1) >= get_i32(ev2)),
// Binop::Divide => Constant::Num(get_i32(ev1) / get_i32(ev2)),
// Binop::Reminder => Constant::Num(get_i32(ev1) % get_i32(ev2)),
// Binop::Minus => Constant::Num(get_i32(ev1) - get_i32(ev2)),
// Binop::Plus => Constant::Num(get_i32(ev1) + get_i32(ev2)),
// Binop::Times => Constant::Num(get_i32(ev1) * get_i32(ev2)),
// })
// }
// Expr::Id(id) => {
// let e = mem.Menv.get(venv.get(id).unwrap()).unwrap();
// println!("{:?} -> {:?}", id, e);
// e.to_owned()
// }
// Expr::Not(e) => {
// let ev = eval_expr(e, mem, venv, fenv);
// Data::Value(Constant::Boolean(!get_bool(ev)))
// }
// Expr::Application(id, exprs) => {
// // evaluate arguments
// println!("application {:?}", id);
// let args: Vec<Data> = exprs
// .into_iter()
// .map(|e| eval_expr(e, mem, venv, fenv))
// .collect();
// println!("args {:?}", args);
// // lookup callee
// let f = fenv.get(id).unwrap();
// println!("f {:?}", &f);
// let parameter_names: Vec<String> =
// f.sig.1.clone().into_iter().map(|idt| idt.0).collect();
// println!("f par_names {:?}", ¶meter_names);
// let mut lenv = Venv::new(); // local environment for function application
// let arg_assign: Vec<(String, Data)> =
// parameter_names.into_iter().zip(args.into_iter()).collect();
// println!("arg assignments {:?}", &arg_assign);
// for (id, val) in arg_assign {
// let addr = mem.alloc(); // get new allocation slot
// mem.Menv.insert(addr, val); // write the new value
// lenv.insert(id, addr);
// }
// println!("local enviroment {:?}", &lenv);
// println!("memory {:?}", &mem);
// // execute function, unwrap the result as we need a Constant
// eval_body(f.body.clone(), mem, &mut lenv, fenv).unwrap()
// }
// Expr::Ref(exp) => {
// println!("here");
// match *exp.to_owned() {
// Expr::Id(id) => {
// println!("id {:?}", &id);
// let addr = venv.get(&id).unwrap();
// Data::Pointer(*addr)
// }
// _ => {
// let val = eval_expr(exp, mem, venv, fenv);
// println!("-- value {:?}", &val);
// let addr = mem.alloc(); // get new allocation slot
// mem.Menv.insert(addr, val.to_owned()); // write the new value
// let ref_val = Data::Pointer(addr);
// println!(
// "Ref exp {:?} e {:?} mem {:?} venv {:?}",
// exp, val, mem, venv
// );
// ref_val
// }
// }
// }
// Expr::RefMut(exp) => {
// println!("here");
// match *exp.to_owned() {
// Expr::Id(id) => {
// println!("id {:?}", &id);
// let addr = venv.get(&id).unwrap();
// Data::Pointer(*addr)
// }
// _ => {
// let val = eval_expr(exp, mem, venv, fenv);
// println!("-- value {:?}", &val);
// let addr = mem.alloc(); // get new allocation slot
// mem.Menv.insert(addr, val.to_owned()); // write the new value
// let ref_val = Data::Pointer(addr);
// println!(
// "Ref exp {:?} e {:?} mem {:?} venv {:?}",
// exp, val, mem, venv
// );
// ref_val
// }
// }
// }
// Expr::Deref(exp) => {
// println!("-- Deref");
// let e = eval_expr(exp, mem, venv, fenv);
// println!("-- DereRef {:?} {:?}", exp, e);
// if let Data::Pointer(addr) = e {
// mem.Menv.get(&addr).unwrap().to_owned()
// } else {
// panic!("cannot deref {:?}", e);
// }
// }
// _ => unimplemented!(),
// }
// }
// pub fn eval_lvalue(exp: &Expr, mem: &mut Mem, venv: &Venv, fenv: &Fenv) -> Addr {
// println!("eval_lvalue {:?},{:?},{:?},{:?} ", exp, mem, venv, fenv);
// match exp {
// Expr::Id(id) => {
// let addr = venv.get(id).unwrap();
// println!("addr {:?}", addr);
// addr.to_owned()
// }
// Expr::Deref(exp) => {
// let lv = eval_expr(exp, mem, venv, fenv);
// println!("lv {:?}", lv);
// match eval_expr(exp, mem, venv, fenv) {
// Data::Pointer(addr) => addr,
// _ => panic!("cannot deref {:?}", exp),
// }
// }
// _ => unimplemented!(),
// }
// }
// // commands may return with a value
// // either directly (return) or
// // if inside an inner block (then/else, or while)
// pub fn menv_update(data: Data, menv: &mut Menv) {
// // match data {
// // Pointer::
// // }
// }
// pub fn dump(msg: &str, mem: &Mem, venv: &Venv) {
// println!("{:?} {:?} {:?}", msg, mem, venv);
// }
// // A return genaretes Some(Data) else None
// pub fn eval_cmd(cmd: &Cmd, mem: &mut Mem, venv: &mut Venv, fenv: &Fenv) -> Option<Data> {
// println!("{:?}", cmd);
// match cmd {
// Cmd::Assign(lexp, rexp) => {
// let rval = eval_expr(rexp, mem, venv, fenv);
// println!("val {:?}", rval);
// let addr = eval_lvalue(lexp, mem, venv, fenv);
// // println!("lval {:?}", lval);
// // let addr = venv.get(&lval).unwrap();
// mem.Menv.insert(addr, rval);
// None
// }
// Cmd::If(exp, then_block, opt_else) => {
// if get_bool(eval_expr(exp, mem, venv, fenv)) {
// eval_body(then_block.to_vec(), mem, venv, fenv)
// } else {
// if let Some(else_block) = opt_else {
// eval_body(else_block.to_vec(), mem, venv, fenv)
// } else {
// None
// }
// }
// }
// Cmd::Let(_, id, _, exp) => {
// let val = eval_expr(exp, mem, venv, fenv);
// println!("val {:?}", val);
// let addr = mem.alloc(); // get new allocation slot
// mem.Menv.insert(addr, val); // write the new value
// venv.insert(id.to_owned(), addr);
// dump("after Let", mem, venv);
// None
// }
// Cmd::Return(exp) => {
// let v = Some(eval_expr(exp, mem, venv, fenv));
// println!("return value {:?}", v);
// v
// }
// Cmd::While(exp, body) => {
// while get_bool(eval_expr(exp, mem, venv, fenv)) {
// if let Some(retv) = eval_body(body.to_vec(), mem, venv, fenv) {
// return Some(retv);
// }
// }
// None
// }
// }
// }
// pub fn eval_body(cmds: Vec<Cmd>, mem: &mut Mem, venv: &mut Venv, fenv: &Fenv) -> Option<Data> {
// for c in &cmds {
// if let Some(ret) = eval_cmd(c, mem, venv, fenv) {
// return Some(ret);
// }
// }
// None
// }
// pub fn build_env(prog: Prog) -> (Tenv, Fenv) {
// let mut tenv = Tenv::new();
// let mut fenv = Fenv::new();
// for i in prog {
// match i {
// Item::TypeDecl(TypeDecl::Struct(id, layout)) => {
// tenv.insert(id.clone(), TypeDecl::Struct(id, layout));
// }
// Item::Function(f) => {
// fenv.insert(f.sig.0.to_owned(), f);
// }
// }
// }
// (tenv, fenv)
// }
// pub fn eval_prog(prog: &str) {
// let (unparsed, prog) = parse_prog(prog).unwrap();
// println!("prog: {:?}", prog);
// println!("unparsed: {:?}", unparsed);
// let (tenv, fenv) = check_prog(&prog);
// println!("envs {:?}", (tenv, &fenv));
// // assume main does not take any parameters
// let call_main = Expr::Application("main".to_owned(), Vec::<Expr>::new());
// let mut mem = Mem::new();
// let mut venv = Venv::new();
// let ret = eval_expr(&call_main, &mut mem, &mut venv, &fenv);
// println!("return from main = {:?}", ret);
// println!("venv = {:?}", venv);
// println!("mem = {:?}", mem);
// }
This diff is collapsed.
Click to expand it.
src/lib.rs
+
1
−
0
View file @
be369876
...
@@ -2,3 +2,4 @@
...
@@ -2,3 +2,4 @@
pub
mod
ast
;
pub
mod
ast
;
pub
mod
parse
;
pub
mod
parse
;
pub
mod
interpreter
;
This diff is collapsed.
Click to expand it.
src/parse.rs
+
52
−
81
View file @
be369876
...
@@ -6,15 +6,15 @@ use std::slice::Iter;
...
@@ -6,15 +6,15 @@ use std::slice::Iter;
use
nom
::{
use
nom
::{
branch
::
alt
,
branch
::
alt
,
bytes
::
complete
::
tag
,
bytes
::
complete
::
tag
,
character
::
complete
::{
alpha1
,
char
,
digit1
,
multispace0
},
character
::
complete
::{
alpha1
,
char
,
digit1
,
multispace0
,
multispace1
},
combinator
::{
cut
,
map
},
combinator
::{
cut
,
map
,
opt
},
error
::
ParseError
,
error
::
ParseError
,
multi
::{
many1
,
separated_list
},
multi
::{
many1
,
separated_list
},
sequence
::{
delimited
,
preceded
,
tuple
},
sequence
::{
delimited
,
preceded
,
terminated
,
tuple
},
IResult
,
IResult
,
};
};
use
crate
::
ast
::{
Cmd
,
Expr
,
Op
,
Span
,
SpanCmd
,
SpanExpr
};
use
crate
::
ast
::{
Cmd
,
Expr
,
Op
,
Span
,
SpanCmd
,
SpanExpr
,
Block
};
pub
fn
parse_i32
(
i
:
Span
)
->
IResult
<
Span
,
(
Span
,
i32
)
>
{
pub
fn
parse_i32
(
i
:
Span
)
->
IResult
<
Span
,
(
Span
,
i32
)
>
{
map
(
digit1
,
|
digit_str
:
Span
|
{
map
(
digit1
,
|
digit_str
:
Span
|
{
...
@@ -42,7 +42,7 @@ pub enum Token<'a> {
...
@@ -42,7 +42,7 @@ pub enum Token<'a> {
Num
(
i32
),
Num
(
i32
),
Bool
(
bool
),
Bool
(
bool
),
Id
(
String
),
Id
(
String
),
Fn
(
String
,
Vec
<
(
Span
<
'a
>
,
Vec
<
SpanToken
<
'a
>>
)
>
),
Call
(
String
,
Vec
<
(
Span
<
'a
>
,
Vec
<
SpanToken
<
'a
>>
)
>
),
Par
(
Vec
<
SpanToken
<
'a
>>
),
Par
(
Vec
<
SpanToken
<
'a
>>
),
Op
(
Op
),
Op
(
Op
),
}
}
...
@@ -54,9 +54,10 @@ fn parse_terminal(i: Span) -> IResult<Span, SpanToken> {
...
@@ -54,9 +54,10 @@ fn parse_terminal(i: Span) -> IResult<Span, SpanToken> {
map
(
parse_i32
,
|(
s
,
v
)|
(
s
,
Token
::
Num
(
v
))),
map
(
parse_i32
,
|(
s
,
v
)|
(
s
,
Token
::
Num
(
v
))),
map
(
tag
(
"true"
),
|
s
|
(
s
,
Token
::
Bool
(
true
))),
map
(
tag
(
"true"
),
|
s
|
(
s
,
Token
::
Bool
(
true
))),
map
(
tag
(
"false"
),
|
s
|
(
s
,
Token
::
Bool
(
false
))),
map
(
tag
(
"false"
),
|
s
|
(
s
,
Token
::
Bool
(
false
))),
map
(
tuple
((
alpha1
,
parse_par
(
separated_list
(
char
(
','
),
parse_tokens
)))),
|(
s
,
t
)|
{
map
(
(
s
,
Token
::
Fn
(
s
.to_string
(),
t
))
tuple
((
alpha1
,
parse_par
(
separated_list
(
char
(
','
),
parse_tokens
)))),
}),
|(
s
,
t
)|
(
s
,
Token
::
Call
(
s
.to_string
(),
t
)),
),
map
(
alpha1
,
|
s
:
Span
|
(
s
,
Token
::
Id
(
s
.to_string
()))),
map
(
alpha1
,
|
s
:
Span
|
(
s
,
Token
::
Id
(
s
.to_string
()))),
map
(
parse_par
(
parse_tokens
),
|(
s
,
tokens
)|
{
map
(
parse_par
(
parse_tokens
),
|(
s
,
tokens
)|
{
(
s
,
Token
::
Par
(
tokens
))
(
s
,
Token
::
Par
(
tokens
))
...
@@ -82,17 +83,20 @@ fn compute_atom<'a>(t: &mut Peekable<Iter<SpanToken<'a>>>) -> SpanExpr<'a> {
...
@@ -82,17 +83,20 @@ fn compute_atom<'a>(t: &mut Peekable<Iter<SpanToken<'a>>>) -> SpanExpr<'a> {
Some
((
s
,
Token
::
Bool
(
b
)))
=>
(
*
s
,
Expr
::
Bool
(
*
b
)),
Some
((
s
,
Token
::
Bool
(
b
)))
=>
(
*
s
,
Expr
::
Bool
(
*
b
)),
Some
((
s
,
Token
::
Id
(
id
)))
=>
(
*
s
,
Expr
::
Id
(
id
.to_string
())),
Some
((
s
,
Token
::
Id
(
id
)))
=>
(
*
s
,
Expr
::
Id
(
id
.to_string
())),
Some
((
_
,
Token
::
Par
(
v
)))
=>
climb
(
&
mut
v
.iter
()
.peekable
(),
0
),
Some
((
_
,
Token
::
Par
(
v
)))
=>
climb
(
&
mut
v
.iter
()
.peekable
(),
0
),
Some
((
s
,
Token
::
Op
(
op
)))
=>
{
Some
((
s
,
Token
::
Call
(
id
,
vv
)))
=>
{
(
*
s
,
Expr
::
UnaryOp
(
*
op
,
Box
::
new
(
climb
(
t
,
4
))))
//
}
// assume highest precedence
let
v
:
Vec
<
SpanExpr
>
=
vv
.iter
()
.map
(|(
span
,
t
)|
climb
(
&
mut
(
*
t
)
.iter
()
.peekable
(),
0
))
.collect
();
(
*
s
,
Expr
::
Call
(
id
.to_string
(),
v
))
}
Some
((
s
,
Token
::
Op
(
op
)))
=>
(
*
s
,
Expr
::
UnaryOp
(
*
op
,
Box
::
new
(
climb
(
t
,
4
)))),
// assume highest precedence
_
=>
panic!
(
"error in compute atom"
),
_
=>
panic!
(
"error in compute atom"
),
}
}
}
}
fn
climb
<
'a
>
(
fn
climb
<
'a
>
(
t
:
&
mut
Peekable
<
Iter
<
SpanToken
<
'a
>>>
,
min_prec
:
u8
)
->
SpanExpr
<
'a
>
{
t
:
&
mut
Peekable
<
Iter
<
SpanToken
<
'a
>>>
,
min_prec
:
u8
,
)
->
SpanExpr
<
'a
>
{
let
mut
result
:
SpanExpr
=
compute_atom
(
t
);
let
mut
result
:
SpanExpr
=
compute_atom
(
t
);
loop
{
loop
{
...
@@ -125,35 +129,7 @@ pub fn parse_expr(i: Span) -> IResult<Span, SpanExpr> {
...
@@ -125,35 +129,7 @@ pub fn parse_expr(i: Span) -> IResult<Span, SpanExpr> {
})(
i
)
})(
i
)
}
}
pub
fn
test
(
s
:
&
str
,
v
:
i32
)
{
// fn parse_if(i: Span) -> IResult<Span, SpanCmd> {
match
parse_expr
(
Span
::
new
(
s
))
{
Ok
((
Span
{
fragment
:
""
,
..
},
e
))
=>
{
println!
(
"{:?}"
,
&
e
);
println!
(
"eval {} {}"
,
math_eval
(
&
e
),
v
);
assert_eq!
(
math_eval
(
&
e
),
v
);
}
Ok
((
s
,
t
))
=>
println!
(
"parse incomplete,
\n
parsed tokens
\t
{:?},
\n
remaining
\t
{:?}"
,
t
,
s
),
Err
(
err
)
=>
println!
(
"{:?}"
,
err
),
}
}
// helpers
fn
parse_par
<
'a
,
O
,
F
,
E
>
(
inner
:
F
,
)
->
impl
Fn
(
Span
<
'a
>
)
->
IResult
<
Span
<
'a
>
,
O
,
E
>
where
F
:
Fn
(
Span
<
'a
>
)
->
IResult
<
Span
<
'a
>
,
O
,
E
>
,
E
:
ParseError
<
Span
<
'a
>>
,
{
// delimited allows us to split up the input
// cut allwos us to consume the input (and prevent backtracking)
delimited
(
char
(
'('
),
preceded
(
multispace0
,
inner
),
cut
(
char
(
')'
)))
}
// fn parse_if<'a>(i: Span) -> IResult<Span, SpanCmd> {
// map(
// map(
// preceded(
// preceded(
// // here to avoid ambiguity with other names starting with `if`, if we added
// // here to avoid ambiguity with other names starting with `if`, if we added
...
@@ -172,6 +148,27 @@ where
...
@@ -172,6 +148,27 @@ where
// )(i)
// )(i)
// }
// }
// helpers
fn
parse_par
<
'a
,
O
,
F
,
E
>
(
inner
:
F
)
->
impl
Fn
(
Span
<
'a
>
)
->
IResult
<
Span
<
'a
>
,
O
,
E
>
where
F
:
Fn
(
Span
<
'a
>
)
->
IResult
<
Span
<
'a
>
,
O
,
E
>
,
E
:
ParseError
<
Span
<
'a
>>
,
{
// delimited allows us to split up the input
// cut allwos us to consume the input (and prevent backtracking)
delimited
(
char
(
'('
),
preceded
(
multispace0
,
inner
),
cut
(
char
(
')'
)))
}
fn
parse_sem
<
'a
,
O
,
F
,
E
>
(
inner
:
F
)
->
impl
Fn
(
Span
<
'a
>
)
->
IResult
<
Span
<
'a
>
,
O
,
E
>
where
F
:
Fn
(
Span
<
'a
>
)
->
IResult
<
Span
<
'a
>
,
O
,
E
>
,
E
:
ParseError
<
Span
<
'a
>>
,
{
// delimited allows us to split up the input
// cut allwos us to consume the input (and prevent backtracking)
delimited
(
char
(
'{'
),
preceded
(
multispace0
,
inner
),
cut
(
char
(
'}'
)))
}
// pub fn parse_let(i: &str) -> IResult<&str, Cmd, VerboseError<&str>> {
// pub fn parse_let(i: &str) -> IResult<&str, Cmd, VerboseError<&str>> {
// context(
// context(
// "let expression",
// "let expression",
...
@@ -243,16 +240,18 @@ pub fn parse_assign<'a>(i: Span<'a>) -> IResult<Span<'a>, Cmd<'a>> {
...
@@ -243,16 +240,18 @@ pub fn parse_assign<'a>(i: Span<'a>) -> IResult<Span<'a>, Cmd<'a>> {
// )(i)
// )(i)
// }
// }
// pub fn parse_cmd(i: &str) -> IResult<&str, Cmd, VerboseError<&str>> {
// pub fn parse_cmd<'a>(i: Span<'a>) -> IResult<Span<'a>, Cmd<'a>> {
// preceded(
pub
fn
parse_cmd
(
i
:
Span
)
->
IResult
<
Span
,
Cmd
>
{
// multispace0,
preceded
(
multispace0
,
parse_assign
,
// alt((parse_while, parse_let, parse_if, parse_assign, parse_return)),
// alt((parse_while, parse_let, parse_if, parse_assign, parse_return)),
//
)(i)
)(
i
)
//
}
}
//
pub fn parse_block(i:
&str
) -> IResult<
&str
, Block
, VerboseError<&str>
> {
pub
fn
parse_block
(
i
:
Span
)
->
IResult
<
Span
,
Block
>
{
//
preceded(multispace0,
s_cmd
(separated_list(tag(";"), parse_cmd)))(i)
preceded
(
multispace0
,
parse_sem
(
separated_list
(
tag
(
";"
),
parse_cmd
)))(
i
)
//
}
}
// fn s_cmd<'a, O, F>(inner: F) -> impl Fn(&'a str) -> IResult<&'a str, O, VerboseError<&'a str>>
// fn s_cmd<'a, O, F>(inner: F) -> impl Fn(&'a str) -> IResult<&'a str, O, VerboseError<&'a str>>
// where
// where
...
@@ -355,34 +354,6 @@ pub fn parse_assign<'a>(i: Span<'a>) -> IResult<Span<'a>, Cmd<'a>> {
...
@@ -355,34 +354,6 @@ pub fn parse_assign<'a>(i: Span<'a>) -> IResult<Span<'a>, Cmd<'a>> {
// )(i)
// )(i)
// }
// }
// tests
fn
math_eval
(
e
:
&
SpanExpr
)
->
i32
{
match
e
.clone
()
.1
{
Expr
::
Num
(
i
)
=>
i
,
Expr
::
BinOp
(
op
,
l
,
r
)
=>
{
let
lv
=
math_eval
(
&
l
);
let
rv
=
math_eval
(
&
r
);
match
op
{
Op
::
Add
=>
lv
+
rv
,
Op
::
Sub
=>
lv
-
rv
,
Op
::
Mul
=>
lv
*
rv
,
Op
::
Div
=>
lv
/
rv
,
Op
::
Pow
=>
lv
.pow
(
rv
as
u32
),
_
=>
unimplemented!
(),
}
}
Expr
::
UnaryOp
(
op
,
e
)
=>
{
let
e
=
math_eval
(
&
e
);
match
op
{
Op
::
Add
=>
e
,
Op
::
Sub
=>
-
e
,
_
=>
unimplemented!
(),
}
}
_
=>
unimplemented!
(),
}
}
#[derive(Debug,
Copy,
Clone,
PartialEq)]
#[derive(Debug,
Copy,
Clone,
PartialEq)]
enum
Ass
{
enum
Ass
{
Left
,
Left
,
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment