scanner: cleanup, only v.parser now depends on v.scanner
parent
e9f764db4f
commit
e67bf674e3
|
@ -112,6 +112,7 @@ fn parse_args(args []string) (&pref.Preferences, string) {
|
|||
mut res := &pref.Preferences{}
|
||||
mut command := ''
|
||||
mut command_pos := 0
|
||||
res.is_fmt = util.is_fmt()
|
||||
// for i, arg in args {
|
||||
for i := 0; i < args.len; i++ {
|
||||
arg := args[i]
|
||||
|
|
|
@ -9,7 +9,7 @@ import v.util
|
|||
import v.vmod
|
||||
import v.checker
|
||||
import v.parser
|
||||
import v.scanner
|
||||
import v.errors
|
||||
import v.gen
|
||||
import v.gen.js
|
||||
import v.gen.x64
|
||||
|
@ -267,7 +267,7 @@ pub fn (b Builder) find_module_path(mod, fpath string) ?string {
|
|||
return error('module "$mod" not found in:\n$smodule_lookup_paths')
|
||||
}
|
||||
|
||||
fn (b &Builder) print_errors(errors []scanner.Error) {
|
||||
fn (b &Builder) print_errors(errors []errors.Error) {
|
||||
for err in errors {
|
||||
kind := if b.pref.is_verbose { '$err.reporter error #$b.checker.nr_errors:' } else { 'error:' }
|
||||
ferror := util.formatted_error(kind, err.message, err.file_path, err.pos)
|
||||
|
|
|
@ -9,7 +9,7 @@ import v.table
|
|||
import v.token
|
||||
import v.pref
|
||||
import v.util
|
||||
import v.scanner
|
||||
import v.errors
|
||||
import os
|
||||
|
||||
const (
|
||||
|
@ -21,8 +21,8 @@ pub struct Checker {
|
|||
mut:
|
||||
file ast.File
|
||||
nr_errors int
|
||||
errors []scanner.Error
|
||||
warnings []scanner.Warning
|
||||
errors []errors.Error
|
||||
warnings []errors.Warning
|
||||
error_lines []int // to avoid printing multiple errors for the same line
|
||||
expected_type table.Type
|
||||
fn_return_type table.Type // current function's return type
|
||||
|
@ -51,7 +51,7 @@ pub fn (mut c Checker) check(ast_file ast.File) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (mut c Checker) check2(ast_file ast.File) []scanner.Error {
|
||||
pub fn (mut c Checker) check2(ast_file ast.File) []errors.Error {
|
||||
c.file = ast_file
|
||||
for stmt in ast_file.stmts {
|
||||
c.stmt(stmt)
|
||||
|
@ -944,7 +944,7 @@ pub fn (mut c Checker) assign_stmt(assign_stmt mut ast.AssignStmt) {
|
|||
// check variablename for beginning with capital letter 'Abc'
|
||||
for ident in assign_stmt.left {
|
||||
is_decl := assign_stmt.op == .decl_assign
|
||||
if is_decl && scanner.contains_capital(ident.name) {
|
||||
if is_decl && util.contains_capital(ident.name) {
|
||||
c.error('variable names cannot contain uppercase letters, use snake_case instead',
|
||||
ident.pos)
|
||||
} else if is_decl && ident.kind != .blank_ident {
|
||||
|
@ -1930,8 +1930,8 @@ fn (mut c Checker) warn_or_error(message string, pos token.Position, warn bool)
|
|||
// print_backtrace()
|
||||
// }
|
||||
if warn {
|
||||
c.warnings << scanner.Warning{
|
||||
reporter: scanner.Reporter.checker
|
||||
c.warnings << errors.Warning{
|
||||
reporter: errors.Reporter.checker
|
||||
pos: pos
|
||||
file_path: c.file.path
|
||||
message: message
|
||||
|
@ -1939,8 +1939,8 @@ fn (mut c Checker) warn_or_error(message string, pos token.Position, warn bool)
|
|||
} else {
|
||||
c.nr_errors++
|
||||
if pos.line_nr !in c.error_lines {
|
||||
c.errors << scanner.Error{
|
||||
reporter: scanner.Reporter.checker
|
||||
c.errors << errors.Error{
|
||||
reporter: errors.Reporter.checker
|
||||
pos: pos
|
||||
file_path: c.file.path
|
||||
message: message
|
||||
|
@ -1951,6 +1951,6 @@ fn (mut c Checker) warn_or_error(message string, pos token.Position, warn bool)
|
|||
}
|
||||
|
||||
// for debugging only
|
||||
fn (p Checker) fileis(s string) bool {
|
||||
return p.file.path.contains(s)
|
||||
fn (c &Checker) fileis(s string) bool {
|
||||
return c.file.path.contains(s)
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module scanner
|
||||
module errors
|
||||
|
||||
import v.token
|
||||
|
||||
|
@ -16,3 +16,10 @@ pub struct Error {
|
|||
reporter Reporter
|
||||
backtrace string
|
||||
}
|
||||
|
||||
pub struct Warning {
|
||||
message string
|
||||
file_path string
|
||||
pos token.Position
|
||||
reporter Reporter
|
||||
}
|
|
@ -69,7 +69,7 @@ fn (mut p Parser) comp_if() ast.CompIf {
|
|||
// `$if os {` for a different target, skip everything inside
|
||||
// to avoid compilation errors (like including <windows.h> or calling WinAPI fns
|
||||
// on non-Windows systems)
|
||||
if !p.scanner.is_fmt && ((!is_not && os != p.pref.os) || (is_not && os == p.pref.os)) &&
|
||||
if !p.pref.is_fmt && ((!is_not && os != p.pref.os) || (is_not && os == p.pref.os)) &&
|
||||
!p.pref.output_cross_c {
|
||||
skip_os = true
|
||||
p.check(.lcbr)
|
||||
|
|
|
@ -5,7 +5,6 @@ module parser
|
|||
|
||||
import v.ast
|
||||
import v.table
|
||||
import v.scanner
|
||||
import v.token
|
||||
import v.util
|
||||
|
||||
|
@ -136,7 +135,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
|||
if p.tok.kind == .name {
|
||||
// TODO high order fn
|
||||
name = p.check_name()
|
||||
if !is_js && !is_c && !p.pref.translated && scanner.contains_capital(name) {
|
||||
if !is_js && !is_c && !p.pref.translated && util.contains_capital(name) {
|
||||
p.error('function names cannot contain uppercase letters, use snake_case instead')
|
||||
}
|
||||
if is_method && p.table.get_type_symbol(rec_type).has_method(name) {
|
||||
|
|
|
@ -195,7 +195,7 @@ pub fn (mut p Parser) open_scope() {
|
|||
}
|
||||
|
||||
pub fn (mut p Parser) close_scope() {
|
||||
if !p.pref.is_repl && !p.scanner.is_fmt {
|
||||
if !p.pref.is_repl && !p.pref.is_fmt {
|
||||
for v in p.scope.unused_vars() {
|
||||
if p.pref.is_prod {
|
||||
p.error_with_pos('Unused variable: $v.name', v.pos)
|
||||
|
|
|
@ -64,7 +64,7 @@ pub mut:
|
|||
// generating_vh bool
|
||||
fast bool // use tcc/x64 codegen
|
||||
enable_globals bool // allow __global for low level code
|
||||
// is_fmt bool
|
||||
is_fmt bool
|
||||
is_bare bool
|
||||
lookup_path []string
|
||||
output_cross_c bool
|
||||
|
|
|
@ -11,8 +11,6 @@ import v.util
|
|||
const (
|
||||
single_quote = `\'`
|
||||
double_quote = `"`
|
||||
//is_fmt = os.getenv('VEXE').contains('vfmt')
|
||||
is_fmt = os.executable().contains('vfmt')
|
||||
// char used as number separator
|
||||
num_sep = `_`
|
||||
)
|
||||
|
@ -66,14 +64,15 @@ pub fn new_scanner_file(file_path string, comments_mode CommentsMode) &Scanner {
|
|||
|
||||
// new scanner from string.
|
||||
pub fn new_scanner(text string, comments_mode CommentsMode) &Scanner {
|
||||
return &Scanner{
|
||||
s := &Scanner{
|
||||
text: text
|
||||
is_print_line_on_error: true
|
||||
is_print_colored_error: true
|
||||
is_print_rel_paths_on_error: true
|
||||
is_fmt: is_fmt
|
||||
is_fmt: util.is_fmt()
|
||||
comments_mode: comments_mode
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
pub fn (s &Scanner) add_fn_main_and_rescan() {
|
||||
|
@ -97,7 +96,7 @@ fn (s &Scanner) new_token(tok_kind token.Kind, lit string, len int) token.Token
|
|||
fn (s mut Scanner) ident_name() string {
|
||||
start := s.pos
|
||||
s.pos++
|
||||
for s.pos < s.text.len && (is_name_char(s.text[s.pos]) || s.text[s.pos].is_digit()) {
|
||||
for s.pos < s.text.len && (util.is_name_char(s.text[s.pos]) || s.text[s.pos].is_digit()) {
|
||||
s.pos++
|
||||
}
|
||||
name := s.text[start..s.pos]
|
||||
|
@ -340,11 +339,11 @@ fn (s mut Scanner) ident_number() string {
|
|||
fn (s mut Scanner) skip_whitespace() {
|
||||
// if s.is_vh { println('vh') return }
|
||||
for s.pos < s.text.len && s.text[s.pos].is_space() {
|
||||
if is_nl(s.text[s.pos]) && s.is_vh {
|
||||
if util.is_nl(s.text[s.pos]) && s.is_vh {
|
||||
return
|
||||
}
|
||||
// Count \r\n as one line
|
||||
if is_nl(s.text[s.pos]) && !s.expect('\r\n', s.pos - 1) {
|
||||
if util.is_nl(s.text[s.pos]) && !s.expect('\r\n', s.pos - 1) {
|
||||
s.inc_line_number()
|
||||
}
|
||||
s.pos++
|
||||
|
@ -395,7 +394,7 @@ pub fn (s mut Scanner) scan() token.Token {
|
|||
nextc := if s.pos + 1 < s.text.len { s.text[s.pos + 1] } else { `\0` }
|
||||
|
||||
// name or keyword
|
||||
if is_name_char(c) {
|
||||
if util.is_name_char(c) {
|
||||
name := s.ident_name()
|
||||
// tmp hack to detect . in ${}
|
||||
// Check if not .eof to prevent panic
|
||||
|
@ -595,10 +594,10 @@ pub fn (s mut Scanner) scan() token.Token {
|
|||
}
|
||||
if name == 'VEXE' {
|
||||
vexe := pref.vexe_path()
|
||||
return s.new_token(.string, cescaped_path(vexe), 5)
|
||||
return s.new_token(.string, util.cescaped_path(vexe), 5)
|
||||
}
|
||||
if name == 'FILE' {
|
||||
return s.new_token(.string, cescaped_path(os.real_path(s.file_path)), 5)
|
||||
return s.new_token(.string, util.cescaped_path(os.real_path(s.file_path)), 5)
|
||||
}
|
||||
if name == 'LINE' {
|
||||
return s.new_token(.string, (s.line_nr + 1).str(), 5)
|
||||
|
@ -820,7 +819,7 @@ fn (s &Scanner) current_column() int {
|
|||
return s.pos - s.last_nl_pos
|
||||
}
|
||||
|
||||
fn (s Scanner) count_symbol_before(p int, sym byte) int {
|
||||
fn (s &Scanner) count_symbol_before(p int, sym byte) int {
|
||||
mut count := 0
|
||||
for i := p; i >= 0; i-- {
|
||||
if s.text[i] != sym {
|
||||
|
@ -879,7 +878,7 @@ fn (s mut Scanner) ident_string() string {
|
|||
break
|
||||
}
|
||||
// $var
|
||||
if is_name_char(c) && prevc == `$` && !s.is_fmt && !is_raw && s.count_symbol_before(s.pos - 2, slash) % 2 == 0 {
|
||||
if util.is_name_char(c) && prevc == `$` && !s.is_fmt && !is_raw && s.count_symbol_before(s.pos - 2, slash) % 2 == 0 {
|
||||
s.is_inside_string = true
|
||||
s.is_inter_start = true
|
||||
s.pos -= 2
|
||||
|
@ -997,51 +996,6 @@ fn (s mut Scanner) inc_line_number() {
|
|||
}
|
||||
}
|
||||
|
||||
fn (s Scanner) line(n int) string {
|
||||
mut res := ''
|
||||
if n >= 0 && n < s.line_ends.len {
|
||||
nline_start := if n == 0 { 0 } else { s.line_ends[n - 1] }
|
||||
nline_end := s.line_ends[n]
|
||||
if nline_start <= nline_end {
|
||||
res = s.text[nline_start..nline_end]
|
||||
}
|
||||
}
|
||||
return res.trim_right('\r\n').trim_left('\r\n')
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn is_name_char(c byte) bool {
|
||||
return (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`) || c == `_`
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn is_nl(c byte) bool {
|
||||
return c == `\r` || c == `\n`
|
||||
}
|
||||
|
||||
fn contains_capital(s string) bool {
|
||||
for c in s {
|
||||
if c >= `A` && c <= `Z` {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HTTPRequest bad
|
||||
// HttpRequest good
|
||||
fn good_type_name(s string) bool {
|
||||
if s.len < 4 {
|
||||
return true
|
||||
}
|
||||
for i in 2 .. s.len {
|
||||
if s[i].is_capital() && s[i - 1].is_capital() && s[i - 2].is_capital() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
pub fn (s &Scanner) error(msg string) {
|
||||
pos := token.Position{
|
||||
line_nr: s.line_nr
|
||||
|
@ -1054,7 +1008,3 @@ pub fn (s &Scanner) error(msg string) {
|
|||
pub fn verror(s string) {
|
||||
util.verror('scanner error', s)
|
||||
}
|
||||
|
||||
pub fn cescaped_path(s string) string {
|
||||
return s.replace('\\', '\\\\')
|
||||
}
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
module scanner
|
||||
|
||||
import v.token
|
||||
|
||||
pub struct Warning {
|
||||
message string
|
||||
file_path string
|
||||
pos token.Position
|
||||
reporter Reporter
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
module util
|
||||
|
||||
import os
|
||||
|
||||
[inline]
|
||||
fn is_name_char(c byte) bool {
|
||||
return (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`) || c == `_`
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn is_nl(c byte) bool {
|
||||
return c == `\r` || c == `\n`
|
||||
}
|
||||
|
||||
fn contains_capital(s string) bool {
|
||||
for c in s {
|
||||
if c >= `A` && c <= `Z` {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HTTPRequest bad
|
||||
// HttpRequest good
|
||||
fn good_type_name(s string) bool {
|
||||
if s.len < 4 {
|
||||
return true
|
||||
}
|
||||
for i in 2 .. s.len {
|
||||
if s[i].is_capital() && s[i - 1].is_capital() && s[i - 2].is_capital() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
pub fn cescaped_path(s string) string {
|
||||
return s.replace('\\', '\\\\')
|
||||
}
|
||||
|
||||
pub fn is_fmt() bool {
|
||||
return os.executable().contains('vfmt')
|
||||
}
|
Loading…
Reference in New Issue