🚀 feat: Multiple improvements for Nyash parser and LLVM backend
Parser improvements: - Added expression statement fallback in parse_statement() for flexible syntax - Fixed ternary operator to use PeekExpr instead of If AST (better lowering) - Added peek_token() check to avoid ?/?: operator conflicts LLVM Python improvements: - Added optional ESC_JSON_FIX environment flag for string concatenation - Improved PHI generation with better default handling - Enhanced substring tracking for esc_json pattern Documentation updates: - Updated language guide with peek expression examples - Added box theory diagrams to Phase 15 planning - Clarified peek vs when syntax differences These changes enable cleaner parser implementation for self-hosting, especially for handling digit conversion with peek expressions instead of 19-line if-else chains. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -25,7 +25,7 @@ impl NyashParser {
|
||||
/// パイプライン演算子: lhs |> f(a,b) / lhs |> obj.m(a)
|
||||
/// 基本方針: 右辺が関数呼び出しなら先頭に lhs を挿入。メソッド呼び出しなら引数の先頭に lhs を挿入。
|
||||
fn parse_pipeline(&mut self) -> Result<ASTNode, ParseError> {
|
||||
let mut expr = self.parse_coalesce()?;
|
||||
let mut expr = self.parse_ternary()?;
|
||||
|
||||
while self.match_token(&TokenType::PipeForward) {
|
||||
if !is_sugar_enabled() {
|
||||
@ -82,6 +82,28 @@ impl NyashParser {
|
||||
Ok(expr)
|
||||
}
|
||||
|
||||
/// 三項演算子: cond ? then : else
|
||||
/// Grammar (Phase 12.7): TernaryExpr = NullsafeExpr ( "?" Expr ":" Expr )?
|
||||
/// 実装: coalesce の上に差し込み、`cond ? a : b` を If式に変換する。
|
||||
fn parse_ternary(&mut self) -> Result<ASTNode, ParseError> {
|
||||
let cond = self.parse_coalesce()?;
|
||||
if self.match_token(&TokenType::QUESTION) {
|
||||
// consume '?' and parse then/else expressions
|
||||
self.advance();
|
||||
let then_expr = self.parse_expression()?;
|
||||
self.consume(TokenType::COLON)?; // ':'
|
||||
let else_expr = self.parse_expression()?;
|
||||
// Lower to PeekExpr over boolean scrutinee: peek cond { true => then, else => else }
|
||||
return Ok(ASTNode::PeekExpr {
|
||||
scrutinee: Box::new(cond),
|
||||
arms: vec![(crate::ast::LiteralValue::Bool(true), then_expr)],
|
||||
else_expr: Box::new(else_expr),
|
||||
span: Span::unknown(),
|
||||
});
|
||||
}
|
||||
Ok(cond)
|
||||
}
|
||||
|
||||
/// デフォルト値(??): x ?? y => peek x { null => y, else => x }
|
||||
fn parse_coalesce(&mut self) -> Result<ASTNode, ParseError> {
|
||||
let mut expr = self.parse_or()?;
|
||||
@ -591,7 +613,11 @@ impl NyashParser {
|
||||
expr = ASTNode::Call { callee: Box::new(expr), arguments, span: Span::unknown() };
|
||||
}
|
||||
} else if self.match_token(&TokenType::QUESTION) {
|
||||
// 後置 ?(Result伝播)
|
||||
// 後置 ?(Result伝播)。ただし三項演算子 '?:' と衝突するため、次トークンが ':' の場合は消費しない。
|
||||
// 例: (cond) ? then : else ではここで '?' を処理せず、上位の parse_ternary に委ねる。
|
||||
if self.peek_token() == &TokenType::COLON {
|
||||
break;
|
||||
}
|
||||
self.advance();
|
||||
expr = ASTNode::QMarkPropagate { expression: Box::new(expr), span: Span::unknown() };
|
||||
} else {
|
||||
|
||||
@ -86,8 +86,9 @@ impl NyashParser {
|
||||
self.parse_assignment_or_function_call()
|
||||
}
|
||||
_ => {
|
||||
let line = self.current_token().line;
|
||||
Err(ParseError::InvalidStatement { line })
|
||||
// Fallback: treat as expression statement
|
||||
// Allows forms like: print("x") or a bare literal as the last value in a block
|
||||
Ok(self.parse_expression()?)
|
||||
}
|
||||
};
|
||||
|
||||
@ -246,13 +247,12 @@ impl NyashParser {
|
||||
/// return文をパース
|
||||
pub(super) fn parse_return(&mut self) -> Result<ASTNode, ParseError> {
|
||||
self.advance(); // consume 'return'
|
||||
|
||||
// returnの後に式があるかチェック
|
||||
let value = if self.is_at_end() || self.match_token(&TokenType::NEWLINE) {
|
||||
// return単体の場合はvoidを返す
|
||||
// 許容: 改行をスキップしてから式有無を判定
|
||||
self.skip_newlines();
|
||||
// returnの後に式があるかチェック(RBRACE/EOFなら値なし)
|
||||
let value = if self.is_at_end() || self.match_token(&TokenType::RBRACE) {
|
||||
None
|
||||
} else {
|
||||
// 式をパースして返す
|
||||
Some(Box::new(self.parse_expression()?))
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user