v2 / vlib / v / parser / messages.v
234 lines · 218 sloc · 5.72 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1module parser
2
3import v.ast
4import v.util
5import v.token
6import v.errors
7
8fn (mut p Parser) language_not_allowed_error(language ast.Language, pos token.Pos) {
9 upcase_language := language.str().to_upper_ascii()
10 p.error_with_pos('${upcase_language} code is not allowed in .${p.file_backend_mode}.v files, please move it to a .${language}.v file',
11 pos)
12}
13
14fn (mut p Parser) language_not_allowed_warning(language ast.Language, pos token.Pos) {
15 upcase_language := language.str().to_upper_ascii()
16 p.warn_with_pos('${upcase_language} code will not be allowed in pure .v files, please move it to a .${language}.v file instead',
17 pos)
18}
19
20fn (mut p Parser) check_for_impure_v(language ast.Language, pos token.Pos) {
21 if language == .v {
22 // pure V code is always allowed everywhere
23 return
24 } else {
25 match p.file_backend_mode {
26 .c {
27 if language != .c {
28 p.language_not_allowed_error(language, pos)
29 return
30 }
31 }
32 .js {
33 if language != .js {
34 p.language_not_allowed_error(language, pos)
35 return
36 }
37 }
38 else {}
39 }
40 }
41 if !p.pref.warn_impure_v {
42 // the stricter mode is not ON yet => allow everything for now
43 return
44 }
45 if p.file_backend_mode != language {
46 if p.file_backend_mode == .v {
47 if p.pref.is_bare {
48 return
49 }
50 p.language_not_allowed_warning(language, pos)
51 return
52 }
53 }
54}
55
56fn (mut p Parser) error(s string) ast.NodeError {
57 return p.error_with_pos(s, p.tok.pos())
58}
59
60fn (mut p Parser) warn(s string) {
61 p.warn_with_pos(s, p.tok.pos())
62}
63
64fn (mut p Parser) note(s string) {
65 p.note_with_pos(s, p.tok.pos())
66}
67
68fn (mut p Parser) error_with_pos(s string, pos token.Pos) ast.NodeError {
69 if p.should_abort {
70 // Even after abort, always advance the token to prevent infinite loops
71 // in parser code that doesn't check should_abort (e.g. fn_params loops).
72 if p.tok.kind != .eof {
73 p.next()
74 }
75 return ast.NodeError{
76 idx: if p.errors.len > 0 { p.errors.len - 1 } else { 0 }
77 pos: pos
78 }
79 }
80 // print_backtrace()
81 mut kind := 'error:'
82 file_path := if pos.file_idx < 0 { p.file_path } else { p.table.filelist[pos.file_idx] }
83 should_abort_after_print := p.pref.fatal_errors
84 || (p.pref.output_mode == .stdout && !p.pref.check_only && !p.is_vls)
85 if should_abort_after_print {
86 if p.pref.is_verbose {
87 print_backtrace()
88 kind = 'parser error:'
89 }
90 util.show_compiler_message(kind, pos: pos, file_path: file_path, message: s)
91 p.should_abort = true
92 }
93 p.errors << errors.Error{
94 file_path: file_path
95 pos: pos
96 reporter: .parser
97 message: s
98 }
99
100 // To avoid getting stuck after an error, the parser will always
101 // proceed to the next token in modes where parsing continues, or
102 // while it is unwinding after a printed error.
103 if (should_abort_after_print || p.pref.check_only || p.pref.only_check_syntax
104 || p.pref.output_mode == .silent) && p.tok.kind != .eof {
105 p.next()
106 }
107 return ast.NodeError{
108 idx: p.errors.len - 1
109 pos: pos
110 }
111}
112
113fn (mut p Parser) error_with_error(error errors.Error) {
114 if p.should_abort {
115 if p.tok.kind != .eof {
116 p.next()
117 }
118 return
119 }
120 mut kind := 'error:'
121 should_abort_after_print := p.pref.fatal_errors
122 || (p.pref.output_mode == .stdout && !p.pref.check_only)
123 if should_abort_after_print {
124 if p.pref.is_verbose {
125 print_backtrace()
126 kind = 'parser error:'
127 }
128 util.show_compiler_message(kind, error.CompilerMessage)
129 p.should_abort = true
130 }
131 if p.pref.message_limit >= 0 && p.errors.len >= p.pref.message_limit {
132 p.should_abort = true
133 return
134 }
135 p.errors << error
136 if (should_abort_after_print || p.pref.check_only || p.pref.only_check_syntax
137 || p.pref.output_mode == .silent) && p.tok.kind != .eof {
138 p.next()
139 }
140}
141
142fn (mut p Parser) warn_with_pos(s string, pos token.Pos) {
143 if p.should_abort {
144 return
145 }
146 if p.pref.warns_are_errors {
147 p.error_with_pos(s, pos)
148 return
149 }
150 if p.pref.skip_warnings {
151 return
152 }
153 file_path := if pos.file_idx < 0 { p.file_path } else { p.table.filelist[pos.file_idx] }
154 if p.pref.output_mode == .stdout && !p.pref.check_only {
155 util.show_compiler_message('warning:', pos: pos, file_path: file_path, message: s)
156 } else {
157 if p.pref.message_limit >= 0 && p.warnings.len >= p.pref.message_limit {
158 p.should_abort = true
159 return
160 }
161 p.warnings << errors.Warning{
162 file_path: file_path
163 pos: pos
164 reporter: .parser
165 message: s
166 }
167 }
168}
169
170fn (mut p Parser) note_with_pos(s string, pos token.Pos) {
171 if p.should_abort {
172 return
173 }
174 if p.pref.skip_warnings {
175 return
176 }
177 if p.pref.skip_notes {
178 return
179 }
180 if p.is_generated {
181 return
182 }
183 if p.pref.notes_are_errors {
184 p.error_with_pos(s, pos)
185 return
186 }
187 file_path := if pos.file_idx < 0 { p.file_path } else { p.table.filelist[pos.file_idx] }
188 if p.pref.output_mode == .stdout && !p.pref.check_only {
189 util.show_compiler_message('notice:', pos: pos, file_path: file_path, message: s)
190 } else {
191 p.notices << errors.Notice{
192 file_path: file_path
193 pos: pos
194 reporter: .parser
195 message: s
196 }
197 }
198}
199
200@[params]
201struct ParamsForUnexpected {
202pub:
203 got string
204 expecting string
205 prepend_msg string
206 additional_msg string
207}
208
209fn (mut p Parser) unexpected(params ParamsForUnexpected) ast.NodeError {
210 return p.unexpected_with_pos(p.tok.pos(), params)
211}
212
213fn (mut p Parser) unexpected_with_pos(pos token.Pos, params ParamsForUnexpected) ast.NodeError {
214 mut msg := if params.got != '' {
215 'unexpected ${params.got}'
216 } else {
217 'unexpected ${p.tok}'
218 }
219 if params.expecting != '' {
220 msg += ', expecting ${params.expecting}'
221 }
222 if params.prepend_msg != '' {
223 msg = '${params.prepend_msg} ' + msg
224 }
225 if params.additional_msg != '' {
226 msg += ', ${params.additional_msg}'
227 }
228 return p.error_with_pos(msg, pos)
229}
230
231fn (mut p Parser) chan_type_error() {
232 p.error_with_pos('`chan` has no type specified. Use `chan Type` instead of `chan`',
233 p.prev_tok.pos())
234}
235