source: trunk/src/script/qscriptsyntaxchecker.cpp@ 397

Last change on this file since 397 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 6.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtScript module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qscriptsyntaxchecker_p.h"
43
44#ifndef QT_NO_SCRIPT
45
46#include "qscriptlexer_p.h"
47#include "qscriptparser_p.h"
48
49QT_BEGIN_NAMESPACE
50
51namespace QScript {
52
53
54SyntaxChecker::SyntaxChecker():
55 tos(0),
56 stack_size(0),
57 state_stack(0)
58{
59}
60
61SyntaxChecker::~SyntaxChecker()
62{
63 if (stack_size) {
64 qFree(state_stack);
65 }
66}
67
68bool SyntaxChecker::automatic(QScript::Lexer *lexer, int token) const
69{
70 return token == T_RBRACE || token == 0 || lexer->prevTerminator();
71}
72
73SyntaxChecker::Result SyntaxChecker::checkSyntax(const QString &code)
74{
75 const int INITIAL_STATE = 0;
76 QScript::Lexer lexer (/*engine=*/ 0);
77 lexer.setCode(code, /*lineNo*/ 1);
78
79 int yytoken = -1;
80 int saved_yytoken = -1;
81 QString error_message;
82 int error_lineno = -1;
83 int error_column = -1;
84 State checkerState = Valid;
85
86 reallocateStack();
87
88 tos = 0;
89 state_stack[++tos] = INITIAL_STATE;
90
91 while (true)
92 {
93 const int state = state_stack [tos];
94 if (yytoken == -1 && - TERMINAL_COUNT != action_index [state])
95 {
96 if (saved_yytoken == -1)
97 yytoken = lexer.lex();
98 else
99 {
100 yytoken = saved_yytoken;
101 saved_yytoken = -1;
102 }
103 }
104
105 int act = t_action (state, yytoken);
106
107 if (act == ACCEPT_STATE) {
108 if (lexer.error() == QScript::Lexer::UnclosedComment)
109 checkerState = Intermediate;
110 else
111 checkerState = Valid;
112 break;
113 } else if (act > 0) {
114 if (++tos == stack_size)
115 reallocateStack();
116
117 state_stack [tos] = act;
118 yytoken = -1;
119 }
120
121 else if (act < 0)
122 {
123 int r = - act - 1;
124
125 tos -= rhs [r];
126 act = state_stack [tos++];
127
128 if ((r == Q_SCRIPT_REGEXPLITERAL_RULE1)
129 || (r == Q_SCRIPT_REGEXPLITERAL_RULE2)) {
130 // Skip the rest of the RegExp literal
131 bool rx = lexer.scanRegExp();
132 if (!rx) {
133 checkerState = Intermediate;
134 break;
135 }
136 }
137
138 state_stack [tos] = nt_action (act, lhs [r] - TERMINAL_COUNT);
139 }
140
141 else
142 {
143 if (saved_yytoken == -1 && automatic (&lexer, yytoken) && t_action (state, T_AUTOMATIC_SEMICOLON) > 0)
144 {
145 saved_yytoken = yytoken;
146 yytoken = T_SEMICOLON;
147 continue;
148 }
149
150 else if ((state == INITIAL_STATE) && (yytoken == 0)) {
151 // accept empty input
152 yytoken = T_SEMICOLON;
153 continue;
154 }
155
156 int ers = state;
157 int shifts = 0;
158 int reduces = 0;
159 int expected_tokens [3];
160 for (int tk = 0; tk < TERMINAL_COUNT; ++tk)
161 {
162 int k = t_action (ers, tk);
163
164 if (! k)
165 continue;
166 else if (k < 0)
167 ++reduces;
168 else if (spell [tk])
169 {
170 if (shifts < 3)
171 expected_tokens [shifts] = tk;
172 ++shifts;
173 }
174 }
175
176 error_message.clear ();
177 if (shifts && shifts < 3)
178 {
179 bool first = true;
180
181 for (int s = 0; s < shifts; ++s)
182 {
183 if (first)
184 error_message += QLatin1String ("Expected ");
185 else
186 error_message += QLatin1String (", ");
187
188 first = false;
189 error_message += QLatin1String("`");
190 error_message += QLatin1String (spell [expected_tokens [s]]);
191 error_message += QLatin1String("'");
192 }
193 }
194
195 if (error_message.isEmpty())
196 error_message = lexer.errorMessage();
197
198 error_lineno = lexer.startLineNo();
199 error_column = lexer.startColumnNo();
200 checkerState = Error;
201 break;
202 }
203 }
204
205 if (checkerState == Error) {
206 if (lexer.error() == QScript::Lexer::UnclosedComment)
207 checkerState = Intermediate;
208 else if (yytoken == 0)
209 checkerState = Intermediate;
210 }
211 return Result(checkerState, error_lineno, error_column, error_message);
212}
213
214} // namespace QScript
215
216QT_END_NAMESPACE
217
218#endif // QT_NO_SCRIPT
Note: See TracBrowser for help on using the repository browser.