Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert src/core/ps_parser.js to use ES6 classes #10219

Merged
merged 1 commit into from
Nov 7, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
349 changes: 183 additions & 166 deletions src/core/ps_parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,90 +13,92 @@
* limitations under the License.
*/

import { FormatError, isSpace } from '../shared/util';
import { FormatError, isSpace, shadow } from '../shared/util';
import { EOF } from './primitives';

var PostScriptParser = (function PostScriptParserClosure() {
function PostScriptParser(lexer) {
class PostScriptParser {
constructor(lexer) {
this.lexer = lexer;
this.operators = [];
this.token = null;
this.prev = null;
}
PostScriptParser.prototype = {
nextToken: function PostScriptParser_nextToken() {
this.prev = this.token;
this.token = this.lexer.getToken();
},
accept: function PostScriptParser_accept(type) {
if (this.token.type === type) {
this.nextToken();
return true;
}
return false;
},
expect: function PostScriptParser_expect(type) {
if (this.accept(type)) {
return true;
}
throw new FormatError(
`Unexpected symbol: found ${this.token.type} expected ${type}.`);
},
parse: function PostScriptParser_parse() {

nextToken() {
this.prev = this.token;
this.token = this.lexer.getToken();
}

accept(type) {
if (this.token.type === type) {
this.nextToken();
this.expect(PostScriptTokenTypes.LBRACE);
this.parseBlock();
this.expect(PostScriptTokenTypes.RBRACE);
return this.operators;
},
parseBlock: function PostScriptParser_parseBlock() {
while (true) {
if (this.accept(PostScriptTokenTypes.NUMBER)) {
this.operators.push(this.prev.value);
} else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
this.operators.push(this.prev.value);
} else if (this.accept(PostScriptTokenTypes.LBRACE)) {
this.parseCondition();
} else {
return;
}
}
},
parseCondition: function PostScriptParser_parseCondition() {
// Add two place holders that will be updated later
var conditionLocation = this.operators.length;
this.operators.push(null, null);
return true;
}
return false;
}

this.parseBlock();
this.expect(PostScriptTokenTypes.RBRACE);
if (this.accept(PostScriptTokenTypes.IF)) {
// The true block is right after the 'if' so it just falls through on
// true else it jumps and skips the true block.
this.operators[conditionLocation] = this.operators.length;
this.operators[conditionLocation + 1] = 'jz';
expect(type) {
if (this.accept(type)) {
return true;
}
throw new FormatError(
`Unexpected symbol: found ${this.token.type} expected ${type}.`);
}

parse() {
this.nextToken();
this.expect(PostScriptTokenTypes.LBRACE);
this.parseBlock();
this.expect(PostScriptTokenTypes.RBRACE);
return this.operators;
}

parseBlock() {
while (true) {
if (this.accept(PostScriptTokenTypes.NUMBER)) {
this.operators.push(this.prev.value);
} else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
this.operators.push(this.prev.value);
} else if (this.accept(PostScriptTokenTypes.LBRACE)) {
var jumpLocation = this.operators.length;
this.operators.push(null, null);
var endOfTrue = this.operators.length;
this.parseBlock();
this.expect(PostScriptTokenTypes.RBRACE);
this.expect(PostScriptTokenTypes.IFELSE);
// The jump is added at the end of the true block to skip the false
// block.
this.operators[jumpLocation] = this.operators.length;
this.operators[jumpLocation + 1] = 'j';

this.operators[conditionLocation] = endOfTrue;
this.operators[conditionLocation + 1] = 'jz';
this.parseCondition();
} else {
throw new FormatError('PS Function: error parsing conditional.');
return;
}
},
};
return PostScriptParser;
})();
}
}

var PostScriptTokenTypes = {
parseCondition() {
// Add two place holders that will be updated later
const conditionLocation = this.operators.length;
this.operators.push(null, null);

this.parseBlock();
this.expect(PostScriptTokenTypes.RBRACE);
if (this.accept(PostScriptTokenTypes.IF)) {
// The true block is right after the 'if' so it just falls through on true
// else it jumps and skips the true block.
this.operators[conditionLocation] = this.operators.length;
this.operators[conditionLocation + 1] = 'jz';
} else if (this.accept(PostScriptTokenTypes.LBRACE)) {
const jumpLocation = this.operators.length;
this.operators.push(null, null);
const endOfTrue = this.operators.length;
this.parseBlock();
this.expect(PostScriptTokenTypes.RBRACE);
this.expect(PostScriptTokenTypes.IFELSE);
// The jump is added at the end of the true block to skip the false block.
this.operators[jumpLocation] = this.operators.length;
this.operators[jumpLocation + 1] = 'j';

this.operators[conditionLocation] = endOfTrue;
this.operators[conditionLocation + 1] = 'jz';
} else {
throw new FormatError('PS Function: error parsing conditional.');
}
}
}

const PostScriptTokenTypes = {
LBRACE: 0,
RBRACE: 1,
NUMBER: 2,
Expand All @@ -105,119 +107,134 @@ var PostScriptTokenTypes = {
IFELSE: 5,
};

var PostScriptToken = (function PostScriptTokenClosure() {
function PostScriptToken(type, value) {
this.type = type;
this.value = value;
}
const PostScriptToken = (function PostScriptTokenClosure() {
const opCache = Object.create(null);

var opCache = Object.create(null);
class PostScriptToken {
constructor(type, value) {
this.type = type;
this.value = value;
}

PostScriptToken.getOperator = function PostScriptToken_getOperator(op) {
var opValue = opCache[op];
if (opValue) {
return opValue;
static getOperator(op) {
const opValue = opCache[op];
if (opValue) {
return opValue;
}
return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR,
op);
}
return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
};

PostScriptToken.LBRACE = new PostScriptToken(PostScriptTokenTypes.LBRACE,
'{');
PostScriptToken.RBRACE = new PostScriptToken(PostScriptTokenTypes.RBRACE,
'}');
PostScriptToken.IF = new PostScriptToken(PostScriptTokenTypes.IF, 'IF');
PostScriptToken.IFELSE = new PostScriptToken(PostScriptTokenTypes.IFELSE,
'IFELSE');
static get LBRACE() {
return shadow(this, 'LBRACE',
new PostScriptToken(PostScriptTokenTypes.LBRACE, '{'));
}

static get RBRACE() {
return shadow(this, 'RBRACE',
new PostScriptToken(PostScriptTokenTypes.RBRACE, '}'));
}

static get IF() {
return shadow(this, 'IF',
new PostScriptToken(PostScriptTokenTypes.IF, 'IF'));
}

static get IFELSE() {
return shadow(this, 'IFELSE',
new PostScriptToken(PostScriptTokenTypes.IFELSE, 'IFELSE'));
}
}
return PostScriptToken;
})();

var PostScriptLexer = (function PostScriptLexerClosure() {
function PostScriptLexer(stream) {
class PostScriptLexer {
constructor(stream) {
this.stream = stream;
this.nextChar();

this.strBuf = [];
}
PostScriptLexer.prototype = {
nextChar: function PostScriptLexer_nextChar() {
return (this.currentChar = this.stream.getByte());
},
getToken: function PostScriptLexer_getToken() {
var comment = false;
var ch = this.currentChar;

// skip comments
while (true) {
if (ch < 0) {
return EOF;
}

if (comment) {
if (ch === 0x0A || ch === 0x0D) {
comment = false;
}
} else if (ch === 0x25) { // '%'
comment = true;
} else if (!isSpace(ch)) {
break;
}
ch = this.nextChar();
}
switch (ch | 0) {
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4'
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9'
case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.'
return new PostScriptToken(PostScriptTokenTypes.NUMBER,
this.getNumber());
case 0x7B: // '{'
this.nextChar();
return PostScriptToken.LBRACE;
case 0x7D: // '}'
this.nextChar();
return PostScriptToken.RBRACE;
}
// operator
var strBuf = this.strBuf;
strBuf.length = 0;
strBuf[0] = String.fromCharCode(ch);
nextChar() {
return (this.currentChar = this.stream.getByte());
}

while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z'
((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) {
strBuf.push(String.fromCharCode(ch));
}
var str = strBuf.join('');
switch (str.toLowerCase()) {
case 'if':
return PostScriptToken.IF;
case 'ifelse':
return PostScriptToken.IFELSE;
default:
return PostScriptToken.getOperator(str);
getToken() {
let comment = false;
let ch = this.currentChar;

// skip comments
while (true) {
if (ch < 0) {
return EOF;
}
},
getNumber: function PostScriptLexer_getNumber() {
var ch = this.currentChar;
var strBuf = this.strBuf;
strBuf.length = 0;
strBuf[0] = String.fromCharCode(ch);

while ((ch = this.nextChar()) >= 0) {
if ((ch >= 0x30 && ch <= 0x39) || // '0'-'9'
ch === 0x2D || ch === 0x2E) { // '-', '.'
strBuf.push(String.fromCharCode(ch));
} else {
break;

if (comment) {
if (ch === 0x0A || ch === 0x0D) {
comment = false;
}
} else if (ch === 0x25) { // '%'
comment = true;
} else if (!isSpace(ch)) {
break;
}
var value = parseFloat(strBuf.join(''));
if (isNaN(value)) {
throw new FormatError(`Invalid floating point number: ${value}`);
ch = this.nextChar();
}
switch (ch | 0) {
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: // '0'-'4'
case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: // '5'-'9'
case 0x2B: case 0x2D: case 0x2E: // '+', '-', '.'
return new PostScriptToken(PostScriptTokenTypes.NUMBER,
this.getNumber());
case 0x7B: // '{'
this.nextChar();
return PostScriptToken.LBRACE;
case 0x7D: // '}'
this.nextChar();
return PostScriptToken.RBRACE;
}
// operator
const strBuf = this.strBuf;
strBuf.length = 0;
strBuf[0] = String.fromCharCode(ch);

while ((ch = this.nextChar()) >= 0 && // and 'A'-'Z', 'a'-'z'
((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A))) {
strBuf.push(String.fromCharCode(ch));
}
const str = strBuf.join('');
switch (str.toLowerCase()) {
case 'if':
return PostScriptToken.IF;
case 'ifelse':
return PostScriptToken.IFELSE;
default:
return PostScriptToken.getOperator(str);
}
}

getNumber() {
let ch = this.currentChar;
const strBuf = this.strBuf;
strBuf.length = 0;
strBuf[0] = String.fromCharCode(ch);

while ((ch = this.nextChar()) >= 0) {
if ((ch >= 0x30 && ch <= 0x39) || // '0'-'9'
ch === 0x2D || ch === 0x2E) { // '-', '.'
strBuf.push(String.fromCharCode(ch));
} else {
break;
}
return value;
},
};
return PostScriptLexer;
})();
}
const value = parseFloat(strBuf.join(''));
if (isNaN(value)) {
throw new FormatError(`Invalid floating point number: ${value}`);
}
return value;
}
}

export {
PostScriptLexer,
Expand Down