Skip to content

Commit 0982172

Browse files
authored
Merge pull request #417 from grisenti/main
awk: correctly parse unterminated if
2 parents cecef8d + 2f7f00e commit 0982172

File tree

2 files changed

+87
-2
lines changed

2 files changed

+87
-2
lines changed

awk/compiler.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3047,6 +3047,91 @@ mod test {
30473047
);
30483048
}
30493049

3050+
#[test]
3051+
fn compile_unterminated_if() {
3052+
let (instructions, constant) = compile_stmt("if (1) \n 1");
3053+
assert_eq!(
3054+
instructions,
3055+
vec![
3056+
OpCode::PushConstant(0),
3057+
OpCode::JumpIfFalse(3),
3058+
OpCode::PushConstant(1),
3059+
OpCode::Pop,
3060+
]
3061+
);
3062+
assert_eq!(constant, vec![Constant::Number(1.0), Constant::Number(1.0)]);
3063+
3064+
let (instructions, constant) = compile_stmt("if (1) \n 1; \n else \n 2");
3065+
assert_eq!(
3066+
instructions,
3067+
vec![
3068+
OpCode::PushConstant(0),
3069+
OpCode::JumpIfFalse(4),
3070+
OpCode::PushConstant(1),
3071+
OpCode::Pop,
3072+
OpCode::Jump(3),
3073+
OpCode::PushConstant(2),
3074+
OpCode::Pop,
3075+
]
3076+
);
3077+
assert_eq!(
3078+
constant,
3079+
vec![
3080+
Constant::Number(1.0),
3081+
Constant::Number(1.0),
3082+
Constant::Number(2.0)
3083+
]
3084+
);
3085+
}
3086+
3087+
#[test]
3088+
fn compile_unterminated_while() {
3089+
let (instructions, constant) = compile_stmt("while (1) \n 1");
3090+
assert_eq!(
3091+
instructions,
3092+
vec![
3093+
OpCode::PushConstant(0),
3094+
OpCode::JumpIfFalse(4),
3095+
OpCode::PushConstant(1),
3096+
OpCode::Pop,
3097+
OpCode::Jump(-4),
3098+
]
3099+
);
3100+
assert_eq!(constant, vec![Constant::Number(1.0), Constant::Number(1.0)]);
3101+
}
3102+
3103+
#[test]
3104+
fn test_compile_unterminated_for() {
3105+
let (instructions, constant) = compile_stmt("for (i = 0; i < 10; i++) 1");
3106+
assert_eq!(
3107+
instructions,
3108+
vec![
3109+
OpCode::GlobalScalarRef(FIRST_GLOBAL_VAR),
3110+
OpCode::PushConstant(0),
3111+
OpCode::Assign,
3112+
OpCode::Pop,
3113+
OpCode::GetGlobal(FIRST_GLOBAL_VAR),
3114+
OpCode::PushConstant(1),
3115+
OpCode::Lt,
3116+
OpCode::JumpIfFalse(7),
3117+
OpCode::PushConstant(2),
3118+
OpCode::Pop,
3119+
OpCode::GlobalScalarRef(FIRST_GLOBAL_VAR),
3120+
OpCode::PostInc,
3121+
OpCode::Pop,
3122+
OpCode::Jump(-9),
3123+
]
3124+
);
3125+
assert_eq!(
3126+
constant,
3127+
vec![
3128+
Constant::Number(0.0),
3129+
Constant::Number(10.0),
3130+
Constant::Number(1.0),
3131+
]
3132+
);
3133+
}
3134+
30503135
#[test]
30513136
fn test_compile_break_inside_while_loop() {
30523137
let (instructions, _) = compile_stmt("while (1) { 1; break; }");

awk/grammar.pest

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ terminated_statement = _{
149149
| terminatable_statement ~ ";" ~ opt_newline
150150
}
151151

152-
t_if = { "if" ~ "(" ~ expr ~ ")" ~ opt_newline ~ terminated_statement ~ ("else" ~ opt_newline ~ terminated_statement)? }
152+
t_if = { "if" ~ "(" ~ expr ~ ")" ~ opt_newline ~ terminated_statement ~ (!"else" | "else" ~ opt_newline ~ terminated_statement) }
153153
t_while = { "while" ~ "(" ~ expr ~ ")" ~ opt_newline ~ terminated_statement }
154154
t_for = { "for" ~ "(" ~ simple_statement? ~ ";" ~ expr? ~ ";" ~ simple_statement? ~ ")" ~ opt_newline ~ terminated_statement }
155155
t_foreach = { "for" ~ "(" ~ name ~ "in" ~ name ~ ")" ~ opt_newline ~ terminated_statement }
@@ -163,7 +163,7 @@ unterminated_statement = _{
163163
| ut_foreach
164164
}
165165

166-
ut_if = { "if" ~ "(" ~ expr ~ ")" ~ opt_newline ~ (unterminated_statement | terminated_statement ~ "else" ~ opt_newline ~ unterminated_statement) }
166+
ut_if = { "if" ~ "(" ~ expr ~ ")" ~ opt_newline ~ (terminated_statement ~ "else" ~ opt_newline ~ unterminated_statement | unterminated_statement) }
167167
ut_while = { "while" ~ "(" ~ expr ~ ")" ~ opt_newline ~ unterminated_statement }
168168
ut_for = { "for" ~ "(" ~ simple_statement? ~ ";" ~ expr? ~ ";" ~ simple_statement? ~ ")" ~ opt_newline ~ unterminated_statement }
169169
ut_foreach = { "for" ~ "(" ~ name ~ in_op ~ name ~ ")" ~ opt_newline ~ unterminated_statement }

0 commit comments

Comments
 (0)