parser: replace eat_line_end_comments() with configurable eat_comments() (#8636)

pull/8637/head^2
Lukas Neubert 2021-02-08 17:16:02 +01:00 committed by GitHub
parent 5abd49d9bc
commit cb1f63f765
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 51 additions and 53 deletions

View File

@ -99,7 +99,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
p.next() p.next()
mut comments := []ast.Comment{cap: 2 * left_comments.len + 1} mut comments := []ast.Comment{cap: 2 * left_comments.len + 1}
comments << left_comments comments << left_comments
comments << p.eat_comments() comments << p.eat_comments({})
mut right_comments := []ast.Comment{} mut right_comments := []ast.Comment{}
mut right := []ast.Expr{cap: left.len} mut right := []ast.Expr{cap: left.len}
if p.tok.kind == .key_go { if p.tok.kind == .key_go {
@ -113,7 +113,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
right, right_comments = p.expr_list() right, right_comments = p.expr_list()
} }
comments << right_comments comments << right_comments
end_comments := p.eat_line_end_comments() end_comments := p.eat_comments(same_line: true)
mut has_cross_var := false mut has_cross_var := false
if op == .decl_assign { if op == .decl_assign {
// a, b := a + 1, b // a, b := a + 1, b

View File

@ -41,7 +41,7 @@ fn (mut p Parser) array_init() ast.ArrayInit {
// [1,2,3] or [const]byte // [1,2,3] or [const]byte
for i := 0; p.tok.kind !in [.rsbr, .eof]; i++ { for i := 0; p.tok.kind !in [.rsbr, .eof]; i++ {
exprs << p.expr(0) exprs << p.expr(0)
ecmnts << p.eat_comments() ecmnts << p.eat_comments({})
if p.tok.kind == .comma { if p.tok.kind == .comma {
p.next() p.next()
} }

View File

@ -87,7 +87,7 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp
if fn_name in p.imported_symbols { if fn_name in p.imported_symbols {
fn_name = p.imported_symbols[fn_name] fn_name = p.imported_symbols[fn_name]
} }
comments := p.eat_line_end_comments() comments := p.eat_comments(same_line: true)
pos.update_last_line(p.prev_tok.line_nr) pos.update_last_line(p.prev_tok.line_nr)
return ast.CallExpr{ return ast.CallExpr{
name: fn_name name: fn_name
@ -121,7 +121,7 @@ pub fn (mut p Parser) call_args() []ast.CallArg {
if is_mut { if is_mut {
p.next() p.next()
} }
mut comments := p.eat_comments() mut comments := p.eat_comments({})
arg_start_pos := p.tok.position() arg_start_pos := p.tok.position()
mut array_decompose := false mut array_decompose := false
if p.tok.kind == .ellipsis { if p.tok.kind == .ellipsis {
@ -146,7 +146,7 @@ pub fn (mut p Parser) call_args() []ast.CallArg {
comments = []ast.Comment{} comments = []ast.Comment{}
} }
pos := arg_start_pos.extend(p.prev_tok.position()) pos := arg_start_pos.extend(p.prev_tok.position())
comments << p.eat_comments() comments << p.eat_comments({})
args << ast.CallArg{ args << ast.CallArg{
is_mut: is_mut is_mut: is_mut
share: table.sharetype_from_flags(is_shared, is_atomic) share: table.sharetype_from_flags(is_shared, is_atomic)

View File

@ -34,9 +34,9 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
p.tok.position() p.tok.position()
} }
if p.tok.kind == .key_else { if p.tok.kind == .key_else {
comments << p.eat_comments() comments << p.eat_comments({})
p.check(.key_else) p.check(.key_else)
comments << p.eat_comments() comments << p.eat_comments({})
if p.tok.kind == .key_match { if p.tok.kind == .key_match {
p.error('cannot use `match` with `if` statements') p.error('cannot use `match` with `if` statements')
return ast.IfExpr{} return ast.IfExpr{}
@ -84,7 +84,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
p.error('cannot use `match` with `if` statements') p.error('cannot use `match` with `if` statements')
return ast.IfExpr{} return ast.IfExpr{}
} }
comments << p.eat_comments() comments << p.eat_comments({})
mut cond := ast.Expr{} mut cond := ast.Expr{}
mut is_guard := false mut is_guard := false
// `if x := opt() {` // `if x := opt() {`
@ -93,9 +93,9 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
is_guard = true is_guard = true
var_pos := p.tok.position() var_pos := p.tok.position()
var_name := p.check_name() var_name := p.check_name()
comments << p.eat_comments() comments << p.eat_comments({})
p.check(.decl_assign) p.check(.decl_assign)
comments << p.eat_comments() comments << p.eat_comments({})
expr := p.expr(0) expr := p.expr(0)
cond = ast.IfGuardExpr{ cond = ast.IfGuardExpr{
var_name: var_name var_name: var_name
@ -111,7 +111,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
prev_guard = false prev_guard = false
cond = p.expr(0) cond = p.expr(0)
} }
comments << p.eat_comments() comments << p.eat_comments({})
end_pos := p.prev_tok.position() end_pos := p.prev_tok.position()
body_pos := p.tok.position() body_pos := p.tok.position()
p.inside_if = false p.inside_if = false
@ -129,7 +129,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr {
if is_guard { if is_guard {
p.close_scope() p.close_scope()
} }
comments = p.eat_comments() comments = p.eat_comments({})
if is_comptime { if is_comptime {
if p.tok.kind == .key_else { if p.tok.kind == .key_else {
p.error('use `\$else` instead of `else` in compile-time `if` branches') p.error('use `\$else` instead of `else` in compile-time `if` branches')
@ -168,7 +168,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
if !no_lcbr { if !no_lcbr {
p.check(.lcbr) p.check(.lcbr)
} }
comments := p.eat_comments() // comments before the first branch comments := p.eat_comments({}) // comments before the first branch
mut branches := []ast.MatchBranch{} mut branches := []ast.MatchBranch{}
for p.tok.kind != .eof { for p.tok.kind != .eof {
branch_first_pos := p.tok.position() branch_first_pos := p.tok.position()
@ -188,7 +188,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
for { for {
// Sum type match // Sum type match
parsed_type := p.parse_type() parsed_type := p.parse_type()
ecmnts << p.eat_comments() ecmnts << p.eat_comments({})
types << parsed_type types << parsed_type
exprs << ast.Type{ exprs << ast.Type{
typ: parsed_type typ: parsed_type
@ -205,7 +205,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
for { for {
p.inside_match_case = true p.inside_match_case = true
expr := p.expr(0) expr := p.expr(0)
ecmnts << p.eat_comments() ecmnts << p.eat_comments({})
p.inside_match_case = false p.inside_match_case = false
if p.tok.kind == .dotdot { if p.tok.kind == .dotdot {
p.error_with_pos('match only supports inclusive (`...`) ranges, not exclusive (`..`)', p.error_with_pos('match only supports inclusive (`...`) ranges, not exclusive (`..`)',
@ -238,7 +238,7 @@ fn (mut p Parser) match_expr() ast.MatchExpr {
p.close_scope() p.close_scope()
p.inside_match_body = false p.inside_match_body = false
pos := branch_first_pos.extend_with_last_line(branch_last_pos, p.prev_tok.line_nr) pos := branch_first_pos.extend_with_last_line(branch_last_pos, p.prev_tok.line_nr)
post_comments := p.eat_comments() post_comments := p.eat_comments({})
branches << ast.MatchBranch{ branches << ast.MatchBranch{
exprs: exprs exprs: exprs
ecmnts: ecmnts ecmnts: ecmnts
@ -405,7 +405,7 @@ fn (mut p Parser) select_expr() ast.SelectExpr {
pos: branch_first_pos.pos pos: branch_first_pos.pos
len: branch_last_pos.pos - branch_first_pos.pos + branch_last_pos.len len: branch_last_pos.pos - branch_first_pos.pos + branch_last_pos.len
} }
post_comments := p.eat_comments() post_comments := p.eat_comments({})
pos.update_last_line(p.prev_tok.line_nr) pos.update_last_line(p.prev_tok.line_nr)
if post_comments.len > 0 { if post_comments.len > 0 {
pos.last_line = post_comments.last().pos.last_line pos.last_line = post_comments.last().pos.last_line

View File

@ -598,25 +598,23 @@ pub fn (mut p Parser) comment_stmt() ast.ExprStmt {
} }
} }
pub fn (mut p Parser) eat_comments() []ast.Comment { struct EatCommentsConfig {
mut comments := []ast.Comment{} same_line bool // Only eat comments on the same line as the previous token
for { follow_up bool // Comments directly below the previous token as long as there is no empty line
if p.tok.kind != .comment {
break
}
comments << p.comment()
}
return comments
} }
pub fn (mut p Parser) eat_line_end_comments() []ast.Comment { pub fn (mut p Parser) eat_comments(cfg EatCommentsConfig) []ast.Comment {
line := p.prev_tok.line_nr mut line := p.prev_tok.line_nr
mut comments := []ast.Comment{} mut comments := []ast.Comment{}
for { for {
if p.tok.kind != .comment || p.tok.line_nr > line { if p.tok.kind != .comment || (cfg.same_line && p.tok.line_nr > line)
|| (cfg.follow_up && p.tok.line_nr > line + 1) {
break break
} }
comments << p.comment() comments << p.comment()
if cfg.follow_up {
line = p.prev_tok.line_nr
}
} }
return comments return comments
} }
@ -1558,7 +1556,7 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr {
// //
end_pos := p.prev_tok.position() end_pos := p.prev_tok.position()
pos := name_pos.extend(end_pos) pos := name_pos.extend(end_pos)
comments := p.eat_line_end_comments() comments := p.eat_comments(same_line: true)
mcall_expr := ast.CallExpr{ mcall_expr := ast.CallExpr{
left: left left: left
name: field_name name: field_name
@ -1919,7 +1917,7 @@ fn (mut p Parser) import_stmt() ast.Import {
return import_node return import_node
} }
} }
import_node.comments = p.eat_line_end_comments() import_node.comments = p.eat_comments(same_line: true)
p.imports[mod_alias] = mod_name p.imports[mod_alias] = mod_name
// if mod_name !in p.table.imports { // if mod_name !in p.table.imports {
p.table.imports << mod_name p.table.imports << mod_name
@ -1992,7 +1990,7 @@ fn (mut p Parser) const_decl() ast.ConstDecl {
p.error_with_pos('const declaration is missing closing `)`', const_pos) p.error_with_pos('const declaration is missing closing `)`', const_pos)
return ast.ConstDecl{} return ast.ConstDecl{}
} }
comments = p.eat_comments() comments = p.eat_comments({})
if p.tok.kind == .rpar { if p.tok.kind == .rpar {
break break
} }
@ -2043,7 +2041,7 @@ fn (mut p Parser) return_stmt() ast.Return {
first_pos := p.tok.position() first_pos := p.tok.position()
p.next() p.next()
// no return // no return
mut comments := p.eat_comments() mut comments := p.eat_comments({})
if p.tok.kind == .rcbr { if p.tok.kind == .rcbr {
return ast.Return{ return ast.Return{
comments: comments comments: comments
@ -2085,7 +2083,7 @@ fn (mut p Parser) global_decl() ast.GlobalDecl {
mut fields := []ast.GlobalField{} mut fields := []ast.GlobalField{}
mut comments := []ast.Comment{} mut comments := []ast.Comment{}
for { for {
comments = p.eat_comments() comments = p.eat_comments({})
if p.tok.kind == .rpar { if p.tok.kind == .rpar {
break break
} }
@ -2147,7 +2145,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
} }
name := p.prepend_mod(enum_name) name := p.prepend_mod(enum_name)
p.check(.lcbr) p.check(.lcbr)
enum_decl_comments := p.eat_comments() enum_decl_comments := p.eat_comments({})
mut vals := []string{} mut vals := []string{}
// mut default_exprs := []ast.Expr{} // mut default_exprs := []ast.Expr{}
mut fields := []ast.EnumField{} mut fields := []ast.EnumField{}
@ -2168,8 +2166,8 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
pos: pos pos: pos
expr: expr expr: expr
has_expr: has_expr has_expr: has_expr
comments: p.eat_line_end_comments() comments: p.eat_comments(same_line: true)
next_comments: p.eat_comments() next_comments: p.eat_comments({})
} }
} }
p.top_level_statement_end() p.top_level_statement_end()
@ -2248,7 +2246,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
// function type: `type mycallback = fn(string, int)` // function type: `type mycallback = fn(string, int)`
fn_name := p.prepend_mod(name) fn_name := p.prepend_mod(name)
fn_type := p.parse_fn_type(fn_name) fn_type := p.parse_fn_type(fn_name)
comments = p.eat_line_end_comments() comments = p.eat_comments(same_line: true)
return ast.FnTypeDecl{ return ast.FnTypeDecl{
name: fn_name name: fn_name
is_pub: is_pub is_pub: is_pub
@ -2296,7 +2294,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
} }
is_public: is_pub is_public: is_pub
}) })
comments = p.eat_line_end_comments() comments = p.eat_comments(same_line: true)
return ast.SumTypeDecl{ return ast.SumTypeDecl{
name: name name: name
is_pub: is_pub is_pub: is_pub
@ -2332,7 +2330,7 @@ fn (mut p Parser) type_decl() ast.TypeDecl {
p.error_with_pos('a type alias can not refer to itself: $name', decl_pos.extend(type_alias_pos)) p.error_with_pos('a type alias can not refer to itself: $name', decl_pos.extend(type_alias_pos))
return ast.AliasTypeDecl{} return ast.AliasTypeDecl{}
} }
comments = p.eat_line_end_comments() comments = p.eat_comments(same_line: true)
return ast.AliasTypeDecl{ return ast.AliasTypeDecl{
name: name name: name
is_pub: is_pub is_pub: is_pub

View File

@ -18,7 +18,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
is_stmt_ident := p.is_stmt_ident is_stmt_ident := p.is_stmt_ident
p.is_stmt_ident = false p.is_stmt_ident = false
if !p.pref.is_fmt { if !p.pref.is_fmt {
p.eat_comments() p.eat_comments({})
} }
// Prefix // Prefix
match p.tok.kind { match p.tok.kind {

View File

@ -234,7 +234,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
field_pos = field_start_pos.extend(type_pos) field_pos = field_start_pos.extend(type_pos)
} }
// Comments after type (same line) // Comments after type (same line)
comments << p.eat_comments() comments << p.eat_comments({})
if p.tok.kind == .lsbr { if p.tok.kind == .lsbr {
// attrs are stored in `p.attrs` // attrs are stored in `p.attrs`
p.attributes() p.attributes()
@ -252,7 +252,7 @@ fn (mut p Parser) struct_decl() ast.StructDecl {
else {} else {}
} }
has_default_expr = true has_default_expr = true
comments << p.eat_comments() comments << p.eat_comments({})
} }
// TODO merge table and ast Fields? // TODO merge table and ast Fields?
ast_fields << ast.StructField{ ast_fields << ast.StructField{
@ -343,7 +343,7 @@ fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit {
if !short_syntax { if !short_syntax {
p.check(.lcbr) p.check(.lcbr)
} }
pre_comments := p.eat_comments() pre_comments := p.eat_comments({})
mut fields := []ast.StructInitField{} mut fields := []ast.StructInitField{}
mut i := 0 mut i := 0
no_keys := p.peek_tok.kind != .colon && p.tok.kind != .rcbr && p.tok.kind != .ellipsis // `Vec{a,b,c} no_keys := p.peek_tok.kind != .colon && p.tok.kind != .rcbr && p.tok.kind != .ellipsis // `Vec{a,b,c}
@ -364,19 +364,19 @@ fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit {
// name will be set later in checker // name will be set later in checker
expr = p.expr(0) expr = p.expr(0)
field_pos = expr.position() field_pos = expr.position()
comments = p.eat_line_end_comments() comments = p.eat_comments(same_line: true)
} else if is_update_expr { } else if is_update_expr {
// struct updating syntax; f2 := Foo{ ...f, name: 'f2' } // struct updating syntax; f2 := Foo{ ...f, name: 'f2' }
p.check(.ellipsis) p.check(.ellipsis)
update_expr = p.expr(0) update_expr = p.expr(0)
update_expr_comments << p.eat_line_end_comments() update_expr_comments << p.eat_comments(same_line: true)
has_update_expr = true has_update_expr = true
} else { } else {
first_field_pos := p.tok.position() first_field_pos := p.tok.position()
field_name = p.check_name() field_name = p.check_name()
p.check(.colon) p.check(.colon)
expr = p.expr(0) expr = p.expr(0)
comments = p.eat_line_end_comments() comments = p.eat_comments(same_line: true)
last_field_pos := expr.position() last_field_pos := expr.position()
field_len := if last_field_pos.len > 0 { field_len := if last_field_pos.len > 0 {
last_field_pos.pos - first_field_pos.pos + last_field_pos.len last_field_pos.pos - first_field_pos.pos + last_field_pos.len
@ -393,8 +393,8 @@ fn (mut p Parser) struct_init(short_syntax bool) ast.StructInit {
if p.tok.kind == .comma { if p.tok.kind == .comma {
p.next() p.next()
} }
comments << p.eat_line_end_comments() comments << p.eat_comments(same_line: true)
nline_comments << p.eat_comments() nline_comments << p.eat_comments({})
if !is_update_expr { if !is_update_expr {
fields << ast.StructInitField{ fields << ast.StructInitField{
name: field_name name: field_name
@ -435,7 +435,7 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
interface_name := p.prepend_mod(p.check_name()).clone() interface_name := p.prepend_mod(p.check_name()).clone()
// println('interface decl $interface_name') // println('interface decl $interface_name')
p.check(.lcbr) p.check(.lcbr)
pre_comments := p.eat_comments() pre_comments := p.eat_comments({})
// Declare the type // Declare the type
reg_idx := p.table.register_type_symbol( reg_idx := p.table.register_type_symbol(
is_public: is_pub is_public: is_pub
@ -506,8 +506,8 @@ fn (mut p Parser) interface_decl() ast.InterfaceDecl {
if p.tok.kind.is_start_of_type() && p.tok.line_nr == line_nr { if p.tok.kind.is_start_of_type() && p.tok.line_nr == line_nr {
method.return_type = p.parse_type() method.return_type = p.parse_type()
} }
mcomments := p.eat_line_end_comments() mcomments := p.eat_comments(same_line: true)
mnext_comments := p.eat_comments() mnext_comments := p.eat_comments({})
method.comments = mcomments method.comments = mcomments
method.next_comments = mnext_comments method.next_comments = mnext_comments
methods << method methods << method