attrpath
Version:
Attribute Path Traverser.
404 lines • 10.6 kB
JavaScript
/**
* Copyright © 2020 2021 2022 7thCode.(http://seventh-code.com/)
* This software is released under the MIT License.
* opensource.org/licenses/mit-license.php
*/
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AttributeParser = exports.FormulaParser = exports.BaseParser = exports.TokenType = void 0;
var TokenType;
(function (TokenType) {
TokenType[TokenType["operator"] = 0] = "operator";
TokenType[TokenType["number"] = 1] = "number";
TokenType[TokenType["name"] = 2] = "name";
TokenType[TokenType["index"] = 3] = "index";
})(TokenType = exports.TokenType || (exports.TokenType = {}));
/**
* BaseParser
* @remarks
*/
class BaseParser {
/**
*
* @remarks
*/
constructor(handler, stream) {
this.stream = stream;
this.handler = handler;
}
/**
* is_s
* s ::= | \t
*/
is_s() {
const code = this.stream.charCode;
return (code === 32) || (code === 9);
}
/**
* is_s
*
* S ::= ( " " | tab ) *
*
* @remarks Spaces or Tabs
*/
parse_s() {
let result = false;
while (this.is_s()) {
this.stream.next();
result = true;
}
return result;
}
/**
* is_terminal
*
* @remarks
*
*/
is_terminal() {
return this.stream.is_terminal;
}
/**
* is_char
*
* @param c
*
* @remarks
*/
is_char(c) {
let result = false;
const char = this.stream.char;
if (char === c) {
this.stream.next();
result = true;
}
return result;
}
/**/
between(data, s, e) {
return ((s <= data) && (data <= e));
}
/**
* is_symbol
* symbol ::= "." | "[" | "]" | "'" | '"' | "+" | "-" | "*" | "/" | "%" | "~" | "&" | "|" | "^" | ">" | "<" | "!" | "=" | "`" | "(" | ")" | "{" | "}" | "?" | ":" | ";" | ","
* @remarks
*/
/*
protected is_symbol(): boolean {
let result: boolean = false;
const code: number = this.stream.charCode;
switch (code) {
case 33: // "!"
case 34: // "'"
case 91: // "["
case 93: // "]"
case 94: // "^"
case 96: // "`"
this.stream.next();
result = true;
break;
default: // '%&"()*+,-./' ":;<=>?" "{|}~"
if (this.between(code, 37, 47) || this.between(code, 58, 63) || this.between(code, 123, 126)) {
this.stream.next();
result = true;
}
break;
}
return result;
}
*/
/**
* is_digit
* digit ::= ( 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 )
*/
is_digit() {
const code = this.stream.charCode;
return this.between(code, 48, 57);
}
/**
* parse_number
* number ::= digit *
*/
parse_number() {
let result = false;
this.stream.restore_point();
while (this.is_digit()) {
this.stream.next();
result = true;
}
if (this.handler) {
this.handler.token(TokenType.number, this.stream.current, this.is_terminal());
}
return result;
}
}
exports.BaseParser = BaseParser;
class FormulaParser extends BaseParser {
/**
*
* @remarks
*/
constructor(handler, stream) {
super(handler, stream);
}
/**
*
* expr ::= term { S { "+" | "-" } S term } *
* @remarks
* */
is_expr() {
let result = false;
this.stream.restore_point();
this.parse_s();
if (this.is_term()) {
result = true;
while (true) {
const char = this.stream.char;
if (this.is_char("+") || this.is_char("-")) {
if (this.handler) {
this.handler.token(TokenType.operator, char, this.is_terminal());
}
if (this.is_term()) {
result = true;
}
}
else {
break;
}
}
}
return result;
}
/**
* is_term
*
* @remarks
* term ::= factor { S { "*" | "/" } S factor } *
*
*
* */
is_term() {
let result = false;
this.stream.restore_point();
this.parse_s();
if (this.is_factor()) {
result = true;
while (true) {
const char = this.stream.char;
if (this.is_char("*") || this.is_char("/")) {
if (this.handler) {
this.handler.token(TokenType.operator, char, this.is_terminal());
}
if (this.is_factor()) {
result = true;
}
}
else {
break;
}
}
}
return result;
}
/**
* is_factor
*
* @remarks
* factor ::= "(" S expr S ")" | number
*
* */
is_factor() {
let result = false;
this.stream.restore_point();
this.parse_s();
const char = this.stream.char;
if (this.is_char("(")) {
if (this.handler) {
this.handler.token(TokenType.operator, char, this.is_terminal());
}
if (this.is_expr()) {
const char = this.stream.char;
if (this.is_char(")")) {
if (this.handler) {
this.handler.token(TokenType.operator, char, this.is_terminal());
}
this.parse_s();
result = true;
}
}
}
else if (this.parse_number()) {
this.parse_s();
result = true;
}
return result;
}
}
exports.FormulaParser = FormulaParser;
/**
* Parse semantic strings of object references in JavaScript.
*
*/
class AttributeParser extends FormulaParser {
/**
*
* @remarks
*
*/
constructor(handler, stream) {
super(handler, stream);
}
/**
* is_reading
*
* @remarks
* reading ::= ( alpha | "_" | "$" ) *
*
*/
is_reading() {
const code = this.stream.charCode;
return (((0x3040 <= code) && (code <= 0x2FFFF)) || //
((65 <= code) && (code <= 90)) || ((97 <= code) && (code <= 122)) || // Alphabet
(code === 95) || (code === 36)); // _ $
}
/**
* is_trailing
*
* @remarks
* trailing ::= ( alpha | "_" | "$" | digit ) *
*
*/
is_trailing() {
const code = this.stream.charCode;
return (((0x3040 <= code) && (code <= 0x2FFFF)) || //
((65 <= code) && (code <= 90)) || ((97 <= code) && (code <= 122)) || // Alphabet
((48 <= code) && (code <= 57)) || // Number
(code === 95) || (code === 36)); // _ $
}
/**
* is_subscript_trailing
*
* @remarks
* subscript_trailing ::= ( alpha | "_" | "$" | digit | "." ) *
*
*/
is_subscript_trailing() {
const code = this.stream.charCode;
return (((0x3040 <= code) && (code <= 0x2FFFF)) || //
((65 <= code) && (code <= 90)) || ((97 <= code) && (code <= 122)) || // Alphabet
((48 <= code) && (code <= 57)) || // Number
(code === 95) || (code === 36) || // _ $
(code === 46)); // .
}
/**
* parse_name
*
* @remarks
* name ::= reading [ trailing ]
*
*/
parse_name() {
let result = false;
this.stream.restore_point();
if (this.is_reading()) {
this.stream.next();
result = true;
while (this.is_trailing()) {
this.stream.next();
result = true;
}
}
if (this.handler) {
this.handler.token(TokenType.name, this.stream.current, this.is_terminal());
}
return result;
}
/**
* parse_subscript_name
*
* @remarks
* subscript_name ::= subscript_reading [ subscript_trailing ]
*
*/
parse_subscript_name() {
let result = false;
this.stream.restore_point();
if (this.is_reading()) {
this.stream.next();
result = true;
while (this.is_subscript_trailing()) {
this.stream.next();
result = true;
}
}
if (this.handler) {
this.handler.token(TokenType.name, this.stream.current, this.is_terminal());
}
return result;
}
/**
* parse_subscript_string
*
* @remarks
* subscript_string = "'" subscript_mame "'" | '"' subscript_mame '"'
*
*/
parse_subscript_string() {
let result = false;
this.stream.restore_point();
if (this.is_char("'") || this.is_char('"')) {
if (this.parse_subscript_name()) {
if ((this.is_char("'") || this.is_char('"'))) {
result = true;
}
}
}
return result;
}
/**
* parse_attr
*
* @remarks
* attr ::= "." name | '[' subscript_string | number ']'
*
*/
parse_attr() {
let result = false;
this.stream.restore_point();
if (this.is_char("[")) {
if (this.parse_subscript_string()) {
result = this.is_char("]");
}
else if (this.parse_number()) {
const word = this.stream.current;
if (this.is_char("]")) {
if (this.handler) {
this.handler.token(TokenType.index, word, this.is_terminal());
}
result = true;
}
}
}
else if (this.is_char(".")) {
result = this.parse_name();
}
return result;
}
/**
* parse_path
*
* @remarks
* path ::= attr *
*
*/
parse_path() {
let result = false;
this.stream.restore_point();
while (this.parse_attr()) {
result = (this.is_terminal());
}
return result;
}
}
exports.AttributeParser = AttributeParser;
//# sourceMappingURL=parser.js.map