11package annotation
22
3- import "strings"
3+ import (
4+ "fmt"
5+ "strings"
6+ )
7+
8+ type ParseError struct {
9+ Column int
10+ Message string
11+ }
12+
13+ func (e * ParseError ) Error () string {
14+ return e .Message
15+ }
16+
17+ func NewParseError (column int , message string ) * ParseError {
18+ return & ParseError {Column : column , Message : message }
19+ }
420
521type Parser struct {
622 text string
723
824 tokens []* Token
925 position int
26+ column int
1027}
1128
1229func NewParser (text string ) * Parser {
13- text = strings .TrimPrefix (text , "//" )
1430 return & Parser {text : text }
1531}
1632
17- func (p * Parser ) Parse () Annotation {
18- tokens , err := NewLexer (p .text ).Lex ()
33+ func (p * Parser ) Parse () (Annotation , error ) {
34+ var column = 0
35+ var text = p .text
36+ if strings .HasPrefix (text , "//" ) {
37+ column = 2
38+ text = strings .TrimPrefix (text , "//" )
39+ }
40+
41+ tokens , err := NewLexer (text ).Lex ()
1942 if err != nil {
20- return nil
43+ return nil , nil
2144 }
2245 if len (tokens ) == 0 {
23- return nil
46+ return nil , nil
2447 }
2548
2649 p .tokens = tokens
2750 p .position = 0
51+ p .column = column
2852
2953 return p .parse ()
3054}
3155
32- func (p * Parser ) parse () Annotation {
33- tag := p .consume (tokenTag )
34- if tag = = nil {
35- return nil
56+ func (p * Parser ) parse () ( Annotation , error ) {
57+ tag , err := p .consume (tokenTag )
58+ if err ! = nil {
59+ return nil , nil
3660 }
3761
3862 switch strings .ToLower (tag .Image ) {
3963 case "@required" :
40- return newSimpleAnnotation (Required )
64+ return newSimpleAnnotation (Required ), nil
4165 case "@consume" :
4266 return p .consumeAnnotation ()
4367 case "@produce" :
4468 return p .produceAnnotation ()
4569 case "@ignore" :
46- return newSimpleAnnotation (Ignore )
70+ return newSimpleAnnotation (Ignore ), nil
4771 case "@tag" , "@tags" :
48- return p .tags ()
72+ return p .tags (), nil
4973 case "@description" :
50- return p .description ()
74+ return p .description (), nil
5175 case "@summary" :
52- return p .summary ()
76+ return p .summary (), nil
5377 case "@id" :
54- return p .id ()
78+ return p .id (), nil
5579 case "@deprecated" :
56- return newSimpleAnnotation (Deprecated )
80+ return newSimpleAnnotation (Deprecated ), nil
81+ case "@security" :
82+ return p .security ()
5783 default : // unresolved plugin
58- return p .unresolved (tag )
84+ return p .unresolved (tag ), nil
5985 }
6086}
6187
62- func (p * Parser ) consume (typ TokenType ) * Token {
88+ func (p * Parser ) consume (typ TokenType ) ( * Token , error ) {
6389 for {
6490 t := p .lookahead ()
6591 if t != nil && t .Type == tokenWhiteSpace {
6692 p .position += 1
93+ p .column += len (t .Image )
6794 } else {
6895 break
6996 }
7097 }
7198
7299 t := p .lookahead ()
73- if t == nil || t .Type != typ {
74- return nil
100+ if t == nil {
101+ return nil , NewParseError (p .column , fmt .Sprintf ("expect %s, but got EOF" , tokenNameMap [typ ]))
102+ }
103+ if t .Type != typ {
104+ return nil , NewParseError (p .column , fmt .Sprintf ("expect %s, but got '%s'" , tokenNameMap [typ ], t .Image ))
75105 }
76106
77107 p .position += 1
78- return t
108+ p .column += len (t .Image )
109+ return t , nil
79110}
80111
81112func (p * Parser ) consumeAny () * Token {
@@ -85,6 +116,7 @@ func (p *Parser) consumeAny() *Token {
85116 }
86117
87118 p .position += 1
119+ p .column += len (t .Image )
88120 return t
89121}
90122
@@ -99,24 +131,27 @@ func (p *Parser) hasMore() bool {
99131 return len (p .tokens ) > p .position
100132}
101133
102- func (p * Parser ) consumeAnnotation () * ConsumeAnnotation {
103- ident := p .consume (tokenIdentifier )
104- if ident = = nil {
105- return nil
134+ func (p * Parser ) consumeAnnotation () ( * ConsumeAnnotation , error ) {
135+ ident , err := p .consume (tokenIdentifier )
136+ if err ! = nil {
137+ return nil , err
106138 }
107139 return & ConsumeAnnotation {
108140 ContentType : ident .Image ,
109- }
141+ }, nil
110142}
111143
112- func (p * Parser ) produceAnnotation () * ProduceAnnotation {
113- ident := p .consume (tokenIdentifier )
144+ func (p * Parser ) produceAnnotation () (* ProduceAnnotation , error ) {
145+ ident , err := p .consume (tokenIdentifier )
146+ if err != nil {
147+ return nil , err
148+ }
114149 if ident == nil {
115- return nil
150+ return nil , nil
116151 }
117152 return & ProduceAnnotation {
118153 ContentType : ident .Image ,
119- }
154+ }, nil
120155}
121156
122157func (p * Parser ) unresolved (tag * Token ) Annotation {
@@ -130,8 +165,10 @@ func (p *Parser) tags() Annotation {
130165 res := & TagAnnotation {}
131166 var tag []string
132167 for p .hasMore () {
133- ident := p .consume (tokenIdentifier )
134- tag = append (tag , ident .Image )
168+ ident , _ := p .consume (tokenIdentifier )
169+ if ident != nil {
170+ tag = append (tag , ident .Image )
171+ }
135172 }
136173 res .Tag = strings .Join (tag , " " )
137174 return res
@@ -163,3 +200,23 @@ func (p *Parser) id() Annotation {
163200 }
164201 return res
165202}
203+
204+ // @security name scope1 [...]
205+ func (p * Parser ) security () (* SecurityAnnotation , error ) {
206+ name , err := p .consume (tokenIdentifier )
207+ if err != nil {
208+ return nil , NewParseError (p .column , "expect name after @security" )
209+ }
210+ var security = SecurityAnnotation {
211+ Name : name .Image ,
212+ Params : make ([]string , 0 ),
213+ }
214+ for p .hasMore () {
215+ token := p .consumeAny ()
216+ if token .Type == tokenIdentifier {
217+ security .Params = append (security .Params , token .Image )
218+ }
219+ }
220+
221+ return & security , nil
222+ }
0 commit comments