grammar: add '<<' shift-left safely (Phase 1); map to AST/MIR/VM; keep '>>' as legacy ARROW

- Tokenizer: add SHIFT_LEFT for '<<' (before <= detection)
- Parser: introduce parse_shift() layer; left-associative; only '<<' handled in Phase 1
- AST: add BinaryOperator::Shl and display
- MIR builder: map Shl -> BinaryOp::Shl
- Interpreter: implement Shl in both execution paths (integer-only, type error otherwise)

No change to '>>' (legacy ARROW remains). No runtime gate yet for SHL as it does not collide with existing syntax.
This commit is contained in:
Tomoaki
2025-09-08 03:44:55 +09:00
parent 2578120b23
commit 7c2b09c647
7 changed files with 53 additions and 3 deletions

View File

@ -231,13 +231,13 @@ impl NyashParser {
/// 項をパース: + - >>
fn parse_term(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_factor()?;
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_factor()?;
let right = self.parse_shift()?;
expr = ASTNode::Arrow {
sender: Box::new(expr),
receiver: Box::new(right),
@ -250,7 +250,7 @@ impl NyashParser {
_ => unreachable!(),
};
self.advance();
let right = self.parse_factor()?;
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);
@ -268,6 +268,22 @@ impl NyashParser {
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(),
};
}
Ok(expr)
}
/// 因子をパース: * /
fn parse_factor(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_unary()?;