ps_parser.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /**
  2. * @licstart The following is the entire license notice for the
  3. * Javascript code in this page
  4. *
  5. * Copyright 2019 Mozilla Foundation
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * @licend The above is the entire license notice for the
  20. * Javascript code in this page
  21. */
  22. "use strict";
  23. Object.defineProperty(exports, "__esModule", {
  24. value: true
  25. });
  26. exports.PostScriptParser = exports.PostScriptLexer = void 0;
  27. var _util = require("../shared/util");
  28. var _primitives = require("./primitives");
  29. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  30. function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
  31. function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  32. var PostScriptParser =
  33. /*#__PURE__*/
  34. function () {
  35. function PostScriptParser(lexer) {
  36. _classCallCheck(this, PostScriptParser);
  37. this.lexer = lexer;
  38. this.operators = [];
  39. this.token = null;
  40. this.prev = null;
  41. }
  42. _createClass(PostScriptParser, [{
  43. key: "nextToken",
  44. value: function nextToken() {
  45. this.prev = this.token;
  46. this.token = this.lexer.getToken();
  47. }
  48. }, {
  49. key: "accept",
  50. value: function accept(type) {
  51. if (this.token.type === type) {
  52. this.nextToken();
  53. return true;
  54. }
  55. return false;
  56. }
  57. }, {
  58. key: "expect",
  59. value: function expect(type) {
  60. if (this.accept(type)) {
  61. return true;
  62. }
  63. throw new _util.FormatError("Unexpected symbol: found ".concat(this.token.type, " expected ").concat(type, "."));
  64. }
  65. }, {
  66. key: "parse",
  67. value: function parse() {
  68. this.nextToken();
  69. this.expect(PostScriptTokenTypes.LBRACE);
  70. this.parseBlock();
  71. this.expect(PostScriptTokenTypes.RBRACE);
  72. return this.operators;
  73. }
  74. }, {
  75. key: "parseBlock",
  76. value: function parseBlock() {
  77. while (true) {
  78. if (this.accept(PostScriptTokenTypes.NUMBER)) {
  79. this.operators.push(this.prev.value);
  80. } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
  81. this.operators.push(this.prev.value);
  82. } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
  83. this.parseCondition();
  84. } else {
  85. return;
  86. }
  87. }
  88. }
  89. }, {
  90. key: "parseCondition",
  91. value: function parseCondition() {
  92. var conditionLocation = this.operators.length;
  93. this.operators.push(null, null);
  94. this.parseBlock();
  95. this.expect(PostScriptTokenTypes.RBRACE);
  96. if (this.accept(PostScriptTokenTypes.IF)) {
  97. this.operators[conditionLocation] = this.operators.length;
  98. this.operators[conditionLocation + 1] = 'jz';
  99. } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
  100. var jumpLocation = this.operators.length;
  101. this.operators.push(null, null);
  102. var endOfTrue = this.operators.length;
  103. this.parseBlock();
  104. this.expect(PostScriptTokenTypes.RBRACE);
  105. this.expect(PostScriptTokenTypes.IFELSE);
  106. this.operators[jumpLocation] = this.operators.length;
  107. this.operators[jumpLocation + 1] = 'j';
  108. this.operators[conditionLocation] = endOfTrue;
  109. this.operators[conditionLocation + 1] = 'jz';
  110. } else {
  111. throw new _util.FormatError('PS Function: error parsing conditional.');
  112. }
  113. }
  114. }]);
  115. return PostScriptParser;
  116. }();
  117. exports.PostScriptParser = PostScriptParser;
  118. var PostScriptTokenTypes = {
  119. LBRACE: 0,
  120. RBRACE: 1,
  121. NUMBER: 2,
  122. OPERATOR: 3,
  123. IF: 4,
  124. IFELSE: 5
  125. };
  126. var PostScriptToken = function PostScriptTokenClosure() {
  127. var opCache = Object.create(null);
  128. var PostScriptToken =
  129. /*#__PURE__*/
  130. function () {
  131. function PostScriptToken(type, value) {
  132. _classCallCheck(this, PostScriptToken);
  133. this.type = type;
  134. this.value = value;
  135. }
  136. _createClass(PostScriptToken, null, [{
  137. key: "getOperator",
  138. value: function getOperator(op) {
  139. var opValue = opCache[op];
  140. if (opValue) {
  141. return opValue;
  142. }
  143. return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
  144. }
  145. }, {
  146. key: "LBRACE",
  147. get: function get() {
  148. return (0, _util.shadow)(this, 'LBRACE', new PostScriptToken(PostScriptTokenTypes.LBRACE, '{'));
  149. }
  150. }, {
  151. key: "RBRACE",
  152. get: function get() {
  153. return (0, _util.shadow)(this, 'RBRACE', new PostScriptToken(PostScriptTokenTypes.RBRACE, '}'));
  154. }
  155. }, {
  156. key: "IF",
  157. get: function get() {
  158. return (0, _util.shadow)(this, 'IF', new PostScriptToken(PostScriptTokenTypes.IF, 'IF'));
  159. }
  160. }, {
  161. key: "IFELSE",
  162. get: function get() {
  163. return (0, _util.shadow)(this, 'IFELSE', new PostScriptToken(PostScriptTokenTypes.IFELSE, 'IFELSE'));
  164. }
  165. }]);
  166. return PostScriptToken;
  167. }();
  168. return PostScriptToken;
  169. }();
  170. var PostScriptLexer =
  171. /*#__PURE__*/
  172. function () {
  173. function PostScriptLexer(stream) {
  174. _classCallCheck(this, PostScriptLexer);
  175. this.stream = stream;
  176. this.nextChar();
  177. this.strBuf = [];
  178. }
  179. _createClass(PostScriptLexer, [{
  180. key: "nextChar",
  181. value: function nextChar() {
  182. return this.currentChar = this.stream.getByte();
  183. }
  184. }, {
  185. key: "getToken",
  186. value: function getToken() {
  187. var comment = false;
  188. var ch = this.currentChar;
  189. while (true) {
  190. if (ch < 0) {
  191. return _primitives.EOF;
  192. }
  193. if (comment) {
  194. if (ch === 0x0A || ch === 0x0D) {
  195. comment = false;
  196. }
  197. } else if (ch === 0x25) {
  198. comment = true;
  199. } else if (!(0, _util.isSpace)(ch)) {
  200. break;
  201. }
  202. ch = this.nextChar();
  203. }
  204. switch (ch | 0) {
  205. case 0x30:
  206. case 0x31:
  207. case 0x32:
  208. case 0x33:
  209. case 0x34:
  210. case 0x35:
  211. case 0x36:
  212. case 0x37:
  213. case 0x38:
  214. case 0x39:
  215. case 0x2B:
  216. case 0x2D:
  217. case 0x2E:
  218. return new PostScriptToken(PostScriptTokenTypes.NUMBER, this.getNumber());
  219. case 0x7B:
  220. this.nextChar();
  221. return PostScriptToken.LBRACE;
  222. case 0x7D:
  223. this.nextChar();
  224. return PostScriptToken.RBRACE;
  225. }
  226. var strBuf = this.strBuf;
  227. strBuf.length = 0;
  228. strBuf[0] = String.fromCharCode(ch);
  229. while ((ch = this.nextChar()) >= 0 && (ch >= 0x41 && ch <= 0x5A || ch >= 0x61 && ch <= 0x7A)) {
  230. strBuf.push(String.fromCharCode(ch));
  231. }
  232. var str = strBuf.join('');
  233. switch (str.toLowerCase()) {
  234. case 'if':
  235. return PostScriptToken.IF;
  236. case 'ifelse':
  237. return PostScriptToken.IFELSE;
  238. default:
  239. return PostScriptToken.getOperator(str);
  240. }
  241. }
  242. }, {
  243. key: "getNumber",
  244. value: function getNumber() {
  245. var ch = this.currentChar;
  246. var strBuf = this.strBuf;
  247. strBuf.length = 0;
  248. strBuf[0] = String.fromCharCode(ch);
  249. while ((ch = this.nextChar()) >= 0) {
  250. if (ch >= 0x30 && ch <= 0x39 || ch === 0x2D || ch === 0x2E) {
  251. strBuf.push(String.fromCharCode(ch));
  252. } else {
  253. break;
  254. }
  255. }
  256. var value = parseFloat(strBuf.join(''));
  257. if (isNaN(value)) {
  258. throw new _util.FormatError("Invalid floating point number: ".concat(value));
  259. }
  260. return value;
  261. }
  262. }]);
  263. return PostScriptLexer;
  264. }();
  265. exports.PostScriptLexer = PostScriptLexer;