scanner: fix parsing multiple .amp

pull/5364/head
Adam Stankiewicz 2020-06-13 00:01:44 +02:00 committed by GitHub
parent af27963938
commit b3fc462a78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 98 additions and 18 deletions

View File

@ -505,7 +505,8 @@ pub fn (mut f Fmt) struct_field_expr(fexpr ast.Expr) {
fn (f &Fmt) type_to_str(t table.Type) string { fn (f &Fmt) type_to_str(t table.Type) string {
mut res := f.table.type_to_str(t) mut res := f.table.type_to_str(t)
if res.ends_with('_ptr') {
for res.ends_with('_ptr') {
// type_ptr => &type // type_ptr => &type
res = res[0..res.len - 4] res = res[0..res.len - 4]
start_pos := 2 * res.count('[]') start_pos := 2 * res.count('[]')

View File

@ -1,13 +1,19 @@
const ( const (
x = &Test{} x = &Test{}
y = []&Test{} y = []&Test{}
z = &[]&Test{} z = &[]&Test{}
xx = &&Test{}
yy = []&&Test{}
zz = &&[]&&Test{}
) )
fn test_type_ptr() { fn test_type_ptr() {
_ := &Test{} _ := &Test{}
_ := []&Test{} _ := []&Test{}
_ := &[]&Test{} _ := &[]&Test{}
_ := &&Test{}
_ := []&&Test{}
_ := &&[]&&Test{}
} }
struct Test { struct Test {

View File

@ -361,7 +361,7 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) {
mut args := []table.Arg{} mut args := []table.Arg{}
mut is_variadic := false mut is_variadic := false
// `int, int, string` (no names, just types) // `int, int, string` (no names, just types)
types_only := p.tok.kind in [.amp, .and, .ellipsis] || (p.peek_tok.kind == .comma && p.table.known_type(p.tok.lit)) || types_only := p.tok.kind in [.amp, .ellipsis] || (p.peek_tok.kind == .comma && p.table.known_type(p.tok.lit)) ||
p.peek_tok.kind == .rpar p.peek_tok.kind == .rpar
// TODO copy pasta, merge 2 branches // TODO copy pasta, merge 2 branches
if types_only { if types_only {

View File

@ -111,12 +111,8 @@ pub fn (mut p Parser) parse_type() table.Type {
p.next() p.next()
} }
// &Type // &Type
for p.tok.kind in [.and, .amp] { for p.tok.kind == .amp {
if p.tok.kind == .and { nr_muls++
nr_muls += 2
} else {
nr_muls++
}
p.next() p.next()
} }

View File

@ -641,6 +641,15 @@ pub fn (mut s Scanner) buffer_scan() token.Token {
} }
} }
[inline]
fn (s Scanner) look_ahead(n int) byte {
if s.pos + n < s.text.len {
return s.text[s.pos + n]
} else {
return `\0`
}
}
fn (mut s Scanner) text_scan() token.Token { fn (mut s Scanner) text_scan() token.Token {
// if s.comments_mode == .parse_comments { // if s.comments_mode == .parse_comments {
// println('\nscan()') // println('\nscan()')
@ -676,14 +685,14 @@ fn (mut s Scanner) text_scan() token.Token {
} }
// handle each char // handle each char
c := s.text[s.pos] c := s.text[s.pos]
nextc := if s.pos + 1 < s.text.len { s.text[s.pos + 1] } else { `\0` } nextc := s.look_ahead(1)
// name or keyword // name or keyword
if util.is_name_char(c) { if util.is_name_char(c) {
name := s.ident_name() name := s.ident_name()
// tmp hack to detect . in ${} // tmp hack to detect . in ${}
// Check if not .eof to prevent panic // Check if not .eof to prevent panic
next_char := if s.pos + 1 < s.text.len { s.text[s.pos + 1] } else { `\0` } next_char := s.look_ahead(1)
kind := token.keywords[name] kind := token.keywords[name]
if kind != .unknown { if kind != .unknown {
if kind == .key_fn { if kind == .key_fn {
@ -738,7 +747,7 @@ fn (mut s Scanner) text_scan() token.Token {
if c == `)` && s.is_inter_start { if c == `)` && s.is_inter_start {
s.is_inter_end = true s.is_inter_end = true
s.is_inter_start = false s.is_inter_start = false
next_char := if s.pos + 1 < s.text.len { s.text[s.pos + 1] } else { `\0` } next_char := s.look_ahead(1)
if next_char == s.quote { if next_char == s.quote {
s.is_inside_string = false s.is_inside_string = false
} }
@ -849,7 +858,9 @@ fn (mut s Scanner) text_scan() token.Token {
s.pos++ s.pos++
return s.new_token(.and_assign, '', 2) return s.new_token(.and_assign, '', 2)
} }
if nextc == `&` {
afternextc := s.look_ahead(2)
if nextc == `&` && afternextc.is_space() {
s.pos++ s.pos++
return s.new_token(.and, '', 2) return s.new_token(.and, '', 2)
} }

View File

@ -44,8 +44,7 @@ fn fn_name_mod_level_high_order(cb fn(int)) {
cb(1) cb(1)
} }
fn test_scan() { fn scan_kinds(text string) []token.Kind {
text := 'println(2 + 3)'
mut scanner := new_scanner(text, .skip_comments) mut scanner := new_scanner(text, .skip_comments)
mut token_kinds := []token.Kind{} mut token_kinds := []token.Kind{}
for { for {
@ -55,6 +54,11 @@ fn test_scan() {
} }
token_kinds << tok.kind token_kinds << tok.kind
} }
return token_kinds
}
fn test_scan() {
token_kinds := scan_kinds('println(2 + 3)')
assert token_kinds.len == 6 assert token_kinds.len == 6
assert token_kinds[0] == .name assert token_kinds[0] == .name
assert token_kinds[1] == .lpar assert token_kinds[1] == .lpar
@ -122,3 +126,55 @@ fn test_vmod_file() {
assert content.contains('version:') assert content.contains('version:')
assert content.contains('description:') assert content.contains('description:')
} }
fn test_reference() {
mut result := scan_kinds('true && false')
assert result.len == 3
assert result[0] == .key_true
assert result[1] == .and
assert result[2] == .key_false
result = scan_kinds('&foo')
assert result.len == 2
assert result[0] == .amp
assert result[1] == .name
result = scan_kinds('[]&foo')
assert result.len == 4
assert result[0] == .lsbr
assert result[1] == .rsbr
assert result[2] == .amp
assert result[3] == .name
result = scan_kinds('&[]&foo')
assert result.len == 5
assert result[0] == .amp
assert result[1] == .lsbr
assert result[2] == .rsbr
assert result[3] == .amp
assert result[4] == .name
result = scan_kinds('&&foo')
assert result.len == 3
assert result[0] == .amp
assert result[1] == .amp
assert result[2] == .name
result = scan_kinds('[]&&foo')
assert result.len == 5
assert result[0] == .lsbr
assert result[1] == .rsbr
assert result[2] == .amp
assert result[3] == .amp
assert result[4] == .name
result = scan_kinds('&&[]&&foo')
assert result.len == 7
assert result[0] == .amp
assert result[1] == .amp
assert result[2] == .lsbr
assert result[3] == .rsbr
assert result[4] == .amp
assert result[5] == .amp
assert result[6] == .name
}

View File

@ -274,7 +274,7 @@ pub fn (t &Table) known_type(name string) bool {
pub fn (t &Table) array_name(elem_type Type, nr_dims int) string { pub fn (t &Table) array_name(elem_type Type, nr_dims int) string {
elem_type_sym := t.get_type_symbol(elem_type) elem_type_sym := t.get_type_symbol(elem_type)
return 'array_${elem_type_sym.name}' + if elem_type.is_ptr() { return 'array_${elem_type_sym.name}' + if elem_type.is_ptr() {
'_ptr' '_ptr'.repeat(elem_type.nr_muls())
} else { } else {
'' ''
} + if nr_dims > 1 { } + if nr_dims > 1 {

View File

@ -0,0 +1,10 @@
fn process(foo &&int) int {
return **foo
}
fn test_ref_deref() {
foo := 12
bar := &foo
fiz := process(&bar)
assert fiz == 12
}