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 kind AttrKind
ct_opt bool // true for [if user_defined_name?] ct_opt bool // true for [if user_defined_name?]
pos token.Pos pos token.Pos
has_at bool // new syntax `@[attr]`
pub mut: pub mut:
ct_expr Expr // .kind == comptime_define, for [if !name] ct_expr Expr // .kind == comptime_define, for [if !name]
ct_evaled bool // whether ct_skip has been evaluated already 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..]) f.single_line_attrs(sorted_attrs[i..])
break break
} }
if attr.has_at {
f.write('@')
}
f.writeln('[${attr}]') f.writeln('[${attr}]')
} }
} }
@ -35,6 +38,9 @@ pub fn (mut f Fmt) single_line_attrs(attrs []ast.Attr, options AttrsOptions) {
if options.inline { if options.inline {
f.write(' ') f.write(' ')
} }
if attrs[0].has_at {
f.write('@')
}
f.write('[') f.write('[')
for i, attr in sorted_attrs { for i, attr in sorted_attrs {
if i > 0 { 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 { .lsbr {
// attrs are stored in `p.attrs` // attrs are stored in `p.attrs`
p.attributes() 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 // when is_top_stmt is true attrs are added to p.attrs
fn (mut p Parser) attributes() { 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 mut has_ctdefine := false
for p.tok.kind != .rsbr { for p.tok.kind != .rsbr {
start_pos := p.tok.pos() 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' { 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())) p.error_with_pos('duplicate attribute `${attr.name}`', start_pos.extend(p.prev_tok.pos()))
return 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 mut kind := ast.AttrKind.plain
apos := p.prev_tok.pos() apos := p.prev_tok.pos()
if p.tok.kind == .key_unsafe { if p.tok.kind == .key_unsafe {
@ -1882,6 +1899,7 @@ fn (mut p Parser) parse_attr() ast.Attr {
ct_expr: comptime_cond ct_expr: comptime_cond
ct_opt: comptime_cond_opt ct_opt: comptime_cond_opt
pos: apos.extend(p.tok.pos()) 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 { fn (mut p Parser) module_decl() ast.Module {
mut module_attrs := []ast.Attr{} mut module_attrs := []ast.Attr{}
mut attrs_pos := p.tok.pos() mut attrs_pos := p.tok.pos()
for p.tok.kind == .lsbr { for p.tok.kind == .lsbr || p.tok.kind == .at {
p.attributes() p.attributes()
} }
module_attrs << p.attrs module_attrs << p.attrs
@ -3959,7 +3977,7 @@ fn (mut p Parser) enum_decl() ast.EnumDecl {
uses_exprs = true uses_exprs = true
} }
mut attrs := []ast.Attr{} mut attrs := []ast.Attr{}
if p.tok.kind == .lsbr { if p.tok.kind == .lsbr || p.tok.kind == .at {
p.attributes() p.attributes()
attrs << p.attrs attrs << p.attrs
enum_attrs[val] = 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) // Comments after type (same line)
prev_attrs := p.attrs prev_attrs := p.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 p.inside_struct_attr_decl = true
// attrs are stored in `p.attrs` // attrs are stored in `p.attrs`
p.attributes() p.attributes()

View File

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

View File

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