|
1 /* This file is part of QJSon |
|
2 * |
|
3 * Copyright (C) 2008 Flavio Castelli <flavio.castelli@gmail.com> |
|
4 * |
|
5 * This library is free software; you can redistribute it and/or |
|
6 * modify it under the terms of the GNU Library General Public |
|
7 * License as published by the Free Software Foundation; either |
|
8 * version 2 of the License, or (at your option) any later version. |
|
9 * |
|
10 * This library is distributed in the hope that it will be useful, |
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 * Library General Public License for more details. |
|
14 * |
|
15 * You should have received a copy of the GNU Library General Public License |
|
16 * along with this library; see the file COPYING.LIB. If not, write to |
|
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
|
18 * Boston, MA 02110-1301, USA. |
|
19 */ |
|
20 |
|
21 %skeleton "lalr1.cc" |
|
22 %defines |
|
23 %define "parser_class_name" "json_parser" |
|
24 |
|
25 %{ |
|
26 #include "parser_p.h" |
|
27 #include "json_scanner.h" |
|
28 #include "qjson_debug.h" |
|
29 |
|
30 #include <QtCore/QByteArray> |
|
31 #include <QtCore/QMap> |
|
32 #include <QtCore/QString> |
|
33 #include <QtCore/QVariant> |
|
34 |
|
35 class JSonScanner; |
|
36 |
|
37 namespace QJson { |
|
38 class Parser; |
|
39 } |
|
40 |
|
41 #define YYERROR_VERBOSE 1 |
|
42 %} |
|
43 |
|
44 %parse-param { QJson::ParserPrivate* driver } |
|
45 %lex-param { QJson::ParserPrivate* driver } |
|
46 |
|
47 %locations |
|
48 |
|
49 %debug |
|
50 %error-verbose |
|
51 |
|
52 %token END 0 "end of file" |
|
53 |
|
54 %token CURLY_BRACKET_OPEN 1 "{" |
|
55 %token CURLY_BRACKET_CLOSE 2 "}" |
|
56 %token SQUARE_BRACKET_OPEN 3 "[" |
|
57 %token SQUARE_BRACKET_CLOSE 4 "]" |
|
58 |
|
59 %token COLON 5 ":" |
|
60 %token COMMA 6 "," |
|
61 %token MINUS 7 "-" |
|
62 %token DOT 8 "." |
|
63 %token DIGIT 9 "digit" |
|
64 %token E 10 "exponential" |
|
65 %token TRUE_VAL 11 "true" |
|
66 %token FALSE_VAL 12 "false" |
|
67 %token NULL_VAL 13 "null" |
|
68 %token QUOTMARKOPEN 14 "open quotation mark" |
|
69 %token QUOTMARKCLOSE 15 "close quotation mark" |
|
70 |
|
71 %token STRING 16 "string" |
|
72 |
|
73 // define the initial token |
|
74 %start start |
|
75 |
|
76 %% |
|
77 |
|
78 // grammar rules |
|
79 |
|
80 start: data { |
|
81 driver->m_result = $1; |
|
82 qjsonDebug() << "json_parser - parsing finished"; |
|
83 }; |
|
84 |
|
85 data: object {$$ = $1; } |
|
86 | array {$$ = $1; } |
|
87 | error |
|
88 { |
|
89 qCritical()<< "json_parser - syntax error found, " |
|
90 << "forcing abort"; |
|
91 YYABORT; |
|
92 } |
|
93 | END; |
|
94 |
|
95 object: CURLY_BRACKET_OPEN members CURLY_BRACKET_CLOSE { $$ = $2; }; |
|
96 |
|
97 members: /* empty */ { $$ = QVariant (QVariantMap()); } |
|
98 | pair r_members { |
|
99 QVariantMap members = $2.toMap(); |
|
100 $2 = QVariant(); // Allow reuse of map |
|
101 $$ = QVariant(members.unite ($1.toMap())); |
|
102 }; |
|
103 |
|
104 r_members: /* empty */ { $$ = QVariant (QVariantMap()); } |
|
105 | COMMA pair r_members { |
|
106 QVariantMap members = $3.toMap(); |
|
107 $3 = QVariant(); // Allow reuse of map |
|
108 $$ = QVariant(members.unite ($2.toMap())); |
|
109 }; |
|
110 |
|
111 pair: string COLON value { |
|
112 QVariantMap pair; |
|
113 pair.insert ($1.toString(), QVariant($3)); |
|
114 $$ = QVariant (pair); |
|
115 }; |
|
116 |
|
117 array: SQUARE_BRACKET_OPEN values SQUARE_BRACKET_CLOSE { $$ = $2; }; |
|
118 |
|
119 values: /* empty */ { $$ = QVariant (QVariantList()); } |
|
120 | value r_values { |
|
121 QVariantList members = $2.toList(); |
|
122 $2 = QVariant(); // Allow reuse of list |
|
123 members.prepend ($1); |
|
124 $$ = QVariant(members); |
|
125 }; |
|
126 |
|
127 r_values: /* empty */ { $$ = QVariant (QVariantList()); } |
|
128 | COMMA value r_values { |
|
129 QVariantList members = $3.toList(); |
|
130 $3 = QVariant(); // Allow reuse of list |
|
131 members.prepend ($2); |
|
132 $$ = QVariant(members); |
|
133 }; |
|
134 |
|
135 value: string { $$ = $1; } |
|
136 | number { $$ = $1; } |
|
137 | object { $$ = $1; } |
|
138 | array { $$ = $1; } |
|
139 | TRUE_VAL { $$ = QVariant (true); } |
|
140 | FALSE_VAL { $$ = QVariant (false); } |
|
141 | NULL_VAL { |
|
142 QVariant null_variant; |
|
143 $$ = null_variant; |
|
144 }; |
|
145 |
|
146 number: int { |
|
147 if ($1.toByteArray().startsWith('-')) { |
|
148 $$ = QVariant (QVariant::LongLong); |
|
149 $$.setValue($1.toLongLong()); |
|
150 } |
|
151 else { |
|
152 $$ = QVariant (QVariant::ULongLong); |
|
153 $$.setValue($1.toULongLong()); |
|
154 } |
|
155 } |
|
156 | int fract { |
|
157 const QByteArray value = $1.toByteArray() + $2.toByteArray(); |
|
158 $$ = QVariant(QVariant::Double); |
|
159 $$.setValue(value.toDouble()); |
|
160 } |
|
161 | int exp { $$ = QVariant ($1.toByteArray() + $2.toByteArray()); } |
|
162 | int fract exp { |
|
163 const QByteArray value = $1.toByteArray() + $2.toByteArray() + $3.toByteArray(); |
|
164 $$ = QVariant (value); |
|
165 }; |
|
166 |
|
167 int: DIGIT digits { $$ = QVariant ($1.toByteArray() + $2.toByteArray()); } |
|
168 | MINUS DIGIT digits { $$ = QVariant (QByteArray("-") + $2.toByteArray() + $3.toByteArray()); }; |
|
169 |
|
170 digits: /* empty */ { $$ = QVariant (QByteArray("")); } |
|
171 | DIGIT digits { |
|
172 $$ = QVariant($1.toByteArray() + $2.toByteArray()); |
|
173 }; |
|
174 |
|
175 fract: DOT digits { |
|
176 $$ = QVariant(QByteArray(".") + $2.toByteArray()); |
|
177 }; |
|
178 |
|
179 exp: E digits { $$ = QVariant($1.toByteArray() + $2.toByteArray()); }; |
|
180 |
|
181 string: QUOTMARKOPEN string_arg QUOTMARKCLOSE { $$ = $2; }; |
|
182 |
|
183 string_arg: /*empty */ { $$ = QVariant (QString(QLatin1String(""))); } |
|
184 | STRING { |
|
185 $$ = $1; |
|
186 }; |
|
187 |
|
188 %% |
|
189 |
|
190 int yy::yylex(YYSTYPE *yylval, yy::location *yylloc, QJson::ParserPrivate* driver) |
|
191 { |
|
192 JSonScanner* scanner = driver->m_scanner; |
|
193 yylval->clear(); |
|
194 int ret = scanner->yylex(yylval, yylloc); |
|
195 |
|
196 qjsonDebug() << "json_parser::yylex - calling scanner yylval==|" |
|
197 << yylval->toByteArray() << "|, ret==|" << QString::number(ret) << "|"; |
|
198 |
|
199 return ret; |
|
200 } |
|
201 |
|
202 void yy::json_parser::error (const yy::location& yyloc, |
|
203 const std::string& error) |
|
204 { |
|
205 /*qjsonDebug() << yyloc.begin.line; |
|
206 qjsonDebug() << yyloc.begin.column; |
|
207 qjsonDebug() << yyloc.end.line; |
|
208 qjsonDebug() << yyloc.end.column;*/ |
|
209 qjsonDebug() << "json_parser::error [line" << yyloc.end.line << "] -" << error.c_str() ; |
|
210 driver->setError(QString::fromLatin1(error.c_str()), yyloc.end.line); |
|
211 } |