-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathparser-attributes.c
100 lines (88 loc) · 2.45 KB
/
parser-attributes.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include "parser-attributes.h"
#include "config.h"
#include "doc.h"
#include "expr.h"
#include "lexer.h"
#include "parser-expr.h"
#include "parser-priv.h"
#include "style.h"
#include "token.h"
int
parser_attributes_peek(struct parser *pr, struct token **rparen,
unsigned int flags)
{
struct lexer_state s;
struct lexer *lx = pr->pr_lx;
int nattributes = 0;
lexer_peek_enter(lx, &s);
for (;;) {
struct token *tmp;
if (lexer_if(lx, TOKEN_ATTRIBUTE, NULL) &&
lexer_if_pair(lx, TOKEN_LPAREN, TOKEN_RPAREN, NULL,
rparen)) {
/* nothing */
} else if ((flags & PARSER_ATTRIBUTES_FUNC) &&
lexer_if(lx, TOKEN_IDENT, NULL) &&
lexer_if_pair(lx, TOKEN_LPAREN, TOKEN_RPAREN, NULL, &tmp) &&
lexer_if(lx, TOKEN_IDENT, NULL) &&
lexer_if(lx, TOKEN_LPAREN, NULL)) {
/* Possible attribute hidden behind cpp macro. */
*rparen = tmp;
} else {
break;
}
nattributes++;
}
lexer_peek_leave(lx, &s);
return nattributes > 0;
}
int
parser_attributes(struct parser *pr, struct doc *dc, struct doc **out,
unsigned int flags)
{
struct doc *def, *optional;
struct lexer *lx = pr->pr_lx;
struct token *end, *pv;
enum doc_type linetype;
int nattributes = 0;
if (!parser_attributes_peek(pr, &end, flags))
return parser_none(pr);
if (out == NULL)
out = &def;
linetype = lexer_back(lx, &pv) && token_has_line(pv, 1) ?
DOC_HARDLINE : DOC_LINE;
optional = doc_alloc(DOC_CONCAT, doc_alloc(DOC_OPTIONAL, dc));
for (;;) {
struct doc *concat;
struct token *rparen = NULL;
struct token *tk;
int error;
if (!lexer_if(lx, TOKEN_ATTRIBUTE, &tk) &&
!lexer_if(lx, TOKEN_IDENT, &tk))
break;
if ((flags & PARSER_ATTRIBUTES_LINE) || nattributes > 0)
doc_alloc(linetype, optional);
linetype = DOC_LINE;
concat = doc_alloc(DOC_CONCAT, doc_alloc(DOC_GROUP, optional));
parser_doc_token(pr, tk, concat);
if (lexer_expect(lx, TOKEN_LPAREN, &tk))
parser_doc_token(pr, tk, concat);
if (lexer_if(lx, TOKEN_LPAREN, &tk))
parser_doc_token(pr, tk, concat);
error = parser_expr(pr, out, &(struct parser_expr_arg){
.dc = concat,
.indent = style(pr->pr_st, ContinuationIndentWidth),
.flags = EXPR_EXEC_SOFTLINE,
});
if (error & HALT)
return parser_fail(pr);
if (lexer_expect(lx, TOKEN_RPAREN, &rparen))
parser_doc_token(pr, rparen, *out);
if (lexer_if(lx, TOKEN_RPAREN, &rparen))
parser_doc_token(pr, rparen, *out);
nattributes++;
if (rparen == end)
break;
}
return parser_good(pr);
}