#include "qmljs_objects.h"
#include "qv4codegen_p.h"
#include "qv4isel_p.h"
+#include "qv4syntaxchecker_p.h"
#include <QtCore>
#include <private/qqmljsengine_p.h>
};
} // builtins
+
+void evaluate(QQmlJS::Engine *engine, const QString &fileName, const QString &code)
+{
+ using namespace QQmlJS;
+
+ Lexer lexer(engine);
+ lexer.setCode(code, 1, false);
+ Parser parser(engine);
+
+ const bool parsed = parser.parseProgram();
+
+ foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {
+ std::cerr << qPrintable(fileName) << ':' << m.loc.startLine << ':' << m.loc.startColumn
+ << ": error: " << qPrintable(m.message) << std::endl;
+ }
+
+ if (parsed) {
+ using namespace AST;
+ Program *program = AST::cast<Program *>(parser.rootNode());
+
+ Codegen cg;
+ IR::Module module;
+ cg(program, &module);
+
+ const size_t codeSize = 10 * getpagesize();
+ uchar *code = (uchar *) malloc(codeSize);
+
+ x86_64::InstructionSelection isel(&module, code);
+ QHash<QString, IR::Function *> codeByName;
+ foreach (IR::Function *function, module.functions) {
+ isel(function);
+ if (function->name && ! function->name->isEmpty()) {
+ codeByName.insert(*function->name, function);
+ }
+ }
+
+ if (! protect(code, codeSize))
+ Q_UNREACHABLE();
+
+ VM::Context *ctx = new VM::Context;
+ ctx->init();
+ ctx->activation = VM::Value::object(ctx, new VM::ArgumentsObject(ctx));
+ ctx->activation.objectValue->put(VM::String::get(ctx, QLatin1String("print")),
+ VM::Value::object(ctx, new builtins::Print()));
+ foreach (IR::Function *function, module.functions) {
+ if (function->name && ! function->name->isEmpty()) {
+ ctx->activation.objectValue->put(VM::String::get(ctx, *function->name),
+ VM::Value::object(ctx, new VM::ScriptFunction(function)));
+ }
+ }
+ codeByName.value(QLatin1String("%entry"))->code(ctx);
+ }
+}
+
int main(int argc, char *argv[])
{
using namespace QQmlJS;
if (file.open(QFile::ReadOnly)) {
const QString code = QString::fromUtf8(file.readAll());
file.close();
-
- Lexer lexer(&engine);
- lexer.setCode(code, 1, false);
- Parser parser(&engine);
-
- const bool parsed = parser.parseProgram();
-
- foreach (const DiagnosticMessage &m, parser.diagnosticMessages()) {
- std::cerr << qPrintable(fn) << ':' << m.loc.startLine << ':' << m.loc.startColumn
- << ": error: " << qPrintable(m.message) << std::endl;
- }
-
- if (parsed) {
- using namespace AST;
- Program *program = AST::cast<Program *>(parser.rootNode());
-
- Codegen cg;
- IR::Module module;
- cg(program, &module);
-
- const size_t codeSize = 10 * getpagesize();
- uchar *code = (uchar *) malloc(codeSize);
-
- x86_64::InstructionSelection isel(&module, code);
- QHash<QString, IR::Function *> codeByName;
- foreach (IR::Function *function, module.functions) {
- isel(function);
- if (function->name && ! function->name->isEmpty()) {
- codeByName.insert(*function->name, function);
- }
- }
-
- if (! protect(code, codeSize))
- Q_UNREACHABLE();
-
- VM::Context *ctx = new VM::Context;
- ctx->init();
- ctx->activation = VM::Value::object(ctx, new VM::ArgumentsObject(ctx));
- ctx->activation.objectValue->put(VM::String::get(ctx, QLatin1String("print")),
- VM::Value::object(ctx, new builtins::Print()));
- foreach (IR::Function *function, module.functions) {
- if (function->name && ! function->name->isEmpty()) {
- ctx->activation.objectValue->put(VM::String::get(ctx, *function->name),
- VM::Value::object(ctx, new VM::ScriptFunction(function)));
- }
- }
- codeByName.value(QLatin1String("%entry"))->code(ctx);
- }
+ evaluate(&engine, fn, code);
}
}
}
--- /dev/null
+
+#include "qv4syntaxchecker_p.h"
+
+using namespace QQmlJS;
+
+SyntaxChecker::SyntaxChecker()
+ : Lexer(&m_engine)
+ , m_stateStack(128)
+{
+}
+
+void QQmlJS::SyntaxChecker::clearText()
+{
+ m_code.clear();
+ m_tokens.clear();
+}
+
+void SyntaxChecker::appendText(const QString &text)
+{
+ m_code += text;
+}
+
+QString SyntaxChecker::text() const
+{
+ return m_code;
+}
+
+bool SyntaxChecker::canEvaluate()
+{
+ int yyaction = 0;
+ int yytoken = -1;
+ int yytos = -1;
+
+ setCode(m_code, 1);
+
+ m_tokens.clear();
+ m_tokens.append(T_FEED_JS_PROGRAM);
+
+ do {
+ if (++yytos == m_stateStack.size())
+ m_stateStack.resize(m_stateStack.size() * 2);
+
+ m_stateStack[yytos] = yyaction;
+
+again:
+ if (yytoken == -1 && action_index[yyaction] != -TERMINAL_COUNT) {
+ if (m_tokens.isEmpty())
+ yytoken = lex();
+ else
+ yytoken = m_tokens.takeFirst();
+ }
+
+ yyaction = t_action(yyaction, yytoken);
+ if (yyaction > 0) {
+ if (yyaction == ACCEPT_STATE) {
+ --yytos;
+ return true;
+ }
+ yytoken = -1;
+ } else if (yyaction < 0) {
+ const int ruleno = -yyaction - 1;
+ yytos -= rhs[ruleno];
+ yyaction = nt_action(m_stateStack[yytos], lhs[ruleno] - TERMINAL_COUNT);
+ }
+ } while (yyaction);
+
+ const int errorState = m_stateStack[yytos];
+ if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && canInsertAutomaticSemicolon(yytoken)) {
+ yyaction = errorState;
+ m_tokens.prepend(yytoken);
+ yytoken = T_SEMICOLON;
+ goto again;
+ }
+
+ if (yytoken != EOF_SYMBOL)
+ return true;
+
+ return false;
+}