956 } |
952 } |
957 } |
953 } |
958 return rv; |
954 return rv; |
959 } |
955 } |
960 |
956 |
|
957 #define CHECK_LINE if(l.currentLineNo() != startLine) return rv; |
|
958 #define CHECK_TOKEN(t) if (token != QDeclarativeJSGrammar:: t) return rv; |
|
959 |
|
960 static const int uriTokens[] = { |
|
961 QDeclarativeJSGrammar::T_IDENTIFIER, |
|
962 QDeclarativeJSGrammar::T_PROPERTY, |
|
963 QDeclarativeJSGrammar::T_SIGNAL, |
|
964 QDeclarativeJSGrammar::T_READONLY, |
|
965 QDeclarativeJSGrammar::T_ON, |
|
966 QDeclarativeJSGrammar::T_BREAK, |
|
967 QDeclarativeJSGrammar::T_CASE, |
|
968 QDeclarativeJSGrammar::T_CATCH, |
|
969 QDeclarativeJSGrammar::T_CONTINUE, |
|
970 QDeclarativeJSGrammar::T_DEFAULT, |
|
971 QDeclarativeJSGrammar::T_DELETE, |
|
972 QDeclarativeJSGrammar::T_DO, |
|
973 QDeclarativeJSGrammar::T_ELSE, |
|
974 QDeclarativeJSGrammar::T_FALSE, |
|
975 QDeclarativeJSGrammar::T_FINALLY, |
|
976 QDeclarativeJSGrammar::T_FOR, |
|
977 QDeclarativeJSGrammar::T_FUNCTION, |
|
978 QDeclarativeJSGrammar::T_IF, |
|
979 QDeclarativeJSGrammar::T_IN, |
|
980 QDeclarativeJSGrammar::T_INSTANCEOF, |
|
981 QDeclarativeJSGrammar::T_NEW, |
|
982 QDeclarativeJSGrammar::T_NULL, |
|
983 QDeclarativeJSGrammar::T_RETURN, |
|
984 QDeclarativeJSGrammar::T_SWITCH, |
|
985 QDeclarativeJSGrammar::T_THIS, |
|
986 QDeclarativeJSGrammar::T_THROW, |
|
987 QDeclarativeJSGrammar::T_TRUE, |
|
988 QDeclarativeJSGrammar::T_TRY, |
|
989 QDeclarativeJSGrammar::T_TYPEOF, |
|
990 QDeclarativeJSGrammar::T_VAR, |
|
991 QDeclarativeJSGrammar::T_VOID, |
|
992 QDeclarativeJSGrammar::T_WHILE, |
|
993 QDeclarativeJSGrammar::T_CONST, |
|
994 QDeclarativeJSGrammar::T_DEBUGGER, |
|
995 QDeclarativeJSGrammar::T_RESERVED_WORD, |
|
996 QDeclarativeJSGrammar::T_WITH, |
|
997 |
|
998 QDeclarativeJSGrammar::EOF_SYMBOL |
|
999 }; |
|
1000 static inline bool isUriToken(int token) |
|
1001 { |
|
1002 const int *current = uriTokens; |
|
1003 while (*current != QDeclarativeJSGrammar::EOF_SYMBOL) { |
|
1004 if (*current == token) |
|
1005 return true; |
|
1006 ++current; |
|
1007 } |
|
1008 return false; |
|
1009 } |
|
1010 |
|
1011 QDeclarativeScriptParser::JavaScriptMetaData QDeclarativeScriptParser::extractMetaData(QString &script) |
|
1012 { |
|
1013 JavaScriptMetaData rv; |
|
1014 |
|
1015 QDeclarativeParser::Object::ScriptBlock::Pragmas &pragmas = rv.pragmas; |
|
1016 |
|
1017 const QString pragma(QLatin1String("pragma")); |
|
1018 const QString js(QLatin1String(".js")); |
|
1019 const QString library(QLatin1String("library")); |
|
1020 |
|
1021 QDeclarativeJS::Lexer l(0); |
|
1022 l.setCode(script, 0); |
|
1023 |
|
1024 int token = l.lex(); |
|
1025 |
|
1026 while (true) { |
|
1027 if (token != QDeclarativeJSGrammar::T_DOT) |
|
1028 return rv; |
|
1029 |
|
1030 int startOffset = l.tokenOffset(); |
|
1031 int startLine = l.currentLineNo(); |
|
1032 |
|
1033 token = l.lex(); |
|
1034 |
|
1035 CHECK_LINE; |
|
1036 |
|
1037 if (token == QDeclarativeJSGrammar::T_IMPORT) { |
|
1038 |
|
1039 // .import <URI> <Version> as <Identifier> |
|
1040 // .import <file.js> as <Identifier> |
|
1041 |
|
1042 token = l.lex(); |
|
1043 |
|
1044 CHECK_LINE; |
|
1045 |
|
1046 if (token == QDeclarativeJSGrammar::T_STRING_LITERAL) { |
|
1047 |
|
1048 QString file(l.characterBuffer(), l.characterCount()); |
|
1049 if (!file.endsWith(js)) |
|
1050 return rv; |
|
1051 |
|
1052 token = l.lex(); |
|
1053 |
|
1054 CHECK_TOKEN(T_AS); |
|
1055 CHECK_LINE; |
|
1056 |
|
1057 token = l.lex(); |
|
1058 |
|
1059 CHECK_TOKEN(T_IDENTIFIER); |
|
1060 CHECK_LINE; |
|
1061 |
|
1062 int endOffset = l.tokenLength() + l.tokenOffset(); |
|
1063 |
|
1064 QString importId = script.mid(l.tokenOffset(), l.tokenLength()); |
|
1065 |
|
1066 if (!importId.at(0).isUpper()) |
|
1067 return rv; |
|
1068 |
|
1069 token = l.lex(); |
|
1070 if (l.currentLineNo() == startLine) |
|
1071 return rv; |
|
1072 |
|
1073 replaceWithSpace(script, startOffset, endOffset - startOffset); |
|
1074 |
|
1075 Import import; |
|
1076 import.type = Import::Script; |
|
1077 import.uri = file; |
|
1078 import.qualifier = importId; |
|
1079 |
|
1080 rv.imports << import; |
|
1081 |
|
1082 } else { |
|
1083 // URI |
|
1084 QString uri; |
|
1085 QString version; |
|
1086 |
|
1087 while (true) { |
|
1088 if (!isUriToken(token)) |
|
1089 return rv; |
|
1090 |
|
1091 uri.append(QString(l.characterBuffer(), l.characterCount())); |
|
1092 |
|
1093 token = l.lex(); |
|
1094 CHECK_LINE; |
|
1095 if (token != QDeclarativeJSGrammar::T_DOT) |
|
1096 break; |
|
1097 |
|
1098 uri.append(QLatin1Char('.')); |
|
1099 |
|
1100 token = l.lex(); |
|
1101 CHECK_LINE; |
|
1102 } |
|
1103 |
|
1104 CHECK_TOKEN(T_NUMERIC_LITERAL); |
|
1105 version = script.mid(l.tokenOffset(), l.tokenLength()); |
|
1106 |
|
1107 token = l.lex(); |
|
1108 |
|
1109 CHECK_TOKEN(T_AS); |
|
1110 CHECK_LINE; |
|
1111 |
|
1112 token = l.lex(); |
|
1113 |
|
1114 CHECK_TOKEN(T_IDENTIFIER); |
|
1115 CHECK_LINE; |
|
1116 |
|
1117 int endOffset = l.tokenLength() + l.tokenOffset(); |
|
1118 |
|
1119 QString importId = script.mid(l.tokenOffset(), l.tokenLength()); |
|
1120 |
|
1121 if (!importId.at(0).isUpper()) |
|
1122 return rv; |
|
1123 |
|
1124 token = l.lex(); |
|
1125 if (l.currentLineNo() == startLine) |
|
1126 return rv; |
|
1127 |
|
1128 replaceWithSpace(script, startOffset, endOffset - startOffset); |
|
1129 |
|
1130 Import import; |
|
1131 import.type = Import::Library; |
|
1132 import.uri = uri; |
|
1133 import.version = version; |
|
1134 import.qualifier = importId; |
|
1135 |
|
1136 rv.imports << import; |
|
1137 } |
|
1138 |
|
1139 } else if (token == QDeclarativeJSGrammar::T_IDENTIFIER && |
|
1140 script.mid(l.tokenOffset(), l.tokenLength()) == pragma) { |
|
1141 |
|
1142 token = l.lex(); |
|
1143 |
|
1144 CHECK_TOKEN(T_IDENTIFIER); |
|
1145 CHECK_LINE; |
|
1146 |
|
1147 QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength()); |
|
1148 int endOffset = l.tokenLength() + l.tokenOffset(); |
|
1149 |
|
1150 if (pragmaValue == QLatin1String("library")) { |
|
1151 pragmas |= QDeclarativeParser::Object::ScriptBlock::Shared; |
|
1152 replaceWithSpace(script, startOffset, endOffset - startOffset); |
|
1153 } else { |
|
1154 return rv; |
|
1155 } |
|
1156 |
|
1157 token = l.lex(); |
|
1158 if (l.currentLineNo() == startLine) |
|
1159 return rv; |
|
1160 |
|
1161 } else { |
|
1162 return rv; |
|
1163 } |
|
1164 } |
|
1165 return rv; |
|
1166 } |
|
1167 |
961 void QDeclarativeScriptParser::clear() |
1168 void QDeclarativeScriptParser::clear() |
962 { |
1169 { |
963 if (root) { |
1170 if (root) { |
964 root->release(); |
1171 root->release(); |
965 root = 0; |
1172 root = 0; |