v2 / vlib / v / build_constraint / lexing.v
103 lines · 96 sloc · 1.7 KB · acfa088b60dcac1dfec76cda3d2efe42d194cc8b
Raw
1module build_constraint
2
3// lexing:
4enum BTokenKind {
5 tfact // linux, tinyc, prod etc
6 tdefine // abc, gcboehm
7 tor // ||
8 tand // &&
9 tnot // !
10 tparen_open
11 tparen_close
12 teof
13}
14
15struct Token {
16 kind BTokenKind
17 value string
18}
19
20fn unexpected(c u8) IError {
21 return error('unexpected character `${rune(c)}`')
22}
23
24fn new_token(kind BTokenKind, value string) Token {
25 return Token{
26 kind: kind
27 value: value
28 }
29}
30
31fn new_op(kind BTokenKind) Token {
32 return new_token(kind, '')
33}
34
35fn new_span(kind BTokenKind, mut span []u8) Token {
36 t := new_token(kind, span.bytestr())
37 span.clear()
38 return t
39}
40
41fn lex(original string) ![]Token {
42 mut res := []Token{}
43 mut span := []u8{cap: original.len}
44 mut op := []u8{}
45 s := original.all_before('//')
46 for c in s {
47 match c {
48 ` `, `\t`, `\n` {}
49 `(` {
50 if span.len > 0 {
51 res << new_span(.tfact, mut span)
52 }
53 res << new_op(.tparen_open)
54 }
55 `)` {
56 if span.len > 0 {
57 res << new_span(.tfact, mut span)
58 }
59 res << new_op(.tparen_close)
60 }
61 `&`, `|` {
62 if span.len > 0 {
63 res << new_span(.tfact, mut span)
64 }
65 op << c
66 if op == [c, c] {
67 op.clear()
68 if c == `&` {
69 res << new_op(.tand)
70 } else if c == `|` {
71 res << new_op(.tor)
72 } else {
73 return unexpected(c)
74 }
75 }
76 if op.len == 2 {
77 return unexpected(c)
78 }
79 }
80 `?` {
81 res << new_span(.tdefine, mut span)
82 }
83 `!` {
84 res << new_op(.tnot)
85 if span.len > 0 {
86 return unexpected(c)
87 }
88 }
89 else {
90 if u8(c).is_alnum() || c in [`_`, `-`] {
91 span << c
92 } else {
93 return unexpected(c)
94 }
95 }
96 }
97 }
98 if span.len > 0 {
99 res << new_span(.tfact, mut span)
100 }
101 res << new_op(.teof)
102 return res
103}
104