feat: 改行処理Phase 1 Smart advance完全実装 - 深度追跡でskip_newlines削減開始
✨ Smart advance()による自動改行処理を実装 - depth_tracking.rsで括弧深度(paren/brace/bracket)を自動管理 - 括弧内では改行を自動スキップ、演算子後の行継続も自動判定 - デフォルトで有効化(NYASH_SMART_ADVANCE=0で無効化可能) ♻️ skip_newlines()の段階的削除を開始 - primary.rsのオブジェクトリテラル内8箇所を削除(48→40箇所、17%削減) - 深度追跡により手動skip_newlines()が不要に 🧪 テスト結果 - 文区切り、演算子行継続、括弧内改行、次行演算子すべて成功 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -43,10 +43,74 @@ pub trait ParserUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/// 位置を1つ進める
|
||||
/// 位置を1つ進める(改行自動スキップ対応)
|
||||
fn advance(&mut self) {
|
||||
if !self.is_at_end() {
|
||||
// 現在のトークンで深度を更新(進める前)
|
||||
self.update_depth_before_advance();
|
||||
|
||||
*self.current_mut() += 1;
|
||||
|
||||
// 新しいトークンで深度を更新(進めた後)
|
||||
self.update_depth_after_advance();
|
||||
|
||||
// Phase 1: Smart advance - コンテキストに応じて改行を自動スキップ
|
||||
if self.should_auto_skip_newlines() {
|
||||
self.skip_newlines_internal();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// advance前の深度更新(閉じ括弧の処理)
|
||||
fn update_depth_before_advance(&mut self) {
|
||||
// デフォルト実装は何もしない(NyashParserでオーバーライド)
|
||||
}
|
||||
|
||||
/// advance後の深度更新(開き括弧の処理)
|
||||
fn update_depth_after_advance(&mut self) {
|
||||
// デフォルト実装は何もしない(NyashParserでオーバーライド)
|
||||
}
|
||||
|
||||
/// 改行を自動スキップすべきか判定
|
||||
fn should_auto_skip_newlines(&self) -> bool {
|
||||
// 環境変数でSmart advanceを有効化
|
||||
if std::env::var("NYASH_SMART_ADVANCE").ok().as_deref() != Some("1") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 現在のトークンがブレースやパーレンの後の場合
|
||||
if self.current() > 0 {
|
||||
let prev_token = &self.tokens()[self.current() - 1].token_type;
|
||||
match prev_token {
|
||||
TokenType::LBRACE | TokenType::LPAREN | TokenType::LBRACK => return true,
|
||||
// 演算子の後(行継続)
|
||||
TokenType::PLUS | TokenType::MINUS | TokenType::MULTIPLY |
|
||||
TokenType::DIVIDE | TokenType::MODULO |
|
||||
TokenType::AND | TokenType::OR |
|
||||
TokenType::DOT | TokenType::DoubleColon |
|
||||
TokenType::COMMA | TokenType::FatArrow => return true,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// 内部用改行スキップ(再帰防止)
|
||||
fn skip_newlines_internal(&mut self) {
|
||||
let allow_sc = std::env::var("NYASH_PARSER_ALLOW_SEMICOLON").ok().map(|v| {
|
||||
let lv = v.to_ascii_lowercase();
|
||||
lv == "1" || lv == "true" || lv == "on"
|
||||
}).unwrap_or(false);
|
||||
|
||||
while !self.is_at_end() {
|
||||
let is_nl = matches!(self.current_token().token_type, TokenType::NEWLINE);
|
||||
let is_sc = allow_sc && matches!(self.current_token().token_type, TokenType::SEMICOLON);
|
||||
if is_nl || is_sc {
|
||||
*self.current_mut() += 1; // advance()を使わず直接更新(再帰防止)
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
124
src/parser/depth_tracking.rs
Normal file
124
src/parser/depth_tracking.rs
Normal file
@ -0,0 +1,124 @@
|
||||
/*!
|
||||
* 深度追跡機能 - Smart advance用
|
||||
*
|
||||
* 括弧の深度を追跡し、改行の自動スキップを判定
|
||||
*/
|
||||
|
||||
use super::{NyashParser, ParserUtils};
|
||||
use crate::tokenizer::TokenType;
|
||||
|
||||
impl NyashParser {
|
||||
/// 現在の括弧深度を取得(デバッグ用)
|
||||
#[allow(dead_code)]
|
||||
pub fn get_depths(&self) -> (usize, usize, usize) {
|
||||
(self.paren_depth, self.brace_depth, self.bracket_depth)
|
||||
}
|
||||
|
||||
/// 括弧の深度が0以上か(何かの括弧内にいるか)
|
||||
pub fn in_brackets(&self) -> bool {
|
||||
self.paren_depth > 0 || self.brace_depth > 0 || self.bracket_depth > 0
|
||||
}
|
||||
}
|
||||
|
||||
impl ParserUtils for NyashParser {
|
||||
fn tokens(&self) -> &Vec<crate::tokenizer::Token> {
|
||||
&self.tokens
|
||||
}
|
||||
|
||||
fn current(&self) -> usize {
|
||||
self.current
|
||||
}
|
||||
|
||||
fn current_mut(&mut self) -> &mut usize {
|
||||
&mut self.current
|
||||
}
|
||||
|
||||
/// advance前の深度更新(現在のトークンを処理)
|
||||
fn update_depth_before_advance(&mut self) {
|
||||
if std::env::var("NYASH_DEBUG_DEPTH").ok().as_deref() == Some("1") {
|
||||
eprintln!("🔍 BEFORE advance: token={:?}, depths=({},{},{})",
|
||||
self.current_token().token_type, self.paren_depth, self.brace_depth, self.bracket_depth);
|
||||
}
|
||||
// 開き括弧の場合は深度を増やす(進む前に)
|
||||
match &self.current_token().token_type {
|
||||
TokenType::LPAREN => {
|
||||
self.paren_depth += 1;
|
||||
}
|
||||
TokenType::LBRACE => {
|
||||
self.brace_depth += 1;
|
||||
}
|
||||
TokenType::LBRACK => {
|
||||
self.bracket_depth += 1;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
/// advance後の深度更新(新しいトークンを処理)
|
||||
fn update_depth_after_advance(&mut self) {
|
||||
if !self.is_at_end() {
|
||||
// 閉じ括弧の場合は深度を減らす(進んだ後)
|
||||
match &self.current_token().token_type {
|
||||
TokenType::RPAREN => {
|
||||
self.paren_depth = self.paren_depth.saturating_sub(1);
|
||||
}
|
||||
TokenType::RBRACE => {
|
||||
self.brace_depth = self.brace_depth.saturating_sub(1);
|
||||
}
|
||||
TokenType::RBRACK => {
|
||||
self.bracket_depth = self.bracket_depth.saturating_sub(1);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if std::env::var("NYASH_DEBUG_DEPTH").ok().as_deref() == Some("1") {
|
||||
eprintln!("🔍 AFTER advance: token={:?}, depths=({},{},{})",
|
||||
self.current_token().token_type, self.paren_depth, self.brace_depth, self.bracket_depth);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 改行を自動スキップすべきか判定(NyashParser版)
|
||||
fn should_auto_skip_newlines(&self) -> bool {
|
||||
// Smart advanceをデフォルトで有効化(NYASH_SMART_ADVANCE=0で無効化可能)
|
||||
if std::env::var("NYASH_SMART_ADVANCE").ok().as_deref() == Some("0") {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 括弧内では常に改行をスキップ
|
||||
if self.in_brackets() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 行継続判定
|
||||
// 1. 直前のトークンが演算子等の場合
|
||||
if self.current() > 0 {
|
||||
let prev_token = &self.tokens[self.current() - 1].token_type;
|
||||
match prev_token {
|
||||
// 演算子の後(行継続)
|
||||
TokenType::PLUS | TokenType::MINUS | TokenType::MULTIPLY |
|
||||
TokenType::DIVIDE | TokenType::MODULO |
|
||||
TokenType::AND | TokenType::OR |
|
||||
TokenType::DOT | TokenType::DoubleColon |
|
||||
TokenType::COMMA | TokenType::FatArrow |
|
||||
TokenType::ASSIGN | TokenType::COLON => return true,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 現在のトークンが改行で、次のトークンが行継続演算子の場合
|
||||
if matches!(self.current_token().token_type, TokenType::NEWLINE) {
|
||||
if self.current() + 1 < self.tokens.len() {
|
||||
let next_token = &self.tokens[self.current() + 1].token_type;
|
||||
match next_token {
|
||||
// 次の行が演算子で始まる場合も行継続
|
||||
TokenType::DOT | TokenType::PLUS | TokenType::MINUS |
|
||||
TokenType::MULTIPLY | TokenType::DIVIDE | TokenType::MODULO |
|
||||
TokenType::AND | TokenType::OR | TokenType::DoubleColon => return true,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
@ -47,9 +47,9 @@ impl NyashParser {
|
||||
let ident_key_on = std::env::var("NYASH_ENABLE_MAP_IDENT_KEY").ok().as_deref()
|
||||
== Some("1")
|
||||
|| sugar_level.as_deref() != Some("basic"); // basic以外は全て許可(デフォルト含む)
|
||||
self.skip_newlines();
|
||||
// skip_newlines削除: brace_depth > 0なので自動スキップされる
|
||||
while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() {
|
||||
self.skip_newlines();
|
||||
// skip_newlines削除: brace_depth > 0なので自動スキップされる
|
||||
let key = match &self.current_token().token_type {
|
||||
TokenType::STRING(s) => {
|
||||
let v = s.clone();
|
||||
@ -74,18 +74,18 @@ impl NyashParser {
|
||||
});
|
||||
}
|
||||
};
|
||||
self.skip_newlines(); // Phase 0 Quick Fix: COLON前に改行スキップ
|
||||
// skip_newlines削除: brace_depth > 0なので自動スキップされる
|
||||
self.consume(TokenType::COLON)?;
|
||||
self.skip_newlines(); // Phase 0 Quick Fix: 値パース前に改行スキップ
|
||||
// skip_newlines削除: brace_depth > 0なので自動スキップされる
|
||||
let value_expr = self.parse_expression()?;
|
||||
entries.push((key, value_expr));
|
||||
self.skip_newlines(); // Phase 0 Quick Fix: COMMA判定前に改行スキップ
|
||||
// skip_newlines削除: brace_depth > 0なので自動スキップされる
|
||||
if self.match_token(&TokenType::COMMA) {
|
||||
self.advance();
|
||||
self.skip_newlines();
|
||||
// skip_newlines削除: brace_depth > 0なので自動スキップされる
|
||||
}
|
||||
}
|
||||
self.skip_newlines();
|
||||
// skip_newlines削除: brace_depth > 0なので自動スキップされる
|
||||
self.consume(TokenType::RBRACE)?;
|
||||
Ok(ASTNode::MapLiteral {
|
||||
entries,
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
mod common;
|
||||
mod cursor; // TokenCursor: 改行処理を一元管理
|
||||
mod declarations;
|
||||
mod depth_tracking; // Phase 1: 深度追跡機能(Smart advance用)
|
||||
pub mod entry_sugar; // helper to parse with sugar level
|
||||
mod expr;
|
||||
mod expr_cursor; // TokenCursorを使用した式パーサー(実験的)
|
||||
@ -138,22 +139,13 @@ pub struct NyashParser {
|
||||
std::collections::HashMap<String, std::collections::HashSet<String>>,
|
||||
/// 🔥 デバッグ燃料:無限ループ検出用制限値 (None = 無制限)
|
||||
pub(super) debug_fuel: Option<usize>,
|
||||
/// Phase 1: Smart advance用深度カウンタ(改行自動スキップ判定)
|
||||
pub(super) paren_depth: usize, // ()
|
||||
pub(super) brace_depth: usize, // {}
|
||||
pub(super) bracket_depth: usize, // []
|
||||
}
|
||||
|
||||
// Implement ParserUtils trait
|
||||
impl ParserUtils for NyashParser {
|
||||
fn tokens(&self) -> &Vec<Token> {
|
||||
&self.tokens
|
||||
}
|
||||
|
||||
fn current(&self) -> usize {
|
||||
self.current
|
||||
}
|
||||
|
||||
fn current_mut(&mut self) -> &mut usize {
|
||||
&mut self.current
|
||||
}
|
||||
}
|
||||
// ParserUtils trait implementation is in depth_tracking.rs
|
||||
|
||||
impl NyashParser {
|
||||
/// 新しいパーサーを作成
|
||||
@ -163,6 +155,9 @@ impl NyashParser {
|
||||
current: 0,
|
||||
static_box_dependencies: std::collections::HashMap::new(),
|
||||
debug_fuel: Some(100_000), // デフォルト値
|
||||
paren_depth: 0,
|
||||
brace_depth: 0,
|
||||
bracket_depth: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user