source: trunk/src/script/parser/qscriptsyntaxchecker.cpp@ 1028

Last change on this file since 1028 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

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