76c698a565da75d55da0bc6a84e1ffb1406acca7
[buliscores] / qjson / src / json_parser.yy
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   #include <limits>
36
37   class JSonScanner;
38
39   namespace QJson {
40     class Parser;
41   }
42
43   #define YYERROR_VERBOSE 1
44 %}
45
46 %parse-param { QJson::ParserPrivate* driver }
47 %lex-param { QJson::ParserPrivate* driver }
48
49 %locations
50
51 %debug
52 %error-verbose
53
54 %token END 0 "end of file"
55
56 %token CURLY_BRACKET_OPEN 1 "{"
57 %token CURLY_BRACKET_CLOSE 2 "}"
58 %token SQUARE_BRACKET_OPEN 3 "["
59 %token SQUARE_BRACKET_CLOSE 4 "]"
60
61 %token COLON 5 ":"
62 %token COMMA 6 ","
63 %token MINUS 7 "-"
64 %token DOT 8 "."
65 %token DIGIT 9 "digit"
66 %token E 10 "exponential"
67 %token TRUE_VAL 11 "true"
68 %token FALSE_VAL 12 "false"
69 %token NULL_VAL 13 "null"
70 %token QUOTMARKOPEN 14 "open quotation mark"
71 %token QUOTMARKCLOSE 15 "close quotation mark"
72
73 %token STRING 16 "string"
74 %token INFINITY_VAL 17 "Infinity"
75 %token NAN_VAL 18 "NaN"
76
77 // define the initial token
78 %start start
79
80 %%
81
82 // grammar rules
83
84 start: data {
85               driver->m_result = $1;
86               qjsonDebug() << "json_parser - parsing finished";
87             };
88
89 data: value { $$ = $1; }
90       | error
91           {
92             qCritical()<< "json_parser - syntax error found, "
93                     << "forcing abort, Line" << @$.begin.line << "Column" << @$.begin.column;
94             YYABORT;
95           }
96       | END;
97
98 object: CURLY_BRACKET_OPEN members CURLY_BRACKET_CLOSE { $$ = $2; };
99
100 members: /* empty */ { $$ = QVariant (QVariantMap()); }
101         | pair r_members {
102             QVariantMap members = $2.toMap();
103             $2 = QVariant(); // Allow reuse of map
104             $$ = QVariant(members.unite ($1.toMap()));
105           };
106
107 r_members: /* empty */ { $$ = QVariant (QVariantMap()); }
108         | COMMA pair r_members {
109           QVariantMap members = $3.toMap();
110           $3 = QVariant(); // Allow reuse of map
111           $$ = QVariant(members.unite ($2.toMap()));
112           };
113
114 pair:   string COLON value {
115             QVariantMap pair;
116             pair.insert ($1.toString(), QVariant($3));
117             $$ = QVariant (pair);
118           };
119
120 array: SQUARE_BRACKET_OPEN values SQUARE_BRACKET_CLOSE { $$ = $2; };
121
122 values: /* empty */ { $$ = QVariant (QVariantList()); }
123         | value r_values {
124           QVariantList members = $2.toList();
125           $2 = QVariant(); // Allow reuse of list
126           members.prepend ($1);
127           $$ = QVariant(members);
128         };
129
130 r_values: /* empty */ { $$ = QVariant (QVariantList()); }
131           | COMMA value r_values {
132             QVariantList members = $3.toList();
133             $3 = QVariant(); // Allow reuse of list
134             members.prepend ($2);
135             $$ = QVariant(members);
136           };
137
138 value: string { $$ = $1; }
139         | special_or_number { $$ = $1; }
140         | object { $$ = $1; }
141         | array { $$ = $1; }
142         | TRUE_VAL { $$ = QVariant (true); }
143         | FALSE_VAL { $$ = QVariant (false); }
144         | NULL_VAL {
145           QVariant null_variant;
146           $$ = null_variant;
147         };
148
149 special_or_number: MINUS INFINITY_VAL { $$ = QVariant(QVariant::Double); $$.setValue( -std::numeric_limits<double>::infinity() ); }
150                    | INFINITY_VAL { $$ = QVariant(QVariant::Double); $$.setValue( std::numeric_limits<double>::infinity() ); }
151                    | NAN_VAL { $$ = QVariant(QVariant::Double); $$.setValue( std::numeric_limits<double>::quiet_NaN() ); }
152                    | number;
153
154 number: int {
155             if ($1.toByteArray().startsWith('-')) {
156               $$ = QVariant (QVariant::LongLong);
157               $$.setValue($1.toLongLong());
158             }
159             else {
160               $$ = QVariant (QVariant::ULongLong);
161               $$.setValue($1.toULongLong());
162             }
163           }
164         | int fract {
165             const QByteArray value = $1.toByteArray() + $2.toByteArray();
166             $$ = QVariant(QVariant::Double);
167             $$.setValue(value.toDouble());
168           }
169         | int exp { $$ = QVariant ($1.toByteArray() + $2.toByteArray()); }
170         | int fract exp {
171             const QByteArray value = $1.toByteArray() + $2.toByteArray() + $3.toByteArray();
172             $$ = QVariant (value);
173           };
174
175 int:  DIGIT digits { $$ = QVariant ($1.toByteArray() + $2.toByteArray()); }
176       | MINUS DIGIT digits { $$ = QVariant (QByteArray("-") + $2.toByteArray() + $3.toByteArray()); };
177
178 digits: /* empty */ { $$ = QVariant (QByteArray("")); }
179         | DIGIT digits {
180           $$ = QVariant($1.toByteArray() + $2.toByteArray());
181         };
182
183 fract: DOT digits {
184           $$ = QVariant(QByteArray(".") + $2.toByteArray());
185         };
186
187 exp: E digits { $$ = QVariant($1.toByteArray() + $2.toByteArray()); };
188
189 string: QUOTMARKOPEN string_arg QUOTMARKCLOSE { $$ = $2; };
190
191 string_arg: /*empty */ { $$ = QVariant (QString(QLatin1String(""))); }
192             | STRING {
193                 $$ = $1;
194               };
195
196 %%
197
198 int yy::yylex(YYSTYPE *yylval, yy::location *yylloc, QJson::ParserPrivate* driver)
199 {
200   JSonScanner* scanner = driver->m_scanner;
201   yylval->clear();
202   int ret = scanner->yylex(yylval, yylloc);
203
204   qjsonDebug() << "json_parser::yylex - calling scanner yylval==|"
205            << yylval->toByteArray() << "|, ret==|" << QString::number(ret) << "|";
206   
207   return ret;
208 }
209
210 void yy::json_parser::error (const yy::location& yyloc,
211                                  const std::string& error)
212 {
213   /*qjsonDebug() << yyloc.begin.line;
214   qjsonDebug() << yyloc.begin.column;
215   qjsonDebug() << yyloc.end.line;
216   qjsonDebug() << yyloc.end.column;*/
217   qjsonDebug() << "json_parser::error [line" << yyloc.end.line << "] -" << error.c_str() ;
218   driver->setError(QString::fromLatin1(error.c_str()), yyloc.end.line);
219 }