mirror of
https://github.com/exoticorn/curlywas.git
synced 2026-01-20 11:46:43 +01:00
implement binop-assignment (+= etc.)
This commit is contained in:
125
src/parser.rs
125
src/parser.rs
@@ -318,13 +318,27 @@ fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = LexerError> {
|
|||||||
Token::Int(value as i32)
|
Token::Int(value as i32)
|
||||||
});
|
});
|
||||||
|
|
||||||
let op = one_of("+-*/%&^|<=>#")
|
let op = choice((
|
||||||
.repeated()
|
just("#/"),
|
||||||
.at_least(1)
|
just("#%"),
|
||||||
.or(just(':').chain(just('=')))
|
just("<<"),
|
||||||
.or(just('!').chain(just('=')))
|
just(">>"),
|
||||||
.collect::<String>()
|
just("#>>"),
|
||||||
.map(Token::Op);
|
just("#<"),
|
||||||
|
just("#>"),
|
||||||
|
just(">="),
|
||||||
|
just("<="),
|
||||||
|
just("=="),
|
||||||
|
just("!="),
|
||||||
|
just("#>="),
|
||||||
|
just("#<="),
|
||||||
|
just("->"),
|
||||||
|
just(":="),
|
||||||
|
))
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.or(one_of("+-*/%&^|<=>").map(|s: char| s.to_string()))
|
||||||
|
.map(Token::Op)
|
||||||
|
.boxed();
|
||||||
|
|
||||||
let ctrl = one_of("(){};,:?!$").map(Token::Ctrl);
|
let ctrl = one_of("(){};,:?!$").map(Token::Ctrl);
|
||||||
|
|
||||||
@@ -408,11 +422,11 @@ fn parse_string_escapes(s: String) -> String {
|
|||||||
match c {
|
match c {
|
||||||
'0'..='9' | 'a'..='f' | 'A'..='F' => {
|
'0'..='9' | 'a'..='f' | 'A'..='F' => {
|
||||||
let mut number = c.to_string();
|
let mut number = c.to_string();
|
||||||
if let Some('0'..='9' | 'a' ..= 'f' | 'A'..='F') = chars.peek() {
|
if let Some('0'..='9' | 'a'..='f' | 'A'..='F') = chars.peek() {
|
||||||
number.push(chars.next().unwrap());
|
number.push(chars.next().unwrap());
|
||||||
}
|
}
|
||||||
result.push(u8::from_str_radix(&number, 16).unwrap() as char);
|
result.push(u8::from_str_radix(&number, 16).unwrap() as char);
|
||||||
},
|
}
|
||||||
'n' => result.push('\n'),
|
'n' => result.push('\n'),
|
||||||
'r' => result.push('\r'),
|
'r' => result.push('\r'),
|
||||||
't' => result.push('\t'),
|
't' => result.push('\t'),
|
||||||
@@ -447,6 +461,28 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = ScriptError> + Clo
|
|||||||
_ => None,
|
_ => None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let product_op = just(Token::Op("*".to_string()))
|
||||||
|
.to(ast::BinOp::Mul)
|
||||||
|
.or(just(Token::Op("/".to_string())).to(ast::BinOp::Div))
|
||||||
|
.or(just(Token::Op("#/".to_string())).to(ast::BinOp::DivU))
|
||||||
|
.or(just(Token::Op("%".to_string())).to(ast::BinOp::Rem))
|
||||||
|
.or(just(Token::Op("#%".to_string())).to(ast::BinOp::RemU))
|
||||||
|
.boxed();
|
||||||
|
let sum_op = just(Token::Op("+".to_string()))
|
||||||
|
.to(ast::BinOp::Add)
|
||||||
|
.or(just(Token::Op("-".to_string())).to(ast::BinOp::Sub))
|
||||||
|
.boxed();
|
||||||
|
let shift_op = just(Token::Op("<<".to_string()))
|
||||||
|
.to(ast::BinOp::Shl)
|
||||||
|
.or(just(Token::Op("#>>".to_string())).to(ast::BinOp::ShrU))
|
||||||
|
.or(just(Token::Op(">>".to_string())).to(ast::BinOp::ShrS))
|
||||||
|
.boxed();
|
||||||
|
let bit_op = just(Token::Op("&".to_string()))
|
||||||
|
.to(ast::BinOp::And)
|
||||||
|
.or(just(Token::Op("|".to_string())).to(ast::BinOp::Or))
|
||||||
|
.or(just(Token::Op("^".to_string())).to(ast::BinOp::Xor))
|
||||||
|
.boxed();
|
||||||
|
|
||||||
let mut expression_out = None;
|
let mut expression_out = None;
|
||||||
let block = recursive(|block| {
|
let block = recursive(|block| {
|
||||||
let mut block_expression = None;
|
let mut block_expression = None;
|
||||||
@@ -723,16 +759,7 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = ScriptError> + Clo
|
|||||||
|
|
||||||
let op_product = memory_op
|
let op_product = memory_op
|
||||||
.clone()
|
.clone()
|
||||||
.then(
|
.then(product_op.clone().then(memory_op.clone()).repeated())
|
||||||
just(Token::Op("*".to_string()))
|
|
||||||
.to(ast::BinOp::Mul)
|
|
||||||
.or(just(Token::Op("/".to_string())).to(ast::BinOp::Div))
|
|
||||||
.or(just(Token::Op("#/".to_string())).to(ast::BinOp::DivU))
|
|
||||||
.or(just(Token::Op("%".to_string())).to(ast::BinOp::Rem))
|
|
||||||
.or(just(Token::Op("#%".to_string())).to(ast::BinOp::RemU))
|
|
||||||
.then(memory_op.clone())
|
|
||||||
.repeated(),
|
|
||||||
)
|
|
||||||
.foldl(|left, (op, right)| {
|
.foldl(|left, (op, right)| {
|
||||||
let span = (left.span.0, left.span.1.start..right.span.1.end);
|
let span = (left.span.0, left.span.1.start..right.span.1.end);
|
||||||
ast::Expr::BinOp {
|
ast::Expr::BinOp {
|
||||||
@@ -746,13 +773,7 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = ScriptError> + Clo
|
|||||||
|
|
||||||
let op_sum = op_product
|
let op_sum = op_product
|
||||||
.clone()
|
.clone()
|
||||||
.then(
|
.then(sum_op.clone().then(op_product.clone()).repeated())
|
||||||
just(Token::Op("+".to_string()))
|
|
||||||
.to(ast::BinOp::Add)
|
|
||||||
.or(just(Token::Op("-".to_string())).to(ast::BinOp::Sub))
|
|
||||||
.then(op_product.clone())
|
|
||||||
.repeated(),
|
|
||||||
)
|
|
||||||
.foldl(|left, (op, right)| {
|
.foldl(|left, (op, right)| {
|
||||||
let span = (left.span.0, left.span.1.start..right.span.1.end);
|
let span = (left.span.0, left.span.1.start..right.span.1.end);
|
||||||
ast::Expr::BinOp {
|
ast::Expr::BinOp {
|
||||||
@@ -766,14 +787,7 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = ScriptError> + Clo
|
|||||||
|
|
||||||
let op_shift = op_sum
|
let op_shift = op_sum
|
||||||
.clone()
|
.clone()
|
||||||
.then(
|
.then(shift_op.clone().then(op_sum.clone()).repeated())
|
||||||
just(Token::Op("<<".to_string()))
|
|
||||||
.to(ast::BinOp::Shl)
|
|
||||||
.or(just(Token::Op("#>>".to_string())).to(ast::BinOp::ShrU))
|
|
||||||
.or(just(Token::Op(">>".to_string())).to(ast::BinOp::ShrS))
|
|
||||||
.then(op_sum.clone())
|
|
||||||
.repeated(),
|
|
||||||
)
|
|
||||||
.foldl(|left, (op, right)| {
|
.foldl(|left, (op, right)| {
|
||||||
let span = (left.span.0, left.span.1.start..right.span.1.end);
|
let span = (left.span.0, left.span.1.start..right.span.1.end);
|
||||||
ast::Expr::BinOp {
|
ast::Expr::BinOp {
|
||||||
@@ -815,14 +829,7 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = ScriptError> + Clo
|
|||||||
|
|
||||||
let op_bit = op_cmp
|
let op_bit = op_cmp
|
||||||
.clone()
|
.clone()
|
||||||
.then(
|
.then(bit_op.clone().then(op_cmp.clone()).repeated())
|
||||||
just(Token::Op("&".to_string()))
|
|
||||||
.to(ast::BinOp::And)
|
|
||||||
.or(just(Token::Op("|".to_string())).to(ast::BinOp::Or))
|
|
||||||
.or(just(Token::Op("^".to_string())).to(ast::BinOp::Xor))
|
|
||||||
.then(op_cmp.clone())
|
|
||||||
.repeated(),
|
|
||||||
)
|
|
||||||
.foldl(|left, (op, right)| {
|
.foldl(|left, (op, right)| {
|
||||||
let span = (left.span.0, left.span.1.start..right.span.1.end);
|
let span = (left.span.0, left.span.1.start..right.span.1.end);
|
||||||
ast::Expr::BinOp {
|
ast::Expr::BinOp {
|
||||||
@@ -867,11 +874,45 @@ fn script_parser() -> impl Parser<Token, ast::Script, Error = ScriptError> + Clo
|
|||||||
.map_with_span(|expr, span| expr.with_span(span))
|
.map_with_span(|expr, span| expr.with_span(span))
|
||||||
.boxed();
|
.boxed();
|
||||||
|
|
||||||
|
let assign_op = identifier
|
||||||
|
.then(
|
||||||
|
product_op
|
||||||
|
.clone()
|
||||||
|
.or(sum_op.clone())
|
||||||
|
.or(shift_op.clone())
|
||||||
|
.or(bit_op.clone()),
|
||||||
|
)
|
||||||
|
.then_ignore(just(Token::Op("=".to_string())))
|
||||||
|
.then(expression.clone())
|
||||||
|
.map_with_span(|((name, op), value), span| {
|
||||||
|
ast::Expr::Assign {
|
||||||
|
name: name.clone(),
|
||||||
|
value: Box::new(
|
||||||
|
ast::Expr::BinOp {
|
||||||
|
left: Box::new(
|
||||||
|
ast::Expr::Variable {
|
||||||
|
name,
|
||||||
|
local_id: None,
|
||||||
|
}
|
||||||
|
.with_span(span.clone()),
|
||||||
|
),
|
||||||
|
right: Box::new(value),
|
||||||
|
op,
|
||||||
|
}
|
||||||
|
.with_span(span.clone()),
|
||||||
|
),
|
||||||
|
local_id: None,
|
||||||
|
}
|
||||||
|
.with_span(span)
|
||||||
|
})
|
||||||
|
.boxed();
|
||||||
|
|
||||||
block_expression
|
block_expression
|
||||||
.clone()
|
.clone()
|
||||||
.then(just(Token::Ctrl(';')).or_not())
|
.then(just(Token::Ctrl(';')).or_not())
|
||||||
.map_with_span(|(expr, semi), span| (expr.with_span(span), semi.is_none()))
|
.map_with_span(|(expr, semi), span| (expr.with_span(span), semi.is_none()))
|
||||||
.or(assign
|
.or(assign
|
||||||
|
.or(assign_op)
|
||||||
.or(expression.clone())
|
.or(expression.clone())
|
||||||
.then(just(Token::Ctrl(';')).to(false)))
|
.then(just(Token::Ctrl(';')).to(false)))
|
||||||
.repeated()
|
.repeated()
|
||||||
|
|||||||
@@ -6,3 +6,10 @@ fn xorshift(x: i32) -> i32 {
|
|||||||
let inline x = x ^ (x << 5);
|
let inline x = x ^ (x << 5);
|
||||||
x
|
x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn xorshift2(x: i32) -> i32 {
|
||||||
|
x ^= x << 13;
|
||||||
|
x ^= x #>> 17;
|
||||||
|
x ^= x << 5;
|
||||||
|
x
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user