lib/std/arch/rv64/asm/scanner/tests.rad 6.1 KiB raw
1
use std::mem;
2
use std::testing;
3
use std::lang::strings;
4
5
/// String pool used by assembler scanner tests.
6
static TEST_STRING_POOL: strings::Pool = strings::Pool { table: undefined, count: 0 };
7
8
/// Create a scanner for test input.
9
fn testScanner(source: *[u8]) -> super::Scanner {
10
    return super::scanner(super::SourceKind::String, source, &mut TEST_STRING_POOL);
11
}
12
13
/// Scanner recognizes assembler-specific sigils and scoped names.
14
@test fn testScanRegisterDirectiveAndLabelTokens() throws (testing::TestError) {
15
    let mut s = testScanner(
16
        ".text %sp @entry name::tail 42"
17
    );
18
    let directive = super::next(&mut s);
19
    try testing::expect(directive.kind == super::TokenKind::Directive);
20
    try testing::expect(mem::eq(directive.source, ".text"));
21
22
    let reg = super::next(&mut s);
23
    try testing::expect(reg.kind == super::TokenKind::Register);
24
    try testing::expect(mem::eq(reg.source, "%sp"));
25
26
    let label = super::next(&mut s);
27
    try testing::expect(label.kind == super::TokenKind::Label);
28
    try testing::expect(mem::eq(label.source, "@entry"));
29
30
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
31
    try testing::expect(super::next(&mut s).kind == super::TokenKind::ColonColon);
32
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
33
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Number);
34
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof);
35
}
36
37
/// Keyword-shaped text remains plain assembler identifiers.
38
@test fn testScanKeywordShapedAsmNamesRemainAsmTokens() throws (testing::TestError) {
39
    let mut s = testScanner(
40
        "and or not align addi .text @label"
41
    );
42
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
43
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
44
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
45
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
46
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Ident);
47
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Directive);
48
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Label);
49
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof);
50
}
51
52
/// Quoted labels can spell symbol names that are not identifier-shaped.
53
@test fn testScanQuotedLabelToken() throws (testing::TestError) {
54
    let mut s = testScanner(
55
        "@\"foo.bar.baz\""
56
    );
57
    let label = super::next(&mut s);
58
    try testing::expect(label.kind == super::TokenKind::QuotedLabel);
59
    try testing::expect(mem::eq(label.source, "@\"foo.bar.baz\""));
60
    try testing::expect(super::next(&mut s).kind == super::TokenKind::Eof);
61
}
62
63
/// Sigil-prefixed tokens require the name to start immediately after the sigil.
64
@test fn testScanSigilsRequireAdjacency() throws (testing::TestError) {
65
    let mut regScan = testScanner("% a0");
66
    try testing::expect(super::next(&mut regScan).kind == super::TokenKind::Invalid);
67
68
    let mut labelScan = testScanner("@ entry");
69
    try testing::expect(super::next(&mut labelScan).kind == super::TokenKind::Invalid);
70
71
    let mut directiveScan = testScanner(". text");
72
    try testing::expect(super::next(&mut directiveScan).kind == super::TokenKind::Invalid);
73
}
74
75
/// Scanner reaches EOF after trailing whitespace and comments.
76
@test fn testScanProgramEndingWithNewline() throws (testing::TestError) {
77
    let mut s = testScanner(
78
        ".text;\n@start\naddi %a0 %zero 42;\nsd %a0 8(%sp);\n// comment\nbeq %a0 %zero @done;\n@done\nret;\n"
79
    );
80
    loop {
81
        let tok = super::next(&mut s);
82
        if tok.kind == super::TokenKind::Eof {
83
            try testing::expect(tok.source.len == 0);
84
            return;
85
        }
86
    }
87
}
88
89
/// Signed numbers scan only the numeric formats supported by the assembler scanner.
90
@test fn testScanSignedHexAndUnsupportedNumericForms() throws (testing::TestError) {
91
    let mut s = testScanner(
92
        "+0x2a -0b10 45.5"
93
    );
94
    let mut tok = super::next(&mut s);
95
    try testing::expect(tok.kind == super::TokenKind::Number);
96
    try testing::expect(mem::eq(tok.source, "+0x2a"));
97
98
    set tok = super::next(&mut s);
99
    try testing::expect(tok.kind == super::TokenKind::Number);
100
    try testing::expect(mem::eq(tok.source, "-0"));
101
102
    set tok = super::next(&mut s);
103
    try testing::expect(tok.kind == super::TokenKind::Ident);
104
    try testing::expect(mem::eq(tok.source, "b10"));
105
106
    set tok = super::next(&mut s);
107
    try testing::expect(tok.kind == super::TokenKind::Number);
108
    try testing::expect(mem::eq(tok.source, "45"));
109
110
    set tok = super::next(&mut s);
111
    try testing::expect(tok.kind == super::TokenKind::Invalid);
112
    try testing::expect(mem::eq(tok.source, "expected directive name after `.`"));
113
114
    set tok = super::next(&mut s);
115
    try testing::expect(tok.kind == super::TokenKind::Number);
116
    try testing::expect(mem::eq(tok.source, "5"));
117
}
118
119
/// Unterminated string and character literals report invalid tokens.
120
@test fn testScanUnterminatedDelimitedLiterals() throws (testing::TestError) {
121
    let mut stringScan = testScanner("\"unterminated");
122
    let stringTok = super::next(&mut stringScan);
123
    try testing::expect(stringTok.kind == super::TokenKind::Invalid);
124
    try testing::expect(mem::eq(stringTok.source, "unterminated string"));
125
126
    let mut escapedStringScan = testScanner("\"unterminated\\");
127
    let escapedStringTok = super::next(&mut escapedStringScan);
128
    try testing::expect(escapedStringTok.kind == super::TokenKind::Invalid);
129
    try testing::expect(mem::eq(escapedStringTok.source, "unterminated string"));
130
131
    let mut charScan = testScanner("'x");
132
    let charTok = super::next(&mut charScan);
133
    try testing::expect(charTok.kind == super::TokenKind::Invalid);
134
    try testing::expect(mem::eq(charTok.source, "unterminated character"));
135
136
    let mut escapedCharScan = testScanner("'\\");
137
    let escapedCharTok = super::next(&mut escapedCharScan);
138
    try testing::expect(escapedCharTok.kind == super::TokenKind::Invalid);
139
    try testing::expect(mem::eq(escapedCharTok.source, "unterminated character"));
140
}