Skip to content

Commit 37ff460

Browse files
committed
parse instruction arguments both with and without the lookahead character; fix #203
1 parent b6978f9 commit 37ff460

File tree

6 files changed

+147
-53
lines changed

6 files changed

+147
-53
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "customasm"
3-
version = "0.13.5"
3+
version = "0.13.6"
44
edition = "2021"
55
authors = ["hlorenzi <https://hlorenzi.com>"]
66
description = "An assembler for custom, user-defined instruction sets!"

src/asm/matcher/mod.rs

Lines changed: 118 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,21 @@ pub struct InstructionMatch
2424
}
2525

2626

27+
impl InstructionMatch
28+
{
29+
pub fn is_same(&self, other: &InstructionMatch) -> bool
30+
{
31+
self.ruledef_ref.0 == other.ruledef_ref.0 &&
32+
self.rule_ref.0 == other.rule_ref.0 &&
33+
self.args.len() == other.args.len() &&
34+
self.args
35+
.iter()
36+
.zip(&other.args)
37+
.all(|(a, b)| a.is_same(&b))
38+
}
39+
}
40+
41+
2742
#[derive(Clone, Debug)]
2843
pub enum InstructionMatchResolution
2944
{
@@ -78,6 +93,32 @@ pub struct InstructionArgument
7893
}
7994

8095

96+
impl InstructionArgument
97+
{
98+
pub fn is_same(&self, other: &InstructionArgument) -> bool
99+
{
100+
if self.span != other.span
101+
{
102+
return false;
103+
}
104+
105+
match (&self.kind, &other.kind)
106+
{
107+
(InstructionArgumentKind::Expr(_),
108+
InstructionArgumentKind::Expr(_)) =>
109+
true,
110+
111+
(InstructionArgumentKind::Nested(ref a),
112+
InstructionArgumentKind::Nested(ref b)) =>
113+
a.is_same(b),
114+
115+
_ =>
116+
false,
117+
}
118+
}
119+
}
120+
121+
81122
#[derive(Clone, Debug)]
82123
pub enum InstructionArgumentKind
83124
{
@@ -379,7 +420,7 @@ pub fn match_instr(
379420
working_matches.extend(ruledef_matches);
380421
}
381422
}
382-
423+
383424
if working_matches.len() == 0
384425
{
385426
return vec![];
@@ -392,6 +433,10 @@ pub fn match_instr(
392433
.collect::<Vec<_>>();
393434

394435

436+
// Identical duplicate matches are already sorted consecutively
437+
matches.dedup_by(|a, b| a.is_same(b));
438+
439+
395440
// Calculate recursive "exact" pattern-part count for
396441
// each match
397442
for mtch in &mut matches
@@ -546,25 +591,45 @@ fn match_with_rule<'src>(
546591
asm::RuleParameterType::Signed(_) |
547592
asm::RuleParameterType::Integer(_) =>
548593
{
549-
return match_with_expr(
550-
defs,
551-
rule,
552-
walker,
553-
needs_consume_all_tokens,
554-
part_index,
555-
match_so_far);
594+
let mut result = vec![];
595+
596+
// Try both with and without lookahead character
597+
for enable_lookahead in [false, true]
598+
{
599+
result.extend(
600+
match_with_expr(
601+
defs,
602+
rule,
603+
walker.clone(),
604+
needs_consume_all_tokens,
605+
part_index,
606+
enable_lookahead,
607+
match_so_far.clone()));
608+
}
609+
610+
return result;
556611
}
557612

558613
asm::RuleParameterType::RuledefRef(ruledef_ref) =>
559614
{
560-
return match_with_nested_ruledef(
561-
defs,
562-
ruledef_ref,
563-
rule,
564-
walker,
565-
needs_consume_all_tokens,
566-
part_index,
567-
match_so_far);
615+
let mut result = vec![];
616+
617+
// Try both with and without lookahead character
618+
for enable_lookahead in [false, true]
619+
{
620+
result.extend(
621+
match_with_nested_ruledef(
622+
defs,
623+
ruledef_ref,
624+
rule,
625+
walker.clone(),
626+
needs_consume_all_tokens,
627+
part_index,
628+
enable_lookahead,
629+
match_so_far.clone()));
630+
}
631+
632+
return result;
568633
}
569634
}
570635
}
@@ -585,19 +650,23 @@ fn match_with_rule<'src>(
585650
fn match_with_expr<'src>(
586651
defs: &asm::ItemDefs,
587652
rule: &asm::Rule,
588-
walker: &mut syntax::Walker<'src>,
653+
mut walker: syntax::Walker<'src>,
589654
needs_consume_all_tokens: bool,
590655
at_pattern_part: usize,
591-
match_so_far: &mut InstructionMatch)
656+
enable_lookahead: bool,
657+
mut match_so_far: InstructionMatch)
592658
-> WorkingMatches<'src>
593659
{
594660
let walker_start = walker.next_useful_index();
595661

596-
let maybe_expr = parse_with_lookahead(
597-
&rule.pattern,
598-
at_pattern_part,
599-
walker,
600-
|walker| expr::parse_optional(walker));
662+
let Some(maybe_expr) =
663+
parse_with_lookahead(
664+
&rule.pattern,
665+
at_pattern_part,
666+
enable_lookahead,
667+
&mut walker,
668+
|walker| expr::parse_optional(walker))
669+
else { return vec![] };
601670

602671
let walker_end = walker.get_cursor_index();
603672
let walker_start = std::cmp::min(walker_start, walker_end);
@@ -627,35 +696,39 @@ fn match_with_expr<'src>(
627696
match_with_rule(
628697
defs,
629698
rule,
630-
walker,
699+
&mut walker,
631700
needs_consume_all_tokens,
632701
at_pattern_part + 1,
633-
match_so_far)
702+
&mut match_so_far)
634703
}
635704

636705

637706
fn match_with_nested_ruledef<'src>(
638707
defs: &asm::ItemDefs,
639708
nested_ruledef_ref: util::ItemRef<asm::Ruledef>,
640709
rule: &asm::Rule,
641-
walker: &mut syntax::Walker<'src>,
710+
mut walker: syntax::Walker<'src>,
642711
needs_consume_all_tokens: bool,
643712
at_pattern_part: usize,
644-
match_so_far: &mut InstructionMatch)
713+
enable_lookahead: bool,
714+
match_so_far: InstructionMatch)
645715
-> WorkingMatches<'src>
646716
{
647717
let walker_start = walker.next_useful_index();
648718
let walker_limit_prev = walker.get_cursor_limit();
649719

650-
let nested_matches = parse_with_lookahead(
651-
&rule.pattern,
652-
at_pattern_part,
653-
walker,
654-
|walker| match_with_ruledef(
655-
defs,
656-
nested_ruledef_ref,
657-
walker,
658-
false));
720+
let Some(nested_matches) =
721+
parse_with_lookahead(
722+
&rule.pattern,
723+
at_pattern_part,
724+
enable_lookahead,
725+
&mut walker,
726+
|walker| match_with_ruledef(
727+
defs,
728+
nested_ruledef_ref,
729+
walker,
730+
false))
731+
else { return vec![] };
659732

660733

661734
let mut matches = WorkingMatches::new();
@@ -729,11 +802,17 @@ fn match_with_nested_ruledef<'src>(
729802
fn parse_with_lookahead<'src, F, T>(
730803
pattern: &asm::RulePattern,
731804
at_pattern_part: usize,
805+
enable_lookahead: bool,
732806
walker: &mut syntax::Walker<'src>,
733807
parse_fn: F)
734-
-> T
808+
-> Option<T>
735809
where F: FnOnce(&mut syntax::Walker<'src>) -> T
736810
{
811+
if !enable_lookahead
812+
{
813+
return Some(parse_fn(walker));
814+
}
815+
737816
let maybe_lookahead_char = find_lookahead_char(
738817
pattern,
739818
at_pattern_part);
@@ -749,11 +828,11 @@ fn parse_with_lookahead<'src, F, T>(
749828
walker.set_cursor_limit(limit);
750829
let result = parse_fn(walker);
751830
walker.set_cursor_limit(prev_limit);
752-
return result;
831+
return Some(result);
753832
}
754833
}
755834

756-
parse_fn(walker)
835+
None
757836
}
758837

759838

tests/issue203/ok.asm

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#subruledef foo
2+
{
3+
add => 0xaa
4+
sub => 0xbb
5+
}
6+
7+
#ruledef Bar
8+
{
9+
{f: foo}d => f
10+
}
11+
12+
addd ; = 0xaa
13+
add d ; = 0xaa
14+
subd ; = 0xbb
15+
sub d ; = 0xbb

tests/rule_nested_ambiguous/err_no_match2.asm

Lines changed: 0 additions & 12 deletions
This file was deleted.

tests/rule_nested_ambiguous/ok.asm renamed to tests/rule_nested_ambiguous/ok1.asm

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,8 @@
1010
}
1111

1212
ld 0xaa$ ; = 0x5511aa
13+
ld 0xaa$$ ; = 0x5522aa
1314
ld 0x99 + 0x11$ ; = 0x5511aa
14-
ld (0x99 + 0x11)$ ; = 0x5511aa
15+
ld 0x99 + 0x11$$ ; = 0x5522aa
16+
ld (0x99 + 0x11)$ ; = 0x5511aa
17+
ld (0x99 + 0x11)$$ ; = 0x5522aa
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#ruledef
2+
{
3+
move to {x: u8} if {y: u8} => 0x55 @ x @ y
4+
}
5+
6+
input:
7+
.input:
8+
move to input if 0xaa ; = 0x5500aa
9+
move to .input if 0xaa ; = 0x5500aa

0 commit comments

Comments
 (0)