The Perl Advent Calendar needs more articles for 2022. Submit your idea today!
#!perl

# $Id$

use strict;
use warnings;

use Test::More tests => 205;
use_ok 'CPU::Z80::Assembler';
use_ok 'CPU::Z80::Assembler::Expr';
use_ok 'Asm::Preproc::Line';
use_ok 'Iterator::Simple::Lookahead';
require_ok 't/test_utils.pl';

my $warn; 
$SIG{__WARN__} = sub {$warn = shift};
END { is $warn, undef, "no warnings"; }

# construct
isa_ok		my $line = Asm::Preproc::Line->new("hello\n", "f.asm", 10),
			'Asm::Preproc::Line';

isa_ok		my $expr = CPU::Z80::Assembler::Expr->new(line => $line),
			'CPU::Z80::Assembler::Expr';
is_deeply	$expr->child,	[], 	"no children";
is			$expr->line->text, 		"hello\n", 	"line text";
is			$expr->line->line_nr, 	10, 		"line line_nr";
is			$expr->line->file, 		"f.asm", 	"line file";
is			$expr->evaluate, 0,			"empty expression is 0";

# parse
our $stream;
$stream = z80lexer(
'#line 1 "FILE"
2+3:');
test_token_line("2+3:\n", 1, "FILE");
$expr->parse($stream);
is			$expr->line->text, 		"2+3:\n", 	"line text";
is			$expr->line->line_nr, 	1,	 		"line line_nr";
is			$expr->line->file, 		"FILE", 	"line file";
test_token(":", ":");
isa_ok $stream = Iterator::Simple::Lookahead->new(@{$expr->child}),
			'Iterator::Simple::Lookahead';
test_token('NUMBER', 2);
test_token("+", "+");
test_token('NUMBER', 3);
test_eof();
is			$expr->evaluate, 2+3,		"eval expression";


$stream = z80lexer(
'#line 2 "FILE"
4+5');
test_token_line("4+5\n", 2, "FILE");
$expr->parse($stream);
is			$expr->line->text, 		"4+5\n", 	"line text";
is			$expr->line->line_nr, 	2,	 		"line line_nr";
is			$expr->line->file, 		"FILE", 	"line file";
test_token("\n", "\n");
isa_ok $stream = Iterator::Simple::Lookahead->new(@{$expr->child}),
			'Iterator::Simple::Lookahead';
test_token('NUMBER', 4);
test_token("+", "+");
test_token('NUMBER', 5);
test_eof();
is			$expr->evaluate, 4+5,		"eval expression";

$stream = z80lexer(
'#line 3 "FILE"
6+7)
');
test_token_line("6+7)\n", 3, "FILE");
$expr->parse($stream);
is			$expr->line->text, 		"6+7)\n", 	"line text";
is			$expr->line->line_nr, 	3,	 		"line line_nr";
is			$expr->line->file, 		"FILE", 	"line file";
test_token(")", ")");
isa_ok $stream = Iterator::Simple::Lookahead->new(@{$expr->child}),
			'Iterator::Simple::Lookahead';
test_token('NUMBER', 6);
test_token("+", "+");
test_token('NUMBER', 7);
test_eof();
is			$expr->evaluate, 6+7,		"eval expression";

$stream = z80lexer(
'#line 3 "FILE"
6+7]
');
test_token_line("6+7]\n", 3, "FILE");
$expr->parse($stream);
is			$expr->line->text, 		"6+7]\n", 	"line text";
is			$expr->line->line_nr, 	3,	 		"line line_nr";
is			$expr->line->file, 		"FILE", 	"line file";
test_token("]", "]");
isa_ok $stream = Iterator::Simple::Lookahead->new(@{$expr->child}),
			'Iterator::Simple::Lookahead';
test_token('NUMBER', 6);
test_token("+", "+");
test_token('NUMBER', 7);
test_eof();
is			$expr->evaluate, 6+7,		"eval expression";

$stream = z80lexer(
'#line 3 "FILE"
6+7,
');
test_token_line("6+7,\n", 3, "FILE");
$expr->parse($stream);
is			$expr->line->text, 		"6+7,\n", 	"line text";
is			$expr->line->line_nr, 	3,	 		"line line_nr";
is			$expr->line->file, 		"FILE", 	"line file";
test_token(",", ",");
isa_ok $stream = Iterator::Simple::Lookahead->new(@{$expr->child}),
			'Iterator::Simple::Lookahead';
test_token('NUMBER', 6);
test_token("+", "+");
test_token('NUMBER', 7);
test_eof();
is			$expr->evaluate, 6+7,		"eval expression";

isa_ok $stream = Iterator::Simple::Lookahead->new(),
			'Iterator::Simple::Lookahead';
eval {$expr->parse($stream)};
is $@, "error: expected one of (\"(\" NAME NUMBER STRING) at EOF\n", "expression not found";
is			$expr->evaluate, 0,			"eval expression";


$stream = z80lexer(
'#line 4 "FILE"
,
');
eval {$expr->parse($stream)};
is $@, "FILE(4) : error: expected one of (\"(\" NAME NUMBER STRING) at \",\"\n", "expression not found";
is			$expr->evaluate, 0,			"eval expression";


$stream = z80lexer('(6]');
eval {$expr->parse($stream)};
is $@, "-(1) : error: expected \")\" at \"]\"\n", "Unbalanced parentheses";
is			$expr->evaluate, 0,			"eval expression";


$stream = z80lexer('(6');
eval {$expr->parse($stream)};
is $@, "-(1) : error: expected \")\" at \"\\n\"\n", "Unbalanced parentheses";
is			$expr->evaluate, 0,			"eval expression";