From a2dd73409b4808a784e1bebde85a6cdb3ef10274 Mon Sep 17 00:00:00 2001 From: Jay Hemnani <193022578+jayhemnani9910@users.noreply.github.com> Date: Sat, 24 Oct 2026 02:28:43 +0530 Subject: [PATCH 1/2] lexer: read / after a built-in variable as division --- lexer/src/lib.rs | 42 +++++++++++++++++++-------------------- tests/by-util/test_awk.rs | 9 +++++++++ 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/lexer/src/lib.rs b/lexer/src/lib.rs index d7eabad..5c82dae 100644 --- a/lexer/src/lib.rs +++ b/lexer/src/lib.rs @@ -183,47 +183,47 @@ pub enum Token<'a> { Lshift, #[token("rshift", |lex| parse_non_posix_keyword(lex, Token::Rshift))] Rshift, - #[regex("(awk::)?NR", accept_expression)] + #[regex("(awk::)?NR", accept_operator)] NrVariable, - #[regex("(awk::)?NF", accept_expression)] + #[regex("(awk::)?NF", accept_operator)] NfVariable, - #[regex("(awk::)?FS", accept_expression)] + #[regex("(awk::)?FS", accept_operator)] FsVariable, - #[regex("(awk::)?FPAT", accept_expression)] + #[regex("(awk::)?FPAT", accept_operator)] FpatVariable, - #[regex("(awk::)?FIELDWIDTHS", accept_expression)] + #[regex("(awk::)?FIELDWIDTHS", accept_operator)] FieldwidthsVariable, - #[regex("(awk::)?RS", accept_expression)] + #[regex("(awk::)?RS", accept_operator)] RsVariable, - #[regex("(awk::)?OFS", accept_expression)] + #[regex("(awk::)?OFS", accept_operator)] OfsVariable, - #[regex("(awk::)?ORS", accept_expression)] + #[regex("(awk::)?ORS", accept_operator)] OrsVariable, - #[regex("(awk::)?FILENAME", accept_expression)] + #[regex("(awk::)?FILENAME", accept_operator)] FilenameVariable, - #[regex("(awk::)?ARGC", accept_expression)] + #[regex("(awk::)?ARGC", accept_operator)] ArgcVariable, - #[regex("(awk::)?ARGV", accept_expression)] + #[regex("(awk::)?ARGV", accept_operator)] ArgvVariable, - #[regex("(awk::)?SUBSEP", accept_expression)] + #[regex("(awk::)?SUBSEP", accept_operator)] SubsepVariable, - #[regex("(awk::)?FNR", accept_expression)] + #[regex("(awk::)?FNR", accept_operator)] FnrVariable, - #[regex("(awk::)?ARGIND")] + #[regex("(awk::)?ARGIND", accept_operator)] ArgindVariable, - #[regex("(awk::)?OFMT", accept_expression)] + #[regex("(awk::)?OFMT", accept_operator)] OfmtVariable, - #[regex("(awk::)?RSTART", accept_expression)] + #[regex("(awk::)?RSTART", accept_operator)] RstartVariable, - #[regex("(awk::)?RLENGTH", accept_expression)] + #[regex("(awk::)?RLENGTH", accept_operator)] RlengthVariable, - #[regex("(awk::)?ENVIRON", accept_expression)] + #[regex("(awk::)?ENVIRON", accept_operator)] EnvironVariable, - #[regex("(awk::)?PROCINFO", accept_expression)] + #[regex("(awk::)?PROCINFO", accept_operator)] ProcinfoVariable, - #[regex("(awk::)?SYMTAB", accept_expression)] + #[regex("(awk::)?SYMTAB", accept_operator)] SymtabVariable, - #[regex("(awk::)?FUNCTAB", accept_expression)] + #[regex("(awk::)?FUNCTAB", accept_operator)] FunctabVariable, #[regex("(?&identifier)", Identifier::parse::<0>)] Identifier(Identifier<'a>), diff --git a/tests/by-util/test_awk.rs b/tests/by-util/test_awk.rs index 9f56c9f..75e019c 100644 --- a/tests/by-util/test_awk.rs +++ b/tests/by-util/test_awk.rs @@ -899,3 +899,12 @@ fn bare_regex_in_expression_matches_record() { .succeeds() .stdout_is("y 2\n2\n"); } + +#[test] +fn slash_after_special_variable_divides() { + ucmd() + .arg("{ print NR / 2, NF/NR } END { RSTART = 8; print RSTART / 2 / 2 }") + .pipe_in("a b\nc d\n") + .succeeds() + .stdout_only("0.5 2\n1 1\n2\n"); +} From f15885cc72635f2df69db56a15b311581d7c0e3a Mon Sep 17 00:00:00 2001 From: Jay Hemnani <193022578+jayhemnani9910@users.noreply.github.com> Date: Sun, 25 Oct 2026 00:15:14 +0530 Subject: [PATCH 2/2] tests: cover NR /= after a built-in variable --- lexer/src/tests.rs | 5 ++++- tests/by-util/test_awk.rs | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lexer/src/tests.rs b/lexer/src/tests.rs index c998bca..f7c6228 100644 --- a/lexer/src/tests.rs +++ b/lexer/src/tests.rs @@ -241,13 +241,16 @@ fn lexer_test_general_tokens() { fn lexer_test_regex_ambiguity() { let arena = Bump::new(); assert_eq!( - &lex(b"1/=1. a/=1", &arena, false, false), + &lex(b"1/=1. a/=1 NR/=1", &arena, false, false), &[ Token::Integer(1), Token::SlashAssign, Token::Number(1.), Token::Identifier(Identifier { literal: "a" }), Token::SlashAssign, + Token::Integer(1), + Token::NrVariable, + Token::SlashAssign, Token::Integer(1) ] ); diff --git a/tests/by-util/test_awk.rs b/tests/by-util/test_awk.rs index 75e019c..9571365 100644 --- a/tests/by-util/test_awk.rs +++ b/tests/by-util/test_awk.rs @@ -903,8 +903,8 @@ fn bare_regex_in_expression_matches_record() { #[test] fn slash_after_special_variable_divides() { ucmd() - .arg("{ print NR / 2, NF/NR } END { RSTART = 8; print RSTART / 2 / 2 }") + .arg("{ print NR / 2, NF/NR } END { RSTART = 8; print RSTART / 2 / 2; NR = 6; NR /= 2; print NR }") .pipe_in("a b\nc d\n") .succeeds() - .stdout_only("0.5 2\n1 1\n2\n"); + .stdout_only("0.5 2\n1 1\n2\n3\n"); }