grammar: introduce bitwise ops & shifts; retire legacy >> ARROW

- Tokenizer: add tokens for << >> & | ^ (SHIFT_LEFT/RIGHT, BIT_AND/OR/XOR); keep ||, &&, |>
- Parser: precedence layers for bit ops (| ^ &) and shift (<< >>); remove >> Arrow production
- AST: add BitAnd/BitOr/BitXor/Shr with Display
- MIR builder: map bit ops and Shr to MIR BinaryOp
- Interpreter: implement integer-only bit ops and shifts, mask shift count to 0..63

Compatibility: legacy >> Arrow removed from parser; use |> for pipeline.
This commit is contained in:
Tomoaki
2025-09-08 03:54:34 +09:00
parent 7c2b09c647
commit 08d9b71297
6 changed files with 169 additions and 46 deletions

View File

@ -133,7 +133,7 @@ impl NyashParser {
/// AND演算子をパース: &&
fn parse_and(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_equality()?;
let mut expr = self.parse_bit_or()?;
while self.match_token(&TokenType::AND) {
let operator = BinaryOperator::And;
@ -153,6 +153,42 @@ impl NyashParser {
Ok(expr)
}
/// ビットOR: |
fn parse_bit_or(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_bit_xor()?;
while self.match_token(&TokenType::BIT_OR) {
let operator = BinaryOperator::BitOr;
self.advance();
let right = self.parse_bit_xor()?;
expr = ASTNode::BinaryOp { operator, left: Box::new(expr), right: Box::new(right), span: Span::unknown() };
}
Ok(expr)
}
/// ビットXOR: ^
fn parse_bit_xor(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_bit_and()?;
while self.match_token(&TokenType::BIT_XOR) {
let operator = BinaryOperator::BitXor;
self.advance();
let right = self.parse_bit_and()?;
expr = ASTNode::BinaryOp { operator, left: Box::new(expr), right: Box::new(right), span: Span::unknown() };
}
Ok(expr)
}
/// ビットAND: &
fn parse_bit_and(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_equality()?;
while self.match_token(&TokenType::BIT_AND) {
let operator = BinaryOperator::BitAnd;
self.advance();
let right = self.parse_equality()?;
expr = ASTNode::BinaryOp { operator, left: Box::new(expr), right: Box::new(right), span: Span::unknown() };
}
Ok(expr)
}
/// 等値演算子をパース: == !=
fn parse_equality(&mut self) -> Result<ASTNode, ParseError> {
@ -229,57 +265,51 @@ impl NyashParser {
Ok(expr)
}
/// 項をパース: + - >>
/// 項をパース: + -
fn parse_term(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_shift()?;
while self.match_token(&TokenType::PLUS) || self.match_token(&TokenType::MINUS) || self.match_token(&TokenType::ARROW) {
if self.match_token(&TokenType::ARROW) {
// >> Arrow演算子
self.advance();
let right = self.parse_shift()?;
expr = ASTNode::Arrow {
sender: Box::new(expr),
receiver: Box::new(right),
span: Span::unknown(),
};
} else {
let operator = match &self.current_token().token_type {
TokenType::PLUS => BinaryOperator::Add,
TokenType::MINUS => BinaryOperator::Subtract,
_ => unreachable!(),
};
self.advance();
let right = self.parse_shift()?;
if std::env::var("NYASH_GRAMMAR_DIFF").ok().as_deref() == Some("1") {
let name = match operator { BinaryOperator::Add=>"add", BinaryOperator::Subtract=>"sub", _=>"term" };
let ok = crate::grammar::engine::get().syntax_is_allowed_binop(name);
if !ok { eprintln!("[GRAMMAR-DIFF][Parser] binop '{}' not allowed by syntax rules", name); }
}
expr = ASTNode::BinaryOp {
operator,
left: Box::new(expr),
right: Box::new(right),
span: Span::unknown(),
};
while self.match_token(&TokenType::PLUS) || self.match_token(&TokenType::MINUS) {
let operator = match &self.current_token().token_type {
TokenType::PLUS => BinaryOperator::Add,
TokenType::MINUS => BinaryOperator::Subtract,
_ => unreachable!(),
};
self.advance();
let right = self.parse_shift()?;
if std::env::var("NYASH_GRAMMAR_DIFF").ok().as_deref() == Some("1") {
let name = match operator { BinaryOperator::Add=>"add", BinaryOperator::Subtract=>"sub", _=>"term" };
let ok = crate::grammar::engine::get().syntax_is_allowed_binop(name);
if !ok { eprintln!("[GRAMMAR-DIFF][Parser] binop '{}' not allowed by syntax rules", name); }
}
expr = ASTNode::BinaryOp {
operator,
left: Box::new(expr),
right: Box::new(right),
span: Span::unknown(),
};
}
Ok(expr)
}
/// シフトをパース: << のみPhase 1
/// シフトをパース: << >>
fn parse_shift(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_factor()?;
while self.match_token(&TokenType::SHIFT_LEFT) {
self.advance(); // consume '<<'
let rhs = self.parse_factor()?;
expr = ASTNode::BinaryOp {
operator: BinaryOperator::Shl,
left: Box::new(expr),
right: Box::new(rhs),
span: Span::unknown(),
};
loop {
if self.match_token(&TokenType::SHIFT_LEFT) {
self.advance();
let rhs = self.parse_factor()?;
expr = ASTNode::BinaryOp { operator: BinaryOperator::Shl, left: Box::new(expr), right: Box::new(rhs), span: Span::unknown() };
continue;
}
if self.match_token(&TokenType::SHIFT_RIGHT) {
self.advance();
let rhs = self.parse_factor()?;
expr = ASTNode::BinaryOp { operator: BinaryOperator::Shr, left: Box::new(expr), right: Box::new(rhs), span: Span::unknown() };
continue;
}
break;
}
Ok(expr)
}