sys

A set of unix utils in hare!
Log | Files | Refs | README

+test.ha (3261B)


      1 use lexical::lex;
      2 
      3 fn literal(
      4 	scan: *lex::scanner,
      5 	lexeme: const str,
      6 	user: nullable *opaque,
      7 ) (str | *lex::token | lex::error) = {
      8 	return lex::scan_token(scan, void, lexeme);
      9 };
     10 
     11 fn skip(
     12 	scan: *lex::scanner,
     13 	lexeme: const str,
     14 	user: nullable *opaque,
     15 ) (str | *lex::token | lex::error) = {
     16 	return lexeme;
     17 };
     18 
     19 def FOO = "FOO";
     20 def BAR = "BAR";
     21 def NAME = "NAME";
     22 
     23 def keywords = [
     24 	(FOO, "foo"),
     25 	(BAR, "bar"),
     26 ];
     27 
     28 def exprs = [
     29 	(NAME, `([a-z]|[A-Z])([a-z]|[A-Z]|[0-9]|_)*`),
     30 ];
     31 
     32 @test fn test_parse() void = {
     33 	let actions: []lex::action = [];
     34 	defer free(actions);
     35 	for (let keyword .. keywords) {
     36 		append(actions, lex::action {
     37 			expr = keyword.1,
     38 			cb = &literal,
     39 			name = keyword.0,
     40 			...
     41 		})!;
     42 	};
     43 	for (let expr .. exprs) {
     44 		append(actions, lex::action {
     45 			expr = expr.1,
     46 			cb = &literal,
     47 			name = expr.0,
     48 			...
     49 		})!;
     50 	};
     51 	append(actions, lex::action {
     52 		expr = "( |\t|\n|\r)+",
     53 		cb = &skip,
     54 		...
     55 	})!;
     56 	const be = lex::def_backend()!(actions)!;
     57 	defer lex::destroy(be);
     58 
     59 	const in = "foo bar foobar foo";
     60 	const lexer = lex::init(be, in);
     61 	defer lex::finish(&lexer);
     62 
     63 	const res = want(&lexer, BAR, lex::EOF);
     64 	assert(res is lex::error);
     65 	assert(res is lex::syntax);
     66 	const res = res as lex::syntax;
     67 	assert(res.1 == "Unexpected 'FOO', was expecting 'BAR', 'EOF'");
     68 	assert(res.0.line == 1);
     69 	assert(res.0.col == 1);
     70 	assert(res.0.off == 0);
     71 
     72 	const res = want(&lexer, BAR, FOO);
     73 	assert(res is *lex::token);
     74 	const res = res as *lex::token;
     75 	assert(res.name == FOO);
     76 	assert(res.lexeme == "foo");
     77 	assert(res.value is void);
     78 	assert(res.start.line == 1);
     79 	assert(res.start.col == 1);
     80 	assert(res.start.off == 0);
     81 	assert(res.end.line == 1);
     82 	assert(res.end.col == 3);
     83 	assert(res.end.off == 2);
     84 
     85 	const res = try(&lexer, FOO);
     86 	assert(res is void);
     87 
     88 	const res = want(&lexer, FOO);
     89 	assert(res is lex::error);
     90 	assert(res is lex::syntax);
     91 	const res = res as lex::syntax;
     92 	assert(res.1 == "Unexpected 'BAR', was expecting 'FOO'");
     93 	assert(res.0.line == 1);
     94 	assert(res.0.col == 5);
     95 	assert(res.0.off == 4);
     96 
     97 	const res = try(&lexer, BAR);
     98 	assert(res is *lex::token);
     99 	const res = res as *lex::token;
    100 	assert(res.name == BAR);
    101 	assert(res.lexeme == "bar");
    102 	assert(res.value is void);
    103 	assert(res.start.line == 1);
    104 	assert(res.start.col == 5);
    105 	assert(res.start.off == 4);
    106 	assert(res.end.line == 1);
    107 	assert(res.end.col == 7);
    108 	assert(res.end.off == 6);
    109 
    110 	const res = peek(&lexer, lex::EOF);
    111 	assert(res is void);
    112 
    113 	const res = peek(&lexer, NAME);
    114 	assert(res is *lex::token);
    115 
    116 	const res = want(&lexer, NAME);
    117 	assert(res is *lex::token);
    118 	const res = res as *lex::token;
    119 	assert(res.name == NAME);
    120 	assert(res.lexeme == "foobar");
    121 	assert(res.value is void);
    122 	assert(res.start.line == 1);
    123 	assert(res.start.col == 9);
    124 	assert(res.start.off == 8);
    125 	assert(res.end.line == 1);
    126 	assert(res.end.col == 14);
    127 	assert(res.end.off == 13);
    128 
    129 	const res = want(&lexer, FOO);
    130 	assert(res is *lex::token);
    131 
    132 	const res = want(&lexer, FOO);
    133 	assert(res is lex::error);
    134 	assert(res is lex::syntax);
    135 	const res = res as lex::syntax;
    136 	assert(res.1 == "Unexpected 'EOF', was expecting 'FOO'");
    137 	assert(res.0.line == 1);
    138 	assert(res.0.col == 19);
    139 	assert(res.0.off == 18);
    140 
    141 	const res = want(&lexer, lex::EOF);
    142 	assert(res is *lex::token);
    143 };