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