all: @[attr] syntax

This commit is contained in:
Alexander Medvednikov 2023-08-18 18:28:57 +03:00
parent f4eede8d23
commit aef83bae62
6 changed files with 37 additions and 8 deletions

View File

@ -23,6 +23,7 @@ pub:
kind AttrKind
ct_opt bool // true for [if user_defined_name?]
pos token.Pos
has_at bool // new syntax `@[attr]`
pub mut:
ct_expr Expr // .kind == comptime_define, for [if !name]
ct_evaled bool // whether ct_skip has been evaluated already

View File

@ -17,6 +17,9 @@ pub fn (mut f Fmt) attrs(attrs []ast.Attr) {
f.single_line_attrs(sorted_attrs[i..])
break
}
if attr.has_at {
f.write('@')
}
f.writeln('[${attr}]')
}
}
@ -35,6 +38,9 @@ pub fn (mut f Fmt) single_line_attrs(attrs []ast.Attr, options AttrsOptions) {
if options.inline {
f.write(' ')
}
if attrs[0].has_at {
f.write('@')
}
f.write('[')
for i, attr in sorted_attrs {
if i > 0 {

View File

@ -723,6 +723,14 @@ fn (mut p Parser) top_stmt() ast.Stmt {
}
}
}
.at {
if p.peek_tok.kind == .lsbr {
p.attributes()
continue
} else {
return p.error('@[attr] expected')
}
}
.lsbr {
// attrs are stored in `p.attrs`
p.attributes()
@ -1769,11 +1777,20 @@ fn (mut p Parser) is_attributes() bool {
// when is_top_stmt is true attrs are added to p.attrs
fn (mut p Parser) attributes() {
p.check(.lsbr)
mut is_at := false
if p.tok.kind == .lsbr {
// [attr]
p.check(.lsbr)
} else if p.tok.kind == .at {
// @[attr]
p.check(.at)
p.check(.lsbr)
is_at = true
}
mut has_ctdefine := false
for p.tok.kind != .rsbr {
start_pos := p.tok.pos()
attr := p.parse_attr()
attr := p.parse_attr(is_at)
if p.attrs.contains(attr.name) && attr.name != 'wasm_export' {
p.error_with_pos('duplicate attribute `${attr.name}`', start_pos.extend(p.prev_tok.pos()))
return
@ -1809,7 +1826,7 @@ fn (mut p Parser) attributes() {
}
}
fn (mut p Parser) parse_attr() ast.Attr {
fn (mut p Parser) parse_attr(is_at bool) ast.Attr {
mut kind := ast.AttrKind.plain
apos := p.prev_tok.pos()
if p.tok.kind == .key_unsafe {
@ -1882,6 +1899,7 @@ fn (mut p Parser) parse_attr() ast.Attr {
ct_expr: comptime_cond
ct_opt: comptime_cond_opt
pos: apos.extend(p.tok.pos())
has_at: is_at
}
}
@ -3431,7 +3449,7 @@ fn (mut p Parser) parse_number_literal() ast.Expr {
fn (mut p Parser) module_decl() ast.Module {
mut module_attrs := []ast.Attr{}
mut attrs_pos := p.tok.pos()
for p.tok.kind == .lsbr {
for p.tok.kind == .lsbr || p.tok.kind == .at {
p.attributes()
}
module_attrs << p.attrs
@ -3959,7 +3977,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
uses_exprs = true
}
mut attrs := []ast.Attr{}
if p.tok.kind == .lsbr {
if p.tok.kind == .lsbr || p.tok.kind == .at {
p.attributes()
attrs << p.attrs
enum_attrs[val] = attrs

View File

@ -269,7 +269,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
// Comments after type (same line)
prev_attrs := p.attrs
p.attrs = []
if p.tok.kind == .lsbr {
if p.tok.kind == .lsbr || p.tok.kind == .at {
p.inside_struct_attr_decl = true
// attrs are stored in `p.attrs`
p.attributes()

View File

@ -886,6 +886,10 @@ fn (mut s Scanner) text_scan() token.Token {
return s.new_token(.comma, '', 1)
}
`@` {
// @[attr]
if s.text[s.pos + 1] == `[` {
return s.new_token(.at, '', 1)
}
mut name := ''
if nextc != `\0` {
s.pos++

View File

@ -1,8 +1,8 @@
import json
enum Foo {
yay [json: 'A'; yay]
foo [foo; json: 'B']
yay @[json: 'A'; yay]
foo @[foo; json: 'B']
}
struct FooStruct {