Browse Source

preparing for Rust 2018 and constructor work

pull/5/head
Jason Williams 6 years ago
parent
commit
5e4999c5fa
  1. 1
      Cargo.toml
  2. 71
      src/lib/exec.rs
  3. 4
      src/lib/js/array.rs
  4. 4
      src/lib/js/console.rs
  5. 6
      src/lib/js/error.rs
  6. 8
      src/lib/js/function.rs
  7. 4
      src/lib/js/json.rs
  8. 4
      src/lib/js/math.rs
  9. 4
      src/lib/js/object.rs
  10. 16
      src/lib/js/string.rs
  11. 22
      src/lib/js/value.rs
  12. 10
      src/lib/syntax/ast/expr.rs
  13. 2
      src/lib/syntax/ast/keyword.rs
  14. 6
      src/lib/syntax/ast/token.rs
  15. 4
      src/lib/syntax/lexer.rs
  16. 164
      src/lib/syntax/parser.rs
  17. 4
      tests/js/test.js

1
Cargo.toml

@ -8,6 +8,7 @@ repository = "https://github.com/jasonwilliams/boa"
keywords = ["javascript", "compiler", "lexer", "parser", "js"] keywords = ["javascript", "compiler", "lexer", "parser", "js"]
license = "Unlicense OR MIT" license = "Unlicense OR MIT"
exclude = [".vscode/*", "Dockerfile", "Makefile", ".editorConfig"] exclude = [".vscode/*", "Dockerfile", "Makefile", ".editorConfig"]
edition = "2018"
[dependencies] [dependencies]
gc = "0.3.2" gc = "0.3.2"

71
src/lib/exec.rs

@ -1,13 +1,13 @@
use gc::{Gc, GcCell}; use gc::{Gc, GcCell};
use js::function::{Function, RegularFunction}; use crate::js::function::{Function, RegularFunction};
use js::object::{INSTANCE_PROTOTYPE, PROTOTYPE}; use crate::js::object::{INSTANCE_PROTOTYPE, PROTOTYPE};
use js::value::{from_value, to_value, ResultValue, Value, ValueData}; use crate::js::value::{from_value, to_value, ResultValue, Value, ValueData};
use js::{array, console, function, json, math, object, string}; use crate::js::{array, console, function, json, math, object, string};
use std::borrow::Borrow; use std::borrow::Borrow;
use std::collections::HashMap; use std::collections::HashMap;
use syntax::ast::constant::Const; use crate::syntax::ast::constant::Const;
use syntax::ast::expr::{Expr, ExprDef}; use crate::syntax::ast::expr::{Expr, ExprDef};
use syntax::ast::op::{BinOp, BitOp, CompOp, LogOp, NumOp, UnaryOp}; use crate::syntax::ast::op::{BinOp, BitOp, CompOp, LogOp, NumOp, UnaryOp};
/// A variable scope /// A variable scope
#[derive(Trace, Finalize, Clone, Debug)] #[derive(Trace, Finalize, Clone, Debug)]
pub struct Scope { pub struct Scope {
@ -188,32 +188,32 @@ impl Executor for Interpreter {
Ok(result) Ok(result)
} }
ExprDef::IfExpr(ref cond, ref expr, None) => { ExprDef::IfExpr(ref cond, ref expr, None) => {
Ok(if try!(self.run(cond)).borrow().is_true() { Ok(if r#try!(self.run(cond)).borrow().is_true() {
try!(self.run(expr)) r#try!(self.run(expr))
} else { } else {
Gc::new(ValueData::Undefined) Gc::new(ValueData::Undefined)
}) })
} }
ExprDef::IfExpr(ref cond, ref expr, Some(ref else_e)) => { ExprDef::IfExpr(ref cond, ref expr, Some(ref else_e)) => {
Ok(if try!(self.run(cond)).borrow().is_true() { Ok(if r#try!(self.run(cond)).borrow().is_true() {
try!(self.run(expr)) r#try!(self.run(expr))
} else { } else {
try!(self.run(else_e)) r#try!(self.run(else_e))
}) })
} }
ExprDef::SwitchExpr(ref val_e, ref vals, ref default) => { ExprDef::SwitchExpr(ref val_e, ref vals, ref default) => {
let val = try!(self.run(val_e)).clone(); let val = r#try!(self.run(val_e)).clone();
let mut result = Gc::new(ValueData::Null); let mut result = Gc::new(ValueData::Null);
let mut matched = false; let mut matched = false;
for tup in vals.iter() { for tup in vals.iter() {
let tup: &(Expr, Vec<Expr>) = tup; let tup: &(Expr, Vec<Expr>) = tup;
let cond = &tup.0; let cond = &tup.0;
let block = &tup.1; let block = &tup.1;
if val == try!(self.run(cond)) { if val == r#try!(self.run(cond)) {
matched = true; matched = true;
let last_expr = block.last().unwrap(); let last_expr = block.last().unwrap();
for expr in block.iter() { for expr in block.iter() {
let e_result = try!(self.run(expr)); let e_result = r#try!(self.run(expr));
if expr == last_expr { if expr == last_expr {
result = e_result; result = e_result;
} }
@ -221,14 +221,14 @@ impl Executor for Interpreter {
} }
} }
if !matched && default.is_some() { if !matched && default.is_some() {
result = try!(self.run(default.as_ref().unwrap())); result = r#try!(self.run(default.as_ref().unwrap()));
} }
Ok(result) Ok(result)
} }
ExprDef::ObjectDeclExpr(ref map) => { ExprDef::ObjectDeclExpr(ref map) => {
let obj = ValueData::new_obj(Some(self.global.clone())); let obj = ValueData::new_obj(Some(self.global.clone()));
for (key, val) in map.iter() { for (key, val) in map.iter() {
obj.borrow().set_field(key.clone(), try!(self.run(val))); obj.borrow().set_field(key.clone(), r#try!(self.run(val)));
} }
Ok(obj) Ok(obj)
} }
@ -236,7 +236,7 @@ impl Executor for Interpreter {
let arr_map = ValueData::new_obj(Some(self.global.clone())); let arr_map = ValueData::new_obj(Some(self.global.clone()));
let mut index: i32 = 0; let mut index: i32 = 0;
for val in arr.iter() { for val in arr.iter() {
let val = try!(self.run(val)); let val = r#try!(self.run(val));
arr_map.borrow().set_field(index.to_string(), val); arr_map.borrow().set_field(index.to_string(), val);
index += 1; index += 1;
} }
@ -266,8 +266,8 @@ impl Executor for Interpreter {
Ok(Gc::new(ValueData::Function(GcCell::new(function)))) Ok(Gc::new(ValueData::Function(GcCell::new(function))))
} }
ExprDef::BinOpExpr(BinOp::Num(ref op), ref a, ref b) => { ExprDef::BinOpExpr(BinOp::Num(ref op), ref a, ref b) => {
let v_r_a = try!(self.run(a)); let v_r_a = r#try!(self.run(a));
let v_r_b = try!(self.run(b)); let v_r_b = r#try!(self.run(b));
let v_a = (*v_r_a).clone(); let v_a = (*v_r_a).clone();
let v_b = (*v_r_b).clone(); let v_b = (*v_r_b).clone();
Ok(Gc::new(match *op { Ok(Gc::new(match *op {
@ -279,7 +279,7 @@ impl Executor for Interpreter {
})) }))
} }
ExprDef::UnaryOpExpr(ref op, ref a) => { ExprDef::UnaryOpExpr(ref op, ref a) => {
let v_r_a = try!(self.run(a)); let v_r_a = r#try!(self.run(a));
let v_a = (*v_r_a).clone(); let v_a = (*v_r_a).clone();
Ok(match *op { Ok(match *op {
UnaryOp::Minus => to_value(-v_a.to_num()), UnaryOp::Minus => to_value(-v_a.to_num()),
@ -289,8 +289,8 @@ impl Executor for Interpreter {
}) })
} }
ExprDef::BinOpExpr(BinOp::Bit(ref op), ref a, ref b) => { ExprDef::BinOpExpr(BinOp::Bit(ref op), ref a, ref b) => {
let v_r_a = try!(self.run(a)); let v_r_a = r#try!(self.run(a));
let v_r_b = try!(self.run(b)); let v_r_b = r#try!(self.run(b));
let v_a = (*v_r_a).clone(); let v_a = (*v_r_a).clone();
let v_b = (*v_r_b).clone(); let v_b = (*v_r_b).clone();
Ok(Gc::new(match *op { Ok(Gc::new(match *op {
@ -302,8 +302,8 @@ impl Executor for Interpreter {
})) }))
} }
ExprDef::BinOpExpr(BinOp::Comp(ref op), ref a, ref b) => { ExprDef::BinOpExpr(BinOp::Comp(ref op), ref a, ref b) => {
let v_r_a = try!(self.run(a)); let v_r_a = r#try!(self.run(a));
let v_r_b = try!(self.run(b)); let v_r_b = r#try!(self.run(b));
let v_a = v_r_a.borrow(); let v_a = v_r_a.borrow();
let v_b = v_r_b.borrow(); let v_b = v_r_b.borrow();
Ok(to_value(match *op { Ok(to_value(match *op {
@ -322,18 +322,18 @@ impl Executor for Interpreter {
})) }))
} }
ExprDef::BinOpExpr(BinOp::Log(ref op), ref a, ref b) => { ExprDef::BinOpExpr(BinOp::Log(ref op), ref a, ref b) => {
let v_a = from_value::<bool>(try!(self.run(a))).unwrap(); let v_a = from_value::<bool>(r#try!(self.run(a))).unwrap();
let v_b = from_value::<bool>(try!(self.run(b))).unwrap(); let v_b = from_value::<bool>(r#try!(self.run(b))).unwrap();
Ok(match *op { Ok(match *op {
LogOp::And => to_value(v_a && v_b), LogOp::And => to_value(v_a && v_b),
LogOp::Or => to_value(v_a || v_b), LogOp::Or => to_value(v_a || v_b),
}) })
} }
ExprDef::ConstructExpr(ref callee, ref args) => { ExprDef::ConstructExpr(ref callee, ref args) => {
let func = try!(self.run(callee)); let func = self.run(callee)?;
let mut v_args = Vec::with_capacity(args.len()); let mut v_args = Vec::with_capacity(args.len());
for arg in args.iter() { for arg in args.iter() {
v_args.push(try!(self.run(arg))); v_args.push(r#try!(self.run(arg)));
} }
let this = Gc::new(ValueData::Object(GcCell::new(HashMap::new()))); let this = Gc::new(ValueData::Object(GcCell::new(HashMap::new())));
this.borrow() this.borrow()
@ -342,7 +342,8 @@ impl Executor for Interpreter {
ValueData::Function(ref func) => match func.clone().into_inner() { ValueData::Function(ref func) => match func.clone().into_inner() {
Function::NativeFunc(ref ntv) => { Function::NativeFunc(ref ntv) => {
let func = ntv.data; let func = ntv.data;
func(this, try!(self.run(callee)), v_args) println!("{:#?}", this);
func(this, self.run(callee)?, v_args)
} }
Function::RegularFunc(ref data) => { Function::RegularFunc(ref data) => {
let scope = self.make_scope(this); let scope = self.make_scope(this);
@ -364,9 +365,9 @@ impl Executor for Interpreter {
Some(ref v) => self.run(v), Some(ref v) => self.run(v),
None => Ok(Gc::new(ValueData::Undefined)), None => Ok(Gc::new(ValueData::Undefined)),
}, },
ExprDef::ThrowExpr(ref ex) => Err(try!(self.run(ex))), ExprDef::ThrowExpr(ref ex) => Err(r#try!(self.run(ex))),
ExprDef::AssignExpr(ref ref_e, ref val_e) => { ExprDef::AssignExpr(ref ref_e, ref val_e) => {
let val = try!(self.run(val_e)); let val = r#try!(self.run(val_e));
match ref_e.def { match ref_e.def {
ExprDef::LocalExpr(ref name) => { ExprDef::LocalExpr(ref name) => {
self.scope() self.scope()
@ -375,7 +376,7 @@ impl Executor for Interpreter {
.set_field(name.clone(), val.clone()); .set_field(name.clone(), val.clone());
} }
ExprDef::GetConstFieldExpr(ref obj, ref field) => { ExprDef::GetConstFieldExpr(ref obj, ref field) => {
let val_obj = try!(self.run(obj)); let val_obj = r#try!(self.run(obj));
val_obj.borrow().set_field(field.clone(), val.clone()); val_obj.borrow().set_field(field.clone(), val.clone());
} }
_ => (), _ => (),
@ -388,7 +389,7 @@ impl Executor for Interpreter {
for var in vars.iter() { for var in vars.iter() {
let (name, value) = var.clone(); let (name, value) = var.clone();
let val = match value { let val = match value {
Some(v) => try!(self.run(&v)), Some(v) => r#try!(self.run(&v)),
None => Gc::new(ValueData::Null), None => Gc::new(ValueData::Null),
}; };
scope_vars_ptr.set_field(name.clone(), val); scope_vars_ptr.set_field(name.clone(), val);
@ -396,7 +397,7 @@ impl Executor for Interpreter {
Ok(Gc::new(ValueData::Undefined)) Ok(Gc::new(ValueData::Undefined))
} }
ExprDef::TypeOfExpr(ref val_e) => { ExprDef::TypeOfExpr(ref val_e) => {
let val = try!(self.run(val_e)); let val = r#try!(self.run(val_e));
Ok(to_value(match *val { Ok(to_value(match *val {
ValueData::Undefined => "undefined", ValueData::Undefined => "undefined",
ValueData::Null | ValueData::Object(_) => "object", ValueData::Null | ValueData::Object(_) => "object",

4
src/lib/js/array.rs

@ -1,6 +1,6 @@
use gc::Gc; use gc::Gc;
use js::function::NativeFunctionData; use crate::js::function::NativeFunctionData;
use js::value::{to_value, ResultValue, Value, ValueData}; use crate::js::value::{to_value, ResultValue, Value, ValueData};
/// Create a new array /// Create a new array
pub fn make_array(this: Value, _: Value, _: Vec<Value>) -> ResultValue { pub fn make_array(this: Value, _: Value, _: Vec<Value>) -> ResultValue {

4
src/lib/js/console.rs

@ -1,6 +1,6 @@
use gc::Gc; use gc::Gc;
use js::function::NativeFunctionData; use crate::js::function::NativeFunctionData;
use js::value::{from_value, to_value, ResultValue, Value, ValueData}; use crate::js::value::{from_value, to_value, ResultValue, Value, ValueData};
use std::iter::FromIterator; use std::iter::FromIterator;
use time::{now, strftime}; use time::{now, strftime};
/// Print a javascript value to the standard output stream /// Print a javascript value to the standard output stream

6
src/lib/js/error.rs

@ -1,7 +1,7 @@
use gc::Gc; use gc::Gc;
use js::function::NativeFunctionData; use crate::js::function::NativeFunctionData;
use js::object::PROTOTYPE; use crate::js::object::PROTOTYPE;
use js::value::{to_value, ResultValue, Value, ValueData}; use crate::js::value::{to_value, ResultValue, Value, ValueData};
/// Create a new error /// Create a new error
pub fn make_error(this: Value, _: Value, args: Vec<Value>) -> ResultValue { pub fn make_error(this: Value, _: Value, args: Vec<Value>) -> ResultValue {

8
src/lib/js/function.rs

@ -1,10 +1,12 @@
use gc::Gc; use gc::Gc;
use js::object::{ObjectData, Property}; use crate::js::object::{ObjectData, Property};
use js::value::{to_value, ResultValue, Value, ValueData}; use crate::js::value::{to_value, ResultValue, Value, ValueData};
use std::collections::HashMap; use std::collections::HashMap;
use syntax::ast::expr::Expr; use crate::syntax::ast::expr::Expr;
/// fn(this, callee, arguments)
pub type NativeFunctionData = fn(Value, Value, Vec<Value>) -> ResultValue; pub type NativeFunctionData = fn(Value, Value, Vec<Value>) -> ResultValue;
/// A Javascript function /// A Javascript function
/// A member of the Object type that may be invoked as a subroutine /// A member of the Object type that may be invoked as a subroutine
/// https://tc39.github.io/ecma262/#sec-terms-and-definitions-function /// https://tc39.github.io/ecma262/#sec-terms-and-definitions-function

4
src/lib/js/json.rs

@ -1,7 +1,7 @@
use js::function::NativeFunctionData; use crate::js::function::NativeFunctionData;
/// The JSON Object /// The JSON Object
/// https://tc39.github.io/ecma262/#sec-json-object /// https://tc39.github.io/ecma262/#sec-json-object
use js::value::{to_value, ResultValue, Value, ValueData}; use crate::js::value::{to_value, ResultValue, Value, ValueData};
use serde_json::{self, to_string_pretty, Value as JSONValue}; use serde_json::{self, to_string_pretty, Value as JSONValue};
/// Parse a JSON string into a Javascript object /// Parse a JSON string into a Javascript object

4
src/lib/js/math.rs

@ -1,5 +1,5 @@
use js::function::NativeFunctionData; use crate::js::function::NativeFunctionData;
use js::value::{from_value, to_value, ResultValue, Value, ValueData}; use crate::js::value::{from_value, to_value, ResultValue, Value, ValueData};
use rand::random; use rand::random;
use std::f64; use std::f64;

4
src/lib/js/object.rs

@ -1,6 +1,6 @@
use gc::Gc; use gc::Gc;
use js::function::NativeFunctionData; use crate::js::function::NativeFunctionData;
use js::value::{from_value, to_value, FromValue, ResultValue, ToValue, Value, ValueData}; use crate::js::value::{from_value, to_value, FromValue, ResultValue, ToValue, Value, ValueData};
use std::collections::HashMap; use std::collections::HashMap;
pub static PROTOTYPE: &'static str = "prototype"; pub static PROTOTYPE: &'static str = "prototype";
pub static INSTANCE_PROTOTYPE: &'static str = "__proto__"; pub static INSTANCE_PROTOTYPE: &'static str = "__proto__";

16
src/lib/js/string.rs

@ -1,12 +1,16 @@
use gc::Gc; use gc::Gc;
use js::function::NativeFunctionData; use crate::js::function::NativeFunctionData;
use js::object::{Property, PROTOTYPE}; use crate::js::object::{Property, PROTOTYPE};
use js::value::{from_value, to_value, ResultValue, Value, ValueData}; use crate::js::value::{from_value, to_value, ResultValue, Value, ValueData};
/// Create new string /// Create new string
pub fn make_string(this: Value, _: Value, _: Vec<Value>) -> ResultValue { /// https://searchfox.org/mozilla-central/source/js/src/vm/StringObject.h#19
this.set_field_slice("length", to_value(0i32)); pub fn make_string(this: Value, _: Value, args: Vec<Value>) -> ResultValue {
Ok(Gc::new(ValueData::Undefined)) // If we're constructing a string, we should set the initial length
// To do this we need to convert the string back to a Rust String, then get the .len()
let a: String = from_value(args[0].clone()).unwrap();
this.set_field_slice("length", to_value(a.len() as i32));
Ok(this)
} }
/// Get a string's length /// Get a string's length
pub fn get_string_length(this: Value, _: Value, _: Vec<Value>) -> ResultValue { pub fn get_string_length(this: Value, _: Value, _: Vec<Value>) -> ResultValue {

22
src/lib/js/value.rs

@ -1,6 +1,6 @@
use gc::{Gc, GcCell}; use gc::{Gc, GcCell};
use js::function::{Function, NativeFunction, NativeFunctionData}; use crate::js::function::{Function, NativeFunction, NativeFunctionData};
use js::object::{ObjectData, Property, INSTANCE_PROTOTYPE, PROTOTYPE}; use crate::js::object::{ObjectData, Property, INSTANCE_PROTOTYPE, PROTOTYPE};
use serde_json::map::Map; use serde_json::map::Map;
use serde_json::Number as JSONNumber; use serde_json::Number as JSONNumber;
use serde_json::Value as JSONValue; use serde_json::Value as JSONValue;
@ -36,6 +36,7 @@ pub enum ValueData {
/// `Number` - A 32-bit integer, such as `42` /// `Number` - A 32-bit integer, such as `42`
Integer(i32), Integer(i32),
/// `Object` - An object, such as `Math`, represented by a binary tree of string keys to Javascript values /// `Object` - An object, such as `Math`, represented by a binary tree of string keys to Javascript values
/// Some Objects will need an internal slot to hold private values, so our second ObjectData is for that
Object(GcCell<ObjectData>), Object(GcCell<ObjectData>),
/// `Function` - A runnable block of code, such as `Math.sqrt`, which can take some variables and return a useful value or act upon an object /// `Function` - A runnable block of code, such as `Math.sqrt`, which can take some variables and return a useful value or act upon an object
Function(GcCell<Function>), Function(GcCell<Function>),
@ -160,7 +161,7 @@ impl ValueData {
/// Returns a copy of the Property /// Returns a copy of the Property
pub fn get_prop(&self, field: String) -> Option<Property> { pub fn get_prop(&self, field: String) -> Option<Property> {
// Spidermonkey has its own GetLengthProperty: https://searchfox.org/mozilla-central/source/js/src/vm/Interpreter-inl.h#154 // Spidermonkey has its own GetLengthProperty: https://searchfox.org/mozilla-central/source/js/src/vm/Interpreter-inl.h#154
// TODO: Move this to a better place // This is only for primitive strings, String() objects have their lengths calculated in string.rs
if self.is_string() && field == "length" { if self.is_string() && field == "length" {
if let ValueData::String(ref s) = *self { if let ValueData::String(ref s) = *self {
return Some(Property::new(to_value(s.len() as i32))) return Some(Property::new(to_value(s.len() as i32)))
@ -173,7 +174,10 @@ impl ValueData {
hash.into_inner() hash.into_inner()
} }
// Accesing .object on borrow() seems to automatically dereference it, so we don't need the * // Accesing .object on borrow() seems to automatically dereference it, so we don't need the *
// ValueData::Function(ref func) => func.clone().object, ValueData::Function(ref func) => match func.clone().into_inner() {
Function::NativeFunc(ref func) => func.object.clone(),
Function::RegularFunc(ref func) => func.object.clone()
}
_ => return None, _ => return None,
}; };
match obj.get(&field) { match obj.get(&field) {
@ -332,13 +336,13 @@ impl Display for ValueData {
} }
), ),
ValueData::Object(ref v) => { ValueData::Object(ref v) => {
try!(write!(f, "{}", "{")); r#try!(write!(f, "{}", "{"));
match v.borrow().iter().last() { match v.borrow().iter().last() {
Some((last_key, _)) => { Some((last_key, _)) => {
for (key, val) in v.borrow().iter() { for (key, val) in v.borrow().iter() {
try!(write!(f, "{}: {}", key, val.value.clone())); r#try!(write!(f, "{}: {}", key, val.value.clone()));
if key != last_key { if key != last_key {
try!(write!(f, "{}", ", ")); r#try!(write!(f, "{}", ", "));
} }
} }
} }
@ -555,7 +559,7 @@ impl<T: FromValue> FromValue for Vec<T> {
let len = v.get_field_slice("length").to_int(); let len = v.get_field_slice("length").to_int();
let mut vec = Vec::with_capacity(len as usize); let mut vec = Vec::with_capacity(len as usize);
for i in 0..len { for i in 0..len {
vec.push(try!(from_value(v.get_field(i.to_string())))) vec.push(r#try!(from_value(v.get_field(i.to_string()))))
} }
Ok(vec) Ok(vec)
} }
@ -616,7 +620,7 @@ impl<T: FromValue> FromValue for Option<T> {
Ok(if value.is_null_or_undefined() { Ok(if value.is_null_or_undefined() {
None None
} else { } else {
Some(try!(FromValue::from_value(value))) Some(r#try!(FromValue::from_value(value)))
}) })
} }
} }

10
src/lib/syntax/ast/expr.rs

@ -1,7 +1,7 @@
use std::collections::btree_map::BTreeMap; use std::collections::btree_map::BTreeMap;
use std::fmt::{Display, Formatter, Result}; use std::fmt::{Display, Formatter, Result};
use syntax::ast::constant::Const; use crate::syntax::ast::constant::Const;
use syntax::ast::op::{BinOp, Operator, UnaryOp}; use crate::syntax::ast::op::{BinOp, Operator, UnaryOp};
#[derive(Clone, Trace, Finalize, Debug, PartialEq)] #[derive(Clone, Trace, Finalize, Debug, PartialEq)]
pub struct Expr { pub struct Expr {
@ -109,9 +109,9 @@ impl Display for ExprDef {
return match *self { return match *self {
ExprDef::ConstExpr(ref c) => write!(f, "{}", c), ExprDef::ConstExpr(ref c) => write!(f, "{}", c),
ExprDef::BlockExpr(ref block) => { ExprDef::BlockExpr(ref block) => {
try!(write!(f, "{}", "{")); r#try!(write!(f, "{}", "{"));
for expr in block.iter() { for expr in block.iter() {
try!(write!(f, "{};", expr)); r#try!(write!(f, "{};", expr));
} }
write!(f, "{}", "}") write!(f, "{}", "}")
} }
@ -119,7 +119,7 @@ impl Display for ExprDef {
ExprDef::GetConstFieldExpr(ref ex, ref field) => write!(f, "{}.{}", ex, field), ExprDef::GetConstFieldExpr(ref ex, ref field) => write!(f, "{}.{}", ex, field),
ExprDef::GetFieldExpr(ref ex, ref field) => write!(f, "{}[{}]", ex, field), ExprDef::GetFieldExpr(ref ex, ref field) => write!(f, "{}[{}]", ex, field),
ExprDef::CallExpr(ref ex, ref args) => { ExprDef::CallExpr(ref ex, ref args) => {
try!(write!(f, "{}(", ex)); r#try!(write!(f, "{}(", ex));
let arg_strs: Vec<String> = args.iter().map(|arg| arg.to_string()).collect(); let arg_strs: Vec<String> = args.iter().map(|arg| arg.to_string()).collect();
write!(f, "{})", arg_strs.join(",")) write!(f, "{})", arg_strs.join(","))
} }

2
src/lib/syntax/ast/keyword.rs

@ -2,7 +2,7 @@ use std::error;
use std::fmt::Error; use std::fmt::Error;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::str::FromStr; use std::str::FromStr;
use syntax::ast::keyword::Keyword::*; use crate::syntax::ast::keyword::Keyword::*;
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
/// A Javascript Keyword /// A Javascript Keyword

6
src/lib/syntax/ast/token.rs

@ -1,7 +1,7 @@
use std::fmt::{Debug, Display, Formatter, Result}; use std::fmt::{Debug, Display, Formatter, Result};
use syntax::ast::keyword::Keyword; use crate::syntax::ast::keyword::Keyword;
use syntax::ast::pos::Position; use crate::syntax::ast::pos::Position;
use syntax::ast::punc::Punctuator; use crate::syntax::ast::punc::Punctuator;
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
/// Represents a token /// Represents a token

4
src/lib/syntax/lexer.rs

@ -8,8 +8,8 @@ use std::fmt;
use std::iter::Peekable; use std::iter::Peekable;
use std::str::Chars; use std::str::Chars;
use std::str::FromStr; use std::str::FromStr;
use syntax::ast::punc::Punctuator; use crate::syntax::ast::punc::Punctuator;
use syntax::ast::token::{Token, TokenData}; use crate::syntax::ast::token::{Token, TokenData};
#[allow(unused)] #[allow(unused)]
macro_rules! vop { macro_rules! vop {

164
src/lib/syntax/parser.rs

@ -1,10 +1,10 @@
use std::collections::btree_map::BTreeMap; use std::collections::btree_map::BTreeMap;
use syntax::ast::constant::Const; use crate::syntax::ast::constant::Const;
use syntax::ast::expr::{Expr, ExprDef}; use crate::syntax::ast::expr::{Expr, ExprDef};
use syntax::ast::keyword::Keyword; use crate::syntax::ast::keyword::Keyword;
use syntax::ast::op::{BinOp, BitOp, CompOp, LogOp, NumOp, Operator, UnaryOp}; use crate::syntax::ast::op::{BinOp, BitOp, CompOp, LogOp, NumOp, Operator, UnaryOp};
use syntax::ast::punc::Punctuator; use crate::syntax::ast::punc::Punctuator;
use syntax::ast::token::{Token, TokenData}; use crate::syntax::ast::token::{Token, TokenData};
macro_rules! mk ( macro_rules! mk (
($this:expr, $def:expr) => { ($this:expr, $def:expr) => {
@ -52,7 +52,7 @@ impl Parser {
pub fn parse_all(&mut self) -> ParseResult { pub fn parse_all(&mut self) -> ParseResult {
let mut exprs = Vec::new(); let mut exprs = Vec::new();
while self.pos < self.tokens.len() { while self.pos < self.tokens.len() {
let result = try!(self.parse()); let result = r#try!(self.parse());
exprs.push(result); exprs.push(result);
} }
@ -72,7 +72,7 @@ impl Parser {
fn parse_struct(&mut self, keyword: Keyword) -> ParseResult { fn parse_struct(&mut self, keyword: Keyword) -> ParseResult {
match keyword { match keyword {
Keyword::Throw => { Keyword::Throw => {
let thrown = try!(self.parse()); let thrown = r#try!(self.parse());
Ok(mk!(self, ExprDef::ThrowExpr(Box::new(thrown)))) Ok(mk!(self, ExprDef::ThrowExpr(Box::new(thrown))))
} }
Keyword::Var => { Keyword::Var => {
@ -171,10 +171,10 @@ impl Parser {
)) ))
} }
Keyword::Switch => { Keyword::Switch => {
try!(self.expect_punc(Punctuator::OpenParen, "switch value")); r#try!(self.expect_punc(Punctuator::OpenParen, "switch value"));
let value = self.parse(); let value = self.parse();
try!(self.expect_punc(Punctuator::CloseParen, "switch value")); r#try!(self.expect_punc(Punctuator::CloseParen, "switch value"));
try!(self.expect_punc(Punctuator::OpenBlock, "switch block")); r#try!(self.expect_punc(Punctuator::OpenBlock, "switch block"));
let mut cases = Vec::new(); let mut cases = Vec::new();
let mut default = None; let mut default = None;
while self.pos + 1 < self.tokens.len() { while self.pos + 1 < self.tokens.len() {
@ -184,26 +184,26 @@ impl Parser {
TokenData::Keyword(Keyword::Case) => { TokenData::Keyword(Keyword::Case) => {
let cond = self.parse(); let cond = self.parse();
let mut block = Vec::new(); let mut block = Vec::new();
try!(self.expect_punc(Punctuator::Colon, "switch case")); r#try!(self.expect_punc(Punctuator::Colon, "switch case"));
loop { loop {
match try!(self.get_token(self.pos)).data { match r#try!(self.get_token(self.pos)).data {
TokenData::Keyword(Keyword::Case) TokenData::Keyword(Keyword::Case)
| TokenData::Keyword(Keyword::Default) => break, | TokenData::Keyword(Keyword::Default) => break,
TokenData::Punctuator(Punctuator::CloseBlock) => break, TokenData::Punctuator(Punctuator::CloseBlock) => break,
_ => block.push(try!(self.parse())), _ => block.push(r#try!(self.parse())),
} }
} }
cases.push((cond.unwrap(), block)); cases.push((cond.unwrap(), block));
} }
TokenData::Keyword(Keyword::Default) => { TokenData::Keyword(Keyword::Default) => {
let mut block = Vec::new(); let mut block = Vec::new();
try!(self.expect_punc(Punctuator::Colon, "default switch case")); r#try!(self.expect_punc(Punctuator::Colon, "default switch case"));
loop { loop {
match try!(self.get_token(self.pos)).data { match r#try!(self.get_token(self.pos)).data {
TokenData::Keyword(Keyword::Case) TokenData::Keyword(Keyword::Case)
| TokenData::Keyword(Keyword::Default) => break, | TokenData::Keyword(Keyword::Default) => break,
TokenData::Punctuator(Punctuator::CloseBlock) => break, TokenData::Punctuator(Punctuator::CloseBlock) => break,
_ => block.push(try!(self.parse())), _ => block.push(r#try!(self.parse())),
} }
} }
default = Some(mk!(self, ExprDef::BlockExpr(block))); default = Some(mk!(self, ExprDef::BlockExpr(block)));
@ -222,7 +222,7 @@ impl Parser {
} }
} }
} }
try!(self.expect_punc(Punctuator::CloseBlock, "switch block")); r#try!(self.expect_punc(Punctuator::CloseBlock, "switch block"));
Ok(mk!( Ok(mk!(
self, self,
ExprDef::SwitchExpr( ExprDef::SwitchExpr(
@ -237,7 +237,7 @@ impl Parser {
} }
Keyword::Function => { Keyword::Function => {
// function [identifier] () { etc } // function [identifier] () { etc }
let tk = try!(self.get_token(self.pos)); let tk = r#try!(self.get_token(self.pos));
let name = match tk.data { let name = match tk.data {
TokenData::Identifier(ref name) => { TokenData::Identifier(ref name) => {
self.pos += 1; self.pos += 1;
@ -268,7 +268,7 @@ impl Parser {
} }
} }
self.pos += 1; self.pos += 1;
if try!(self.get_token(self.pos)).data if r#try!(self.get_token(self.pos)).data
== TokenData::Punctuator(Punctuator::Comma) == TokenData::Punctuator(Punctuator::Comma)
{ {
self.pos += 1; self.pos += 1;
@ -291,13 +291,13 @@ impl Parser {
if self.pos > self.tokens.len() { if self.pos > self.tokens.len() {
return Err(ParseError::AbruptEnd); return Err(ParseError::AbruptEnd);
} }
let token = try!(self.get_token(self.pos)); let token = r#try!(self.get_token(self.pos));
self.pos += 1; self.pos += 1;
let expr: Expr = match token.data { let expr: Expr = match token.data {
TokenData::Punctuator(Punctuator::Semicolon) | TokenData::Comment(_) TokenData::Punctuator(Punctuator::Semicolon) | TokenData::Comment(_)
if self.pos < self.tokens.len() => if self.pos < self.tokens.len() =>
{ {
try!(self.parse()) r#try!(self.parse())
} }
TokenData::Punctuator(Punctuator::Semicolon) | TokenData::Comment(_) => { TokenData::Punctuator(Punctuator::Semicolon) | TokenData::Comment(_) => {
mk!(self, ExprDef::ConstExpr(Const::Undefined)) mk!(self, ExprDef::ConstExpr(Const::Undefined))
@ -310,15 +310,15 @@ impl Parser {
mk!(self, ExprDef::ConstExpr(Const::Undefined)) mk!(self, ExprDef::ConstExpr(Const::Undefined))
} }
TokenData::Identifier(s) => mk!(self, ExprDef::LocalExpr(s)), TokenData::Identifier(s) => mk!(self, ExprDef::LocalExpr(s)),
TokenData::Keyword(keyword) => try!(self.parse_struct(keyword)), TokenData::Keyword(keyword) => r#try!(self.parse_struct(keyword)),
TokenData::Punctuator(Punctuator::OpenParen) => { TokenData::Punctuator(Punctuator::OpenParen) => {
match try!(self.get_token(self.pos)).data { match r#try!(self.get_token(self.pos)).data {
TokenData::Punctuator(Punctuator::CloseParen) TokenData::Punctuator(Punctuator::CloseParen)
if try!(self.get_token(self.pos + 1)).data if r#try!(self.get_token(self.pos + 1)).data
== TokenData::Punctuator(Punctuator::Arrow) => == TokenData::Punctuator(Punctuator::Arrow) =>
{ {
self.pos += 2; self.pos += 2;
let expr = try!(self.parse()); let expr = r#try!(self.parse());
mk!( mk!(
self, self,
ExprDef::ArrowFunctionDeclExpr(Vec::new(), Box::new(expr)), ExprDef::ArrowFunctionDeclExpr(Vec::new(), Box::new(expr)),
@ -326,8 +326,8 @@ impl Parser {
) )
} }
_ => { _ => {
let next = try!(self.parse()); let next = r#try!(self.parse());
let next_tok = try!(self.get_token(self.pos)); let next_tok = r#try!(self.get_token(self.pos));
self.pos += 1; self.pos += 1;
match next_tok.data { match next_tok.data {
TokenData::Punctuator(Punctuator::CloseParen) => next, TokenData::Punctuator(Punctuator::CloseParen) => next,
@ -338,7 +338,7 @@ impl Parser {
ExprDef::LocalExpr(ref name) => (*name).clone(), ExprDef::LocalExpr(ref name) => (*name).clone(),
_ => "".to_string(), _ => "".to_string(),
}, },
match try!(self.get_token(self.pos)).data { match r#try!(self.get_token(self.pos)).data {
TokenData::Identifier(ref id) => id.clone(), TokenData::Identifier(ref id) => id.clone(),
_ => "".to_string(), _ => "".to_string(),
}, },
@ -346,7 +346,7 @@ impl Parser {
let mut expect_ident = true; let mut expect_ident = true;
loop { loop {
self.pos += 1; self.pos += 1;
let curr_tk = try!(self.get_token(self.pos)); let curr_tk = r#try!(self.get_token(self.pos));
match curr_tk.data { match curr_tk.data {
TokenData::Identifier(ref id) if expect_ident => { TokenData::Identifier(ref id) if expect_ident => {
args.push(id.clone()); args.push(id.clone());
@ -380,11 +380,11 @@ impl Parser {
} }
} }
} }
try!(self.expect( r#try!(self.expect(
TokenData::Punctuator(Punctuator::Arrow), TokenData::Punctuator(Punctuator::Arrow),
"arrow function" "arrow function"
)); ));
let expr = try!(self.parse()); let expr = r#try!(self.parse());
mk!( mk!(
self, self,
ExprDef::ArrowFunctionDeclExpr(args, Box::new(expr)), ExprDef::ArrowFunctionDeclExpr(args, Box::new(expr)),
@ -404,10 +404,10 @@ impl Parser {
} }
TokenData::Punctuator(Punctuator::OpenBracket) => { TokenData::Punctuator(Punctuator::OpenBracket) => {
let mut array: Vec<Expr> = Vec::new(); let mut array: Vec<Expr> = Vec::new();
let mut expect_comma_or_end = try!(self.get_token(self.pos)).data let mut expect_comma_or_end = r#try!(self.get_token(self.pos)).data
== TokenData::Punctuator(Punctuator::CloseBracket); == TokenData::Punctuator(Punctuator::CloseBracket);
loop { loop {
let token = try!(self.get_token(self.pos)); let token = r#try!(self.get_token(self.pos));
if token.data == TokenData::Punctuator(Punctuator::CloseBracket) if token.data == TokenData::Punctuator(Punctuator::CloseBracket)
&& expect_comma_or_end && expect_comma_or_end
{ {
@ -432,7 +432,7 @@ impl Parser {
"array declaration", "array declaration",
)); ));
} else { } else {
let parsed = try!(self.parse()); let parsed = r#try!(self.parse());
self.pos -= 1; self.pos -= 1;
array.push(parsed); array.push(parsed);
expect_comma_or_end = true; expect_comma_or_end = true;
@ -442,7 +442,7 @@ impl Parser {
mk!(self, ExprDef::ArrayDeclExpr(array), token) mk!(self, ExprDef::ArrayDeclExpr(array), token)
} }
TokenData::Punctuator(Punctuator::OpenBlock) TokenData::Punctuator(Punctuator::OpenBlock)
if try!(self.get_token(self.pos)).data if r#try!(self.get_token(self.pos)).data
== TokenData::Punctuator(Punctuator::CloseBlock) => == TokenData::Punctuator(Punctuator::CloseBlock) =>
{ {
self.pos += 1; self.pos += 1;
@ -453,15 +453,15 @@ impl Parser {
) )
} }
TokenData::Punctuator(Punctuator::OpenBlock) TokenData::Punctuator(Punctuator::OpenBlock)
if try!(self.get_token(self.pos + 1)).data if r#try!(self.get_token(self.pos + 1)).data
== TokenData::Punctuator(Punctuator::Colon) => == TokenData::Punctuator(Punctuator::Colon) =>
{ {
let mut map = Box::new(BTreeMap::new()); let mut map = Box::new(BTreeMap::new());
while try!(self.get_token(self.pos - 1)).data while r#try!(self.get_token(self.pos - 1)).data
== TokenData::Punctuator(Punctuator::Comma) == TokenData::Punctuator(Punctuator::Comma)
|| map.len() == 0 || map.len() == 0
{ {
let tk = try!(self.get_token(self.pos)); let tk = r#try!(self.get_token(self.pos));
let name = match tk.data { let name = match tk.data {
TokenData::Identifier(ref id) => id.clone(), TokenData::Identifier(ref id) => id.clone(),
TokenData::StringLiteral(ref str) => str.clone(), TokenData::StringLiteral(ref str) => str.clone(),
@ -477,11 +477,11 @@ impl Parser {
} }
}; };
self.pos += 1; self.pos += 1;
try!(self.expect( r#try!(self.expect(
TokenData::Punctuator(Punctuator::Colon), TokenData::Punctuator(Punctuator::Colon),
"object declaration" "object declaration"
)); ));
let value = try!(self.parse()); let value = r#try!(self.parse());
map.insert(name, value); map.insert(name, value);
self.pos += 1; self.pos += 1;
} }
@ -490,12 +490,12 @@ impl Parser {
TokenData::Punctuator(Punctuator::OpenBlock) => { TokenData::Punctuator(Punctuator::OpenBlock) => {
let mut exprs = Vec::new(); let mut exprs = Vec::new();
loop { loop {
if try!(self.get_token(self.pos)).data if r#try!(self.get_token(self.pos)).data
== TokenData::Punctuator(Punctuator::CloseBlock) == TokenData::Punctuator(Punctuator::CloseBlock)
{ {
break; break;
} else { } else {
exprs.push(try!(self.parse())); exprs.push(r#try!(self.parse()));
} }
} }
self.pos += 1; self.pos += 1;
@ -503,23 +503,23 @@ impl Parser {
} }
TokenData::Punctuator(Punctuator::Sub) => mk!( TokenData::Punctuator(Punctuator::Sub) => mk!(
self, self,
ExprDef::UnaryOpExpr(UnaryOp::Minus, Box::new(try!(self.parse()))) ExprDef::UnaryOpExpr(UnaryOp::Minus, Box::new(r#try!(self.parse())))
), ),
TokenData::Punctuator(Punctuator::Add) => mk!( TokenData::Punctuator(Punctuator::Add) => mk!(
self, self,
ExprDef::UnaryOpExpr(UnaryOp::Plus, Box::new(try!(self.parse()))) ExprDef::UnaryOpExpr(UnaryOp::Plus, Box::new(r#try!(self.parse())))
), ),
TokenData::Punctuator(Punctuator::Not) => mk!( TokenData::Punctuator(Punctuator::Not) => mk!(
self, self,
ExprDef::UnaryOpExpr(UnaryOp::Not, Box::new(try!(self.parse()))) ExprDef::UnaryOpExpr(UnaryOp::Not, Box::new(r#try!(self.parse())))
), ),
TokenData::Punctuator(Punctuator::Inc) => mk!( TokenData::Punctuator(Punctuator::Inc) => mk!(
self, self,
ExprDef::UnaryOpExpr(UnaryOp::IncrementPre, Box::new(try!(self.parse()))) ExprDef::UnaryOpExpr(UnaryOp::IncrementPre, Box::new(r#try!(self.parse())))
), ),
TokenData::Punctuator(Punctuator::Dec) => mk!( TokenData::Punctuator(Punctuator::Dec) => mk!(
self, self,
ExprDef::UnaryOpExpr(UnaryOp::DecrementPre, Box::new(try!(self.parse()))) ExprDef::UnaryOpExpr(UnaryOp::DecrementPre, Box::new(r#try!(self.parse())))
), ),
_ => return Err(ParseError::Expected(Vec::new(), token.clone(), "script")), _ => return Err(ParseError::Expected(Vec::new(), token.clone(), "script")),
}; };
@ -537,7 +537,7 @@ impl Parser {
match next.data { match next.data {
TokenData::Punctuator(Punctuator::Dot) => { TokenData::Punctuator(Punctuator::Dot) => {
self.pos += 1; self.pos += 1;
let tk = try!(self.get_token(self.pos)); let tk = r#try!(self.get_token(self.pos));
match tk.data { match tk.data {
TokenData::Identifier(ref s) => { TokenData::Identifier(ref s) => {
result = mk!( result = mk!(
@ -557,11 +557,11 @@ impl Parser {
} }
TokenData::Punctuator(Punctuator::OpenParen) => { TokenData::Punctuator(Punctuator::OpenParen) => {
let mut args = Vec::new(); let mut args = Vec::new();
let mut expect_comma_or_end = try!(self.get_token(self.pos + 1)).data let mut expect_comma_or_end = r#try!(self.get_token(self.pos + 1)).data
== TokenData::Punctuator(Punctuator::CloseParen); == TokenData::Punctuator(Punctuator::CloseParen);
loop { loop {
self.pos += 1; self.pos += 1;
let token = try!(self.get_token(self.pos)); let token = r#try!(self.get_token(self.pos));
if token.data == TokenData::Punctuator(Punctuator::CloseParen) if token.data == TokenData::Punctuator(Punctuator::CloseParen)
&& expect_comma_or_end && expect_comma_or_end
{ {
@ -581,7 +581,7 @@ impl Parser {
"function call arguments", "function call arguments",
)); ));
} else { } else {
let parsed = try!(self.parse()); let parsed = r#try!(self.parse());
self.pos -= 1; self.pos -= 1;
args.push(parsed); args.push(parsed);
expect_comma_or_end = true; expect_comma_or_end = true;
@ -591,9 +591,9 @@ impl Parser {
} }
TokenData::Punctuator(Punctuator::Question) => { TokenData::Punctuator(Punctuator::Question) => {
self.pos += 1; self.pos += 1;
let if_e = try!(self.parse()); let if_e = r#try!(self.parse());
try!(self.expect(TokenData::Punctuator(Punctuator::Colon), "if expression")); r#try!(self.expect(TokenData::Punctuator(Punctuator::Colon), "if expression"));
let else_e = try!(self.parse()); let else_e = r#try!(self.parse());
result = mk!( result = mk!(
self, self,
ExprDef::IfExpr(Box::new(expr), Box::new(if_e), Some(Box::new(else_e))) ExprDef::IfExpr(Box::new(expr), Box::new(if_e), Some(Box::new(else_e)))
@ -601,8 +601,8 @@ impl Parser {
} }
TokenData::Punctuator(Punctuator::OpenBracket) => { TokenData::Punctuator(Punctuator::OpenBracket) => {
self.pos += 1; self.pos += 1;
let index = try!(self.parse()); let index = r#try!(self.parse());
try!(self.expect( r#try!(self.expect(
TokenData::Punctuator(Punctuator::CloseBracket), TokenData::Punctuator(Punctuator::CloseBracket),
"array index" "array index"
)); ));
@ -613,7 +613,7 @@ impl Parser {
} }
TokenData::Punctuator(Punctuator::Assign) => { TokenData::Punctuator(Punctuator::Assign) => {
self.pos += 1; self.pos += 1;
let next = try!(self.parse()); let next = r#try!(self.parse());
result = mk!(self, ExprDef::AssignExpr(Box::new(expr), Box::new(next))); result = mk!(self, ExprDef::AssignExpr(Box::new(expr), Box::new(next)));
} }
TokenData::Punctuator(Punctuator::Arrow) => { TokenData::Punctuator(Punctuator::Arrow) => {
@ -623,79 +623,79 @@ impl Parser {
ExprDef::LocalExpr(ref name) => args.push((*name).clone()), ExprDef::LocalExpr(ref name) => args.push((*name).clone()),
_ => return Err(ParseError::ExpectedExpr("identifier", result)), _ => return Err(ParseError::ExpectedExpr("identifier", result)),
} }
let next = try!(self.parse()); let next = r#try!(self.parse());
result = mk!(self, ExprDef::ArrowFunctionDeclExpr(args, Box::new(next))); result = mk!(self, ExprDef::ArrowFunctionDeclExpr(args, Box::new(next)));
} }
TokenData::Punctuator(Punctuator::Add) => { TokenData::Punctuator(Punctuator::Add) => {
result = try!(self.binop(BinOp::Num(NumOp::Add), expr)) result = r#try!(self.binop(BinOp::Num(NumOp::Add), expr))
} }
TokenData::Punctuator(Punctuator::Sub) => { TokenData::Punctuator(Punctuator::Sub) => {
result = try!(self.binop(BinOp::Num(NumOp::Sub), expr)) result = r#try!(self.binop(BinOp::Num(NumOp::Sub), expr))
} }
TokenData::Punctuator(Punctuator::Mul) => { TokenData::Punctuator(Punctuator::Mul) => {
result = try!(self.binop(BinOp::Num(NumOp::Mul), expr)) result = r#try!(self.binop(BinOp::Num(NumOp::Mul), expr))
} }
TokenData::Punctuator(Punctuator::Div) => { TokenData::Punctuator(Punctuator::Div) => {
result = try!(self.binop(BinOp::Num(NumOp::Div), expr)) result = r#try!(self.binop(BinOp::Num(NumOp::Div), expr))
} }
TokenData::Punctuator(Punctuator::Mod) => { TokenData::Punctuator(Punctuator::Mod) => {
result = try!(self.binop(BinOp::Num(NumOp::Mod), expr)) result = r#try!(self.binop(BinOp::Num(NumOp::Mod), expr))
} }
TokenData::Punctuator(Punctuator::BoolAnd) => { TokenData::Punctuator(Punctuator::BoolAnd) => {
result = try!(self.binop(BinOp::Log(LogOp::And), expr)) result = r#try!(self.binop(BinOp::Log(LogOp::And), expr))
} }
TokenData::Punctuator(Punctuator::BoolOr) => { TokenData::Punctuator(Punctuator::BoolOr) => {
result = try!(self.binop(BinOp::Log(LogOp::Or), expr)) result = r#try!(self.binop(BinOp::Log(LogOp::Or), expr))
} }
TokenData::Punctuator(Punctuator::And) => { TokenData::Punctuator(Punctuator::And) => {
result = try!(self.binop(BinOp::Bit(BitOp::And), expr)) result = r#try!(self.binop(BinOp::Bit(BitOp::And), expr))
} }
TokenData::Punctuator(Punctuator::Or) => { TokenData::Punctuator(Punctuator::Or) => {
result = try!(self.binop(BinOp::Bit(BitOp::Or), expr)) result = r#try!(self.binop(BinOp::Bit(BitOp::Or), expr))
} }
TokenData::Punctuator(Punctuator::Xor) => { TokenData::Punctuator(Punctuator::Xor) => {
result = try!(self.binop(BinOp::Bit(BitOp::Xor), expr)) result = r#try!(self.binop(BinOp::Bit(BitOp::Xor), expr))
} }
TokenData::Punctuator(Punctuator::LeftSh) => { TokenData::Punctuator(Punctuator::LeftSh) => {
result = try!(self.binop(BinOp::Bit(BitOp::Shl), expr)) result = r#try!(self.binop(BinOp::Bit(BitOp::Shl), expr))
} }
TokenData::Punctuator(Punctuator::RightSh) => { TokenData::Punctuator(Punctuator::RightSh) => {
result = try!(self.binop(BinOp::Bit(BitOp::Shr), expr)) result = r#try!(self.binop(BinOp::Bit(BitOp::Shr), expr))
} }
TokenData::Punctuator(Punctuator::Eq) => { TokenData::Punctuator(Punctuator::Eq) => {
result = try!(self.binop(BinOp::Comp(CompOp::Equal), expr)) result = r#try!(self.binop(BinOp::Comp(CompOp::Equal), expr))
} }
TokenData::Punctuator(Punctuator::NotEq) => { TokenData::Punctuator(Punctuator::NotEq) => {
result = try!(self.binop(BinOp::Comp(CompOp::NotEqual), expr)) result = r#try!(self.binop(BinOp::Comp(CompOp::NotEqual), expr))
} }
TokenData::Punctuator(Punctuator::StrictEq) => { TokenData::Punctuator(Punctuator::StrictEq) => {
result = try!(self.binop(BinOp::Comp(CompOp::StrictEqual), expr)) result = r#try!(self.binop(BinOp::Comp(CompOp::StrictEqual), expr))
} }
TokenData::Punctuator(Punctuator::StrictNotEq) => { TokenData::Punctuator(Punctuator::StrictNotEq) => {
result = try!(self.binop(BinOp::Comp(CompOp::StrictNotEqual), expr)) result = r#try!(self.binop(BinOp::Comp(CompOp::StrictNotEqual), expr))
} }
TokenData::Punctuator(Punctuator::LessThan) => { TokenData::Punctuator(Punctuator::LessThan) => {
result = try!(self.binop(BinOp::Comp(CompOp::LessThan), expr)) result = r#try!(self.binop(BinOp::Comp(CompOp::LessThan), expr))
} }
TokenData::Punctuator(Punctuator::LessThanOrEq) => { TokenData::Punctuator(Punctuator::LessThanOrEq) => {
result = try!(self.binop(BinOp::Comp(CompOp::LessThanOrEqual), expr)) result = r#try!(self.binop(BinOp::Comp(CompOp::LessThanOrEqual), expr))
} }
TokenData::Punctuator(Punctuator::GreaterThan) => { TokenData::Punctuator(Punctuator::GreaterThan) => {
result = try!(self.binop(BinOp::Comp(CompOp::GreaterThan), expr)) result = r#try!(self.binop(BinOp::Comp(CompOp::GreaterThan), expr))
} }
TokenData::Punctuator(Punctuator::GreaterThanOrEq) => { TokenData::Punctuator(Punctuator::GreaterThanOrEq) => {
result = try!(self.binop(BinOp::Comp(CompOp::GreaterThanOrEqual), expr)) result = r#try!(self.binop(BinOp::Comp(CompOp::GreaterThanOrEqual), expr))
} }
TokenData::Punctuator(Punctuator::Inc) => { TokenData::Punctuator(Punctuator::Inc) => {
result = mk!( result = mk!(
self, self,
ExprDef::UnaryOpExpr(UnaryOp::IncrementPost, Box::new(try!(self.parse()))) ExprDef::UnaryOpExpr(UnaryOp::IncrementPost, Box::new(r#try!(self.parse())))
) )
} }
TokenData::Punctuator(Punctuator::Dec) => { TokenData::Punctuator(Punctuator::Dec) => {
result = mk!( result = mk!(
self, self,
ExprDef::UnaryOpExpr(UnaryOp::DecrementPost, Box::new(try!(self.parse()))) ExprDef::UnaryOpExpr(UnaryOp::DecrementPost, Box::new(r#try!(self.parse())))
) )
} }
_ => carry_on = false, _ => carry_on = false,
@ -710,7 +710,7 @@ impl Parser {
fn binop(&mut self, op: BinOp, orig: Expr) -> Result<Expr, ParseError> { fn binop(&mut self, op: BinOp, orig: Expr) -> Result<Expr, ParseError> {
let (precedence, assoc) = op.get_precedence_and_assoc(); let (precedence, assoc) = op.get_precedence_and_assoc();
self.pos += 1; self.pos += 1;
let next = try!(self.parse()); let next = r#try!(self.parse());
Ok(match next.def { Ok(match next.def {
ExprDef::BinOpExpr(ref op2, ref a, ref b) => { ExprDef::BinOpExpr(ref op2, ref a, ref b) => {
let other_precedence = op2.get_precedence(); let other_precedence = op2.get_precedence();

4
tests/js/test.js

@ -1,2 +1,2 @@
var a = 'jabrjjja888'; var a = new String("test");
a.length; a;
Loading…
Cancel
Save