1//
2// AttributesParser.cpp
3//
4// Library: CppParser
5// Package: Attributes
6// Module: AttributesParser
7//
8// Copyright (c) 2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/CppParser/AttributesParser.h"
16#include "Poco/CppParser/CppToken.h"
17#include "Poco/Exception.h"
18
19
20using Poco::Token;
21using Poco::SyntaxException;
22
23
24namespace Poco {
25namespace CppParser {
26
27
28AttributesParser::AttributesParser(Attributes& attrs, std::istream& istr):
29 _attrs(attrs),
30 _tokenizer(istr)
31{
32}
33
34
35AttributesParser::~AttributesParser()
36{
37}
38
39
40void AttributesParser::parse()
41{
42 const Token* pNext = next();
43 if (!isEOF(pNext))
44 {
45 pNext = parseAttributes(pNext);
46 }
47 if (!isEOF(pNext))
48 throw Poco::SyntaxException("extra tokens found in attribute declaration");
49}
50
51
52const Token* AttributesParser::parseAttributes(const Token* pNext)
53{
54 pNext = parseAttribute(pNext);
55 while (isOperator(pNext, OperatorToken::OP_COMMA) || isIdentifier(pNext))
56 {
57 if (!isIdentifier(pNext)) pNext = next();
58 pNext = parseAttribute(pNext);
59 }
60 return pNext;
61}
62
63
64const Token* AttributesParser::parseAttribute(const Token* pNext)
65{
66 std::string id;
67 std::string value;
68 pNext = parseIdentifier(pNext, id);
69 if (isOperator(pNext, OperatorToken::OP_ASSIGN))
70 {
71 pNext = next();
72 if (isOperator(pNext, OperatorToken::OP_OPENBRACE))
73 {
74 pNext = parseComplexAttribute(pNext, id);
75 }
76 else if (isIdentifier(pNext) || isLiteral(pNext))
77 {
78 value = pNext->asString();
79 pNext = next();
80 }
81 else throw SyntaxException("bad attribute declaration");
82 }
83 setAttribute(id, value);
84 return pNext;
85}
86
87
88const Token* AttributesParser::parseComplexAttribute(const Token* pNext, const std::string& id)
89{
90 poco_assert_dbg (isOperator(pNext, OperatorToken::OP_OPENBRACE));
91
92 pNext = next();
93 std::string oldId(_id);
94 if (!_id.empty())
95 {
96 _id.append(".");
97 _id.append(id);
98 }
99 else _id = id;
100 pNext = parseAttributes(pNext);
101 _id = oldId;
102 if (isOperator(pNext, OperatorToken::OP_CLOSBRACE))
103 pNext = next();
104 else
105 throw SyntaxException("bad attribute declaration");
106
107 return pNext;
108}
109
110
111const Token* AttributesParser::parseIdentifier(const Token* pNext, std::string& id)
112{
113 if (isIdentifier(pNext))
114 {
115 id = pNext->asString();
116 pNext = next();
117 while (isOperator(pNext, OperatorToken::OP_PERIOD))
118 {
119 id.append(".");
120 pNext = next();
121 if (isIdentifier(pNext))
122 {
123 id.append(pNext->asString());
124 pNext = next();
125 }
126 else throw SyntaxException("identifier expected");
127 }
128 return pNext;
129 }
130 else throw SyntaxException("identifier expected");
131}
132
133
134void AttributesParser::setAttribute(const std::string& name, const std::string& value)
135{
136 std::string n;
137 if (!_id.empty())
138 {
139 n.append(_id);
140 n.append(".");
141 }
142 n.append(name);
143 _attrs.set(n, value);
144}
145
146
147} } // namespace Poco::CppParser
148