Refactor and enable bits flipping in bitwise expression

This commit is contained in:
BorysLevytskyi
2023-05-06 18:43:37 +02:00
parent aa63449f99
commit e8e6e4697a
16 changed files with 110 additions and 110 deletions

View File

@@ -1,5 +1,5 @@
import calc from './calc'; import calc from './calc';
import { BitwiseOperationExpression, ScalarExpression, OperatorExpression } from '../expression/expression'; import { BitwiseOperationExpression, ScalarToken, OperatorToken } from '../expression/expression';
import exp from 'constants'; import exp from 'constants';
import { INT_MAX_VALUE } from './const'; import { INT_MAX_VALUE } from './const';
import formatter from './formatter'; import formatter from './formatter';
@@ -23,9 +23,9 @@ describe("calc", () => {
var result = calc.calcExpression(new BitwiseOperationExpression( var result = calc.calcExpression(new BitwiseOperationExpression(
"1|2&3", "1|2&3",
[ [
new ScalarExpression(1), new ScalarToken(1),
new OperatorExpression(new ScalarExpression(2), "|"), new OperatorToken(new ScalarToken(2), "|"),
new OperatorExpression(new ScalarExpression(3), "&"), new OperatorToken(new ScalarToken(3), "&"),
] ]
)); ));

View File

@@ -1,5 +1,5 @@
import { dblClick } from "@testing-library/user-event/dist/click"; import { dblClick } from "@testing-library/user-event/dist/click";
import { ExpressionInput } from "../expression/expression-interfaces"; import { Expression } from "../expression/expression-interfaces";
import { INT_MAX_VALUE } from "./const"; import { INT_MAX_VALUE } from "./const";
import { start } from "repl"; import { start } from "repl";
@@ -23,7 +23,7 @@ export default {
return Math.max.apply(null, counts); return Math.max.apply(null, counts);
}, },
calcExpression: function (expr: ExpressionInput) { calcExpression: function (expr: Expression) {
return eval(expr.expressionString); return eval(expr.expressionString);
}, },

View File

@@ -1,11 +1,11 @@
import { ExpressionInput, Expression } from "./expression-interfaces"; import { Expression, ExpressionToken } from "./expression-interfaces";
export default class BitwiseOperationExpression implements ExpressionInput { export default class BitwiseOperationExpression implements Expression {
expressionString: string; expressionString: string;
children: Expression[]; children: ExpressionToken[];
constructor(expressionString: string, children: Expression[]) { constructor(expressionString: string, children: ExpressionToken[]) {
this.expressionString = expressionString; this.expressionString = expressionString;
this.children = children; this.children = children;
} }

View File

@@ -1,6 +1,6 @@
import OperatorExpression from "./OperatorExpression"; import OperatorToken from "./OperatorToken";
import { ScalarExpression } from "./expression"; import { ScalarToken } from "./expression";
import { Expression } from "./expression-interfaces"; import { ExpressionToken } from "./expression-interfaces";
import { type } from "os"; import { type } from "os";
import { InputType } from "zlib"; import { InputType } from "zlib";
import exp from "constants"; import exp from "constants";

View File

@@ -1,7 +1,7 @@
import ScalarExpression from "./ScalarExpression"; import ScalarToken from "./ScalarToken";
import ListOfNumbersExpression from "./ListOfNumbersExpression"; import ListOfNumbersExpression from "./ListOfNumbersExpression";
it('calculates max bits length', () => { it('calculates max bits length', () => {
var expr = new ListOfNumbersExpression("10 0xabef 0b01010", [ScalarExpression.parse("10"), ScalarExpression.parse("0xabef"), ScalarExpression.parse("0b01010")]) var expr = new ListOfNumbersExpression("10 0xabef 0b01010", [ScalarToken.parse("10"), ScalarToken.parse("0xabef"), ScalarToken.parse("0b01010")])
expect(expr.maxBitsLength).toBe(16); expect(expr.maxBitsLength).toBe(16);
}); });

View File

@@ -1,13 +1,13 @@
import calc from "../core/calc"; import calc from "../core/calc";
import ScalarExpression from "./ScalarExpression"; import ScalarToken from "./ScalarToken";
import { ExpressionInput, Expression } from "./expression-interfaces"; import { Expression, ExpressionToken } from "./expression-interfaces";
export default class ListOfNumbersExpression implements ExpressionInput { export default class ListOfNumbersExpression implements Expression {
children: ScalarExpression[]; children: ScalarToken[];
expressionString: string; expressionString: string;
maxBitsLength: number; maxBitsLength: number;
constructor(expressionString: string, numbers: ScalarExpression[]) { constructor(expressionString: string, numbers: ScalarToken[]) {
this.expressionString = expressionString; this.expressionString = expressionString;
this.children = numbers; this.children = numbers;
this.maxBitsLength = numbers.map(n => calc.numberOfBitsDisplayed(n.value)).reduce((n , c) => n >= c ? n : c, 0); this.maxBitsLength = numbers.map(n => calc.numberOfBitsDisplayed(n.value)).reduce((n , c) => n >= c ? n : c, 0);

View File

@@ -1,25 +1,25 @@
import ScalarExpression from "./ScalarExpression"; import ScalarToken from "./ScalarToken";
import OperatorExpression from './OperatorExpression'; import OperatorToken from './OperatorToken';
import { INT_MAX_VALUE } from "../core/const"; import { INT_MAX_VALUE } from "../core/const";
it('can apply ~ operand', () => { it('can apply ~ operand', () => {
var op = new ScalarExpression(10, 'dec'); var op = new ScalarToken(10, 'dec');
var expr = new OperatorExpression(op, "~"); var expr = new OperatorToken(op, "~");
var result = expr.evaluate(); var result = expr.evaluate();
expect(result.value).toBe(-11); expect(result.value).toBe(-11);
expect(result.base).toBe('dec'); expect(result.base).toBe('dec');
}); });
it('can apply & operand', () => { it('can apply & operand', () => {
var op1 = new ScalarExpression(3, 'dec'); var op1 = new ScalarToken(3, 'dec');
var op2 = new ScalarExpression(4, 'dec'); var op2 = new ScalarToken(4, 'dec');
var expr = new OperatorExpression(op1, "|"); var expr = new OperatorToken(op1, "|");
var result = expr.evaluate(op2); var result = expr.evaluate(op2);
expect(result.value).toBe(7); expect(result.value).toBe(7);
expect(result.base).toBe('dec'); expect(result.base).toBe('dec');
}); });
it("doesn't support opreations with numbers larger than 32-bit", () => { it("doesn't support opreations with numbers larger than 32-bit", () => {
expect(() => new OperatorExpression(new ScalarExpression(2147483648), "^")) expect(() => new OperatorToken(new ScalarToken(2147483648), "^"))
.toThrowError("2147483648 has more than 32 bits. JavaScript converts all numbers to 32-bit integers when applying bitwise operators. BitwiseCmd currently uses the JavaScript engine of your browser for results calculation and supports numbers in the range from -2147483647 to 2147483647"); .toThrowError("2147483648 has more than 32 bits. JavaScript converts all numbers to 32-bit integers when applying bitwise operators. BitwiseCmd currently uses the JavaScript engine of your browser for results calculation and supports numbers in the range from -2147483647 to 2147483647");
}); });

View File

@@ -1,18 +1,18 @@
import { INT_MAX_VALUE } from '../core/const'; import { INT_MAX_VALUE } from '../core/const';
import formatter from '../core/formatter'; import formatter from '../core/formatter';
import ScalarExpression from './ScalarExpression'; import ScalarToken from './ScalarToken';
import { Expression } from './expression-interfaces'; import { ExpressionToken } from './expression-interfaces';
export default class OperatorExpression implements Expression { export default class OperatorToken implements ExpressionToken {
operand: Expression; operand: ExpressionToken;
operator: string; operator: string;
isOperator: boolean; isOperator: boolean;
isShiftExpression: boolean; isShiftExpression: boolean;
isNotExpression: boolean; isNotExpression: boolean;
constructor(operand : Expression, operator : string) { constructor(operand : ExpressionToken, operator : string) {
if(operand instanceof ScalarExpression) { if(operand instanceof ScalarToken) {
const o = operand.getUnderlyingScalarOperand(); const o = operand.getUnderlyingScalarOperand();
if(Math.abs(o.value) > INT_MAX_VALUE) { if(Math.abs(o.value) > INT_MAX_VALUE) {
const n = formatter.numberToString(o.value, o.base); const n = formatter.numberToString(o.value, o.base);
@@ -27,8 +27,8 @@ export default class OperatorExpression implements Expression {
this.isNotExpression = this.operator === '~'; this.isNotExpression = this.operator === '~';
} }
evaluate(operand?: ScalarExpression) : ScalarExpression { evaluate(operand?: ScalarToken) : ScalarToken {
if (operand instanceof OperatorExpression) { if (operand instanceof OperatorToken) {
throw new Error('value shouldnt be expression'); throw new Error('value shouldnt be expression');
} }
@@ -44,10 +44,10 @@ export default class OperatorExpression implements Expression {
str = operand.value + this.operator + evaluatedOperand.value; str = operand.value + this.operator + evaluatedOperand.value;
} }
return ScalarExpression.create(eval(str), evaluatedOperand.base); return ScalarToken.create(eval(str), evaluatedOperand.base);
} }
getUnderlyingScalarOperand() : ScalarExpression { getUnderlyingScalarOperand() : ScalarToken {
return this.operand.getUnderlyingScalarOperand(); return this.operand.getUnderlyingScalarOperand();
} }

View File

@@ -1,19 +1,19 @@
import ScalarExpression from './ScalarExpression'; import ScalarToken from './ScalarToken';
it('parsed from dec string', () => { it('parsed from dec string', () => {
var op = ScalarExpression.parse('123'); var op = ScalarToken.parse('123');
expect(op.base).toBe('dec'); expect(op.base).toBe('dec');
expect(op.value).toBe(123); expect(op.value).toBe(123);
}); });
it('parsed from bin string', () => { it('parsed from bin string', () => {
var op = ScalarExpression.parse('0b10'); var op = ScalarToken.parse('0b10');
expect(op.base).toBe('bin'); expect(op.base).toBe('bin');
expect(op.value).toBe(2); expect(op.value).toBe(2);
}); });
it('parsed from hex string', () => { it('parsed from hex string', () => {
var op = ScalarExpression.parse('0x10'); var op = ScalarToken.parse('0x10');
expect(op.base).toBe('hex'); expect(op.base).toBe('hex');
expect(op.value).toBe(16); expect(op.value).toBe(16);
}); });

View File

@@ -1,5 +1,5 @@
import {numberParser} from './numberParser'; import {numberParser} from './numberParser';
import { Expression as Expression } from './expression-interfaces'; import { ExpressionToken as ExpressionToken } from './expression-interfaces';
import { NumberBase } from '../core/formatter'; import { NumberBase } from '../core/formatter';
import { INT_MAX_VALUE } from '../core/const'; import { INT_MAX_VALUE } from '../core/const';
@@ -7,7 +7,7 @@ var globalId : number = 1;
// Represents scalar numeric value // Represents scalar numeric value
export default class ScalarExpression implements Expression { export default class ScalarToken implements ExpressionToken {
id: number; id: number;
value: number; value: number;
base: NumberBase; base: NumberBase;
@@ -25,21 +25,21 @@ export default class ScalarExpression implements Expression {
this.value = value; this.value = value;
} }
evaluate() : ScalarExpression { evaluate() : ScalarToken {
return this; return this;
} }
getUnderlyingScalarOperand() : ScalarExpression { getUnderlyingScalarOperand() : ScalarToken {
return this return this
} }
static create(value : number, base? : NumberBase) { static create(value : number, base? : NumberBase) {
return new ScalarExpression(value, base || "dec"); return new ScalarToken(value, base || "dec");
}; };
static parse(input: string) : ScalarExpression { static parse(input: string) : ScalarToken {
var parsed = ScalarExpression.tryParse(input); var parsed = ScalarToken.tryParse(input);
if(parsed == null) { if(parsed == null) {
throw new Error(input + " is not a valid number"); throw new Error(input + " is not a valid number");
@@ -48,7 +48,7 @@ export default class ScalarExpression implements Expression {
return parsed; return parsed;
} }
static tryParse(input: string) : ScalarExpression | null { static tryParse(input: string) : ScalarToken | null {
var parsed = numberParser.parse(input); var parsed = numberParser.parse(input);
@@ -56,7 +56,7 @@ export default class ScalarExpression implements Expression {
return null; return null;
} }
return new ScalarExpression(parsed.value, parsed.base); return new ScalarToken(parsed.value, parsed.base);
} }
} }

View File

@@ -2,11 +2,11 @@ import React from 'react';
import formatter from '../../core/formatter'; import formatter from '../../core/formatter';
import BinaryStringView, { FlipBitEventArg } from '../../core/components/BinaryString'; import BinaryStringView, { FlipBitEventArg } from '../../core/components/BinaryString';
import BitwiseResultViewModel from './BitwiseResultViewModel'; import BitwiseResultViewModel from './BitwiseResultViewModel';
import { ExpressionInput, Expression } from '../expression-interfaces'; import { Expression, ExpressionToken } from '../expression-interfaces';
import { OperatorExpression, ScalarExpression } from '../expression'; import { OperatorToken, ScalarToken } from '../expression';
type BitwiseOperationExpressionViewProps = { type BitwiseOperationExpressionViewProps = {
expression: ExpressionInput; expression: Expression;
emphasizeBytes: boolean; emphasizeBytes: boolean;
} }
@@ -59,7 +59,7 @@ type ExpressionRowProps = {
maxNumberOfBits: number, maxNumberOfBits: number,
emphasizeBytes: boolean, emphasizeBytes: boolean,
allowFlipBits: boolean, allowFlipBits: boolean,
expressionItem: Expression, expressionItem: ExpressionToken,
onBitFlipped: any onBitFlipped: any
} }
@@ -71,7 +71,7 @@ class ExpressionRow extends React.Component<ExpressionRowProps> {
render() { render() {
const { sign, css, maxNumberOfBits, emphasizeBytes, allowFlipBits } = this.props; const { sign, css, maxNumberOfBits, emphasizeBytes, allowFlipBits } = this.props;
return <tr className={css}> return <tr className={"row-with-bits " + css}>
<td className="sign">{sign}</td> <td className="sign">{sign}</td>
<td className="label">{this.getLabel()}</td> <td className="label">{this.getLabel()}</td>
<td className="bin"> <td className="bin">
@@ -95,7 +95,7 @@ class ExpressionRow extends React.Component<ExpressionRowProps> {
// For expressions like |~2 // For expressions like |~2
// TODO: find a better way... // TODO: find a better way...
if(this.props.expressionItem.isOperator) { if(this.props.expressionItem.isOperator) {
const ex = this.props.expressionItem as OperatorExpression; const ex = this.props.expressionItem as OperatorToken;
return ex.operator + this.getLabelString(ex.getUnderlyingScalarOperand()); return ex.operator + this.getLabelString(ex.getUnderlyingScalarOperand());
} }
@@ -105,7 +105,7 @@ class ExpressionRow extends React.Component<ExpressionRowProps> {
getAlternative() { getAlternative() {
if(this.props.expressionItem.isOperator) { if(this.props.expressionItem.isOperator) {
const ex = this.props.expressionItem as OperatorExpression; const ex = this.props.expressionItem as OperatorToken;
const res = ex.evaluate(); const res = ex.evaluate();
return formatter.numberToString(res.value, res.base); return formatter.numberToString(res.value, res.base);
@@ -116,7 +116,7 @@ class ExpressionRow extends React.Component<ExpressionRowProps> {
return formatter.numberToString(v.value, altBase); return formatter.numberToString(v.value, altBase);
} }
getLabelString (op: ScalarExpression) : string { getLabelString (op: ScalarToken) : string {
return formatter.numberToString(op.value, op.base == 'bin' ? 'dec' : op.base); return formatter.numberToString(op.value, op.base == 'bin' ? 'dec' : op.base);
} }

View File

@@ -1,5 +1,5 @@
import { ScalarExpression, ListOfNumbersExpression, BitwiseOperationExpression, OperatorExpression } from '../expression'; import { ScalarToken, ListOfNumbersExpression, BitwiseOperationExpression, OperatorToken } from '../expression';
import { Expression, ExpressionInput } from '../expression-interfaces'; import { ExpressionToken, Expression } from '../expression-interfaces';
import calc from '../../core/calc'; import calc from '../../core/calc';
import formatter from '../../core/formatter'; import formatter from '../../core/formatter';
@@ -8,10 +8,10 @@ type Config = {
allowFlipBits: boolean; allowFlipBits: boolean;
} }
type ExpressionItemModel = { type ExpressionRowModel = {
sign: string; sign: string;
css: string; css: string;
expression: Expression; expression: ExpressionToken;
allowFlipBits: boolean; allowFlipBits: boolean;
label: string; label: string;
} }
@@ -19,7 +19,7 @@ type ExpressionItemModel = {
export default class BitwiseResultViewModel { export default class BitwiseResultViewModel {
emphasizeBytes: boolean; emphasizeBytes: boolean;
items: ExpressionItemModel[]; items: ExpressionRowModel[];
maxNumberOfBits: number; maxNumberOfBits: number;
allowFlipBits: boolean; allowFlipBits: boolean;
@@ -43,17 +43,17 @@ export default class BitwiseResultViewModel {
i = 0, len = expr.children.length, i = 0, len = expr.children.length,
ex, m = new BitwiseResultViewModel(config); ex, m = new BitwiseResultViewModel(config);
var prev : ScalarExpression | null = null; var prev : ScalarToken | null = null;
for (;i<len;i++) { for (;i<len;i++) {
ex = expr.children[i]; ex = expr.children[i];
if(ex instanceof ScalarExpression) { if(ex instanceof ScalarToken) {
m.addScalarRow(ex); m.addScalarRow(ex);
prev = ex; prev = ex;
continue; continue;
} }
var eo = ex as OperatorExpression; var eo = ex as OperatorToken;
// If it a single NOT expression // If it a single NOT expression
if(eo.isNotExpression) { if(eo.isNotExpression) {
@@ -63,11 +63,11 @@ export default class BitwiseResultViewModel {
prev = notResult; prev = notResult;
} }
else if(eo.isShiftExpression){ else if(eo.isShiftExpression){
prev = eo.evaluate(prev as ScalarExpression); prev = eo.evaluate(prev as ScalarToken);
m.addShiftExpressionResultRow(eo, prev); m.addShiftExpressionResultRow(eo, prev);
} else { } else {
prev = eo.evaluate(prev as ScalarExpression); prev = eo.evaluate(prev as ScalarToken);
m.addOperatorRow(eo); m.addOperatorRow(eo);
m.addExpressionResultRow(prev); m.addExpressionResultRow(prev);
} }
@@ -77,7 +77,7 @@ export default class BitwiseResultViewModel {
return m; return m;
}; };
addScalarRow(expr: ScalarExpression) { addScalarRow(expr: ScalarToken) {
const bits = calc.numberOfBitsDisplayed(expr.value); const bits = calc.numberOfBitsDisplayed(expr.value);
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits); this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
this.items.push({ this.items.push({
@@ -89,7 +89,7 @@ export default class BitwiseResultViewModel {
}); });
}; };
addOperatorRow(expr: OperatorExpression) { addOperatorRow(expr: OperatorToken) {
const resultNumber = expr.isNotExpression ? expr.evaluate() : expr.getUnderlyingScalarOperand(); const resultNumber = expr.isNotExpression ? expr.evaluate() : expr.getUnderlyingScalarOperand();
const bits = calc.numberOfBitsDisplayed(resultNumber.value); const bits = calc.numberOfBitsDisplayed(resultNumber.value);
@@ -104,7 +104,7 @@ export default class BitwiseResultViewModel {
}); });
}; };
addShiftExpressionResultRow(expr : OperatorExpression, resultExpr : ScalarExpression) { addShiftExpressionResultRow(expr : OperatorToken, resultExpr : ScalarToken) {
const bits = calc.numberOfBitsDisplayed(resultExpr.value); const bits = calc.numberOfBitsDisplayed(resultExpr.value);
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits); this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
const child = expr.operand.getUnderlyingScalarOperand(); const child = expr.operand.getUnderlyingScalarOperand();
@@ -117,7 +117,7 @@ export default class BitwiseResultViewModel {
}); });
}; };
addExpressionResultRow(expr : ScalarExpression) { addExpressionResultRow(expr : ScalarToken) {
const bits = calc.numberOfBitsDisplayed(expr.value); const bits = calc.numberOfBitsDisplayed(expr.value);
this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits); this.maxNumberOfBits = Math.max(bits, this.maxNumberOfBits);
this.items.push({ this.items.push({
@@ -129,7 +129,7 @@ export default class BitwiseResultViewModel {
}); });
}; };
getLabel (op: ScalarExpression) : string { getLabel (op: ScalarToken) : string {
return formatter.numberToString(op.value, op.base === 'bin' ? 'dec' : op.base) return formatter.numberToString(op.value, op.base === 'bin' ? 'dec' : op.base)
} }
@@ -148,7 +148,7 @@ export default class BitwiseResultViewModel {
return bits; return bits;
}; };
static createModel(expr : ExpressionInput, emphasizeBytes: boolean) : BitwiseResultViewModel { static createModel(expr : Expression, emphasizeBytes: boolean) : BitwiseResultViewModel {
if(expr instanceof ListOfNumbersExpression) { if(expr instanceof ListOfNumbersExpression) {
return BitwiseResultViewModel.buildListOfNumbers(expr, { return BitwiseResultViewModel.buildListOfNumbers(expr, {
emphasizeBytes: emphasizeBytes, emphasizeBytes: emphasizeBytes,
@@ -159,7 +159,7 @@ export default class BitwiseResultViewModel {
if(expr instanceof BitwiseOperationExpression) { if(expr instanceof BitwiseOperationExpression) {
return BitwiseResultViewModel.buildBitwiseOperation(expr, { return BitwiseResultViewModel.buildBitwiseOperation(expr, {
emphasizeBytes: emphasizeBytes, emphasizeBytes: emphasizeBytes,
allowFlipBits: false allowFlipBits: true
}); });
} }

View File

@@ -1,14 +1,14 @@
import { ScalarExpression } from "./expression"; import { ScalarToken } from "./expression";
export interface ExpressionInput export interface Expression
{ {
expressionString: string; expressionString: string;
} }
export interface Expression export interface ExpressionToken
{ {
isOperator: boolean; isOperator: boolean;
getUnderlyingScalarOperand: () => ScalarExpression; getUnderlyingScalarOperand: () => ScalarToken;
evaluate(operand? : ScalarExpression): ScalarExpression; evaluate(operand? : ScalarToken): ScalarToken;
} }

View File

@@ -1,4 +1,4 @@
import { parser, ListOfNumbersExpression, BitwiseOperationExpression, ScalarExpression, OperatorExpression } from "./expression"; import { parser, ListOfNumbersExpression, BitwiseOperationExpression, ScalarToken, OperatorToken } from "./expression";
describe("expression parser", () => { describe("expression parser", () => {
@@ -36,16 +36,16 @@ describe("expression parser", () => {
const first = result.children[0]; const first = result.children[0];
const second = result.children[1]; const second = result.children[1];
expect(first).toBeInstanceOf(ScalarExpression); expect(first).toBeInstanceOf(ScalarToken);
expect((first as ScalarExpression).value).toBe(1); expect((first as ScalarToken).value).toBe(1);
expect(second).toBeInstanceOf(OperatorExpression); expect(second).toBeInstanceOf(OperatorToken);
var secondOp = second as OperatorExpression; var secondOp = second as OperatorToken;
expect(secondOp.operator).toBe("^"); expect(secondOp.operator).toBe("^");
expect(secondOp.operand).toBeInstanceOf(ScalarExpression); expect(secondOp.operand).toBeInstanceOf(ScalarToken);
var childOp = secondOp.operand as ScalarExpression; var childOp = secondOp.operand as ScalarToken;
expect(childOp.value).toBe(2); expect(childOp.value).toBe(2);
}); });

View File

@@ -1,18 +1,18 @@
import ScalarExpression from './ScalarExpression'; import ScalarToken from './ScalarToken';
import OperatorExpression from './OperatorExpression' import OperatorToken from './OperatorToken'
import ListOfNumbersExpression from './ListOfNumbersExpression'; import ListOfNumbersExpression from './ListOfNumbersExpression';
import BitwiseOperationExpression from './BitwiseOperationExpression'; import BitwiseOperationExpression from './BitwiseOperationExpression';
import { ExpressionInput, Expression } from './expression-interfaces'; import { Expression, ExpressionToken } from './expression-interfaces';
import { NumberBase } from '../core/formatter'; import { NumberBase } from '../core/formatter';
export { default as ScalarExpression } from './ScalarExpression'; export { default as ScalarToken } from './ScalarToken';
export { default as OperatorExpression } from './OperatorExpression'; export { default as OperatorToken } from './OperatorToken';
export { default as ListOfNumbersExpression } from './ListOfNumbersExpression'; export { default as ListOfNumbersExpression } from './ListOfNumbersExpression';
export { default as BitwiseOperationExpression } from './BitwiseOperationExpression'; export { default as BitwiseOperationExpression } from './BitwiseOperationExpression';
interface IExpressionParserFactory { interface IExpressionParserFactory {
canCreate: (input: string) => boolean; canCreate: (input: string) => boolean;
create: (input: string) => ExpressionInput; create: (input: string) => Expression;
}; };
class ExpressionParser { class ExpressionParser {
@@ -32,7 +32,7 @@ class ExpressionParser {
return false; return false;
}; };
parse (input: string) : ExpressionInput | null { parse (input: string) : Expression | null {
var trimmed = input.replace(/^\s+|\s+$/, ''); var trimmed = input.replace(/^\s+|\s+$/, '');
var i = 0, l = this.factories.length, factory; var i = 0, l = this.factories.length, factory;
@@ -47,12 +47,12 @@ class ExpressionParser {
return null; return null;
}; };
parseOperand (input : string) : ScalarExpression { parseOperand (input : string) : ScalarToken {
return ScalarExpression.parse(input); return ScalarToken.parse(input);
}; };
createOperand (number : number, base : NumberBase) : ScalarExpression { createOperand (number : number, base : NumberBase) : ScalarToken {
return ScalarExpression.create(number, base); return ScalarToken.create(number, base);
}; };
addFactory (factory: IExpressionParserFactory) { addFactory (factory: IExpressionParserFactory) {
@@ -70,16 +70,16 @@ class ListOfNumbersExpressionFactory implements IExpressionParserFactory
return input.split(' ') return input.split(' ')
.filter(p => p.length > 0) .filter(p => p.length > 0)
.map(p => ScalarExpression.tryParse(p)) .map(p => ScalarToken.tryParse(p))
.filter(n => n == null) .filter(n => n == null)
.length == 0; .length == 0;
}; };
create (input : string) : ExpressionInput { create (input : string) : Expression {
const numbers = input.split(' ') const numbers = input.split(' ')
.filter(p => p.length > 0) .filter(p => p.length > 0)
.map(m => ScalarExpression.parse(m)); .map(m => ScalarToken.parse(m));
return new ListOfNumbersExpression(input, numbers); return new ListOfNumbersExpression(input, numbers);
} }
@@ -99,9 +99,9 @@ class BitwiseOperationExpressionFactory implements IExpressionParserFactory {
return this.fullRegex.test(this.normalizeString(input)); return this.fullRegex.test(this.normalizeString(input));
}; };
create (input: string) : ExpressionInput { create (input: string) : Expression {
var m : RegExpExecArray | null; var m : RegExpExecArray | null;
const operands : Expression[] = []; const operands : ExpressionToken[] = [];
const normalizedString = this.normalizeString(input); const normalizedString = this.normalizeString(input);
this.regex.lastIndex = 0; this.regex.lastIndex = 0;
@@ -113,23 +113,23 @@ class BitwiseOperationExpressionFactory implements IExpressionParserFactory {
return new BitwiseOperationExpression(normalizedString, operands) return new BitwiseOperationExpression(normalizedString, operands)
}; };
parseMatch (m:any): Expression { parseMatch (m:any): ExpressionToken {
var input = m[0], var input = m[0],
operator = m[1], operator = m[1],
num = m[2]; num = m[2];
var parsed = null; var parsed = null;
if(num.indexOf('~') == 0) { if(num.indexOf('~') == 0) {
parsed = new OperatorExpression(ScalarExpression.parse(num.substring(1)), '~'); parsed = new OperatorToken(ScalarToken.parse(num.substring(1)), '~');
} }
else { else {
parsed = ScalarExpression.parse(num); parsed = ScalarToken.parse(num);
} }
if(operator == null) { if(operator == null) {
return parsed as OperatorExpression; return parsed as OperatorToken;
} else { } else {
return new OperatorExpression(parsed as ScalarExpression, operator); return new OperatorToken(parsed as ScalarToken, operator);
} }
}; };

View File

@@ -14,7 +14,7 @@ export class IpAddressView extends React.Component<IpAddressViewProps>
render() { render() {
return <table className="expression"> return <table className="expression">
<tbody> <tbody>
{this.props.ipAddresses.map((ip, i) => <tr key={i}> {this.props.ipAddresses.map((ip, i) => <tr key={i} className='row-with-bits'>
<td className="label"><strong>{ip.toString()}</strong></td> <td className="label"><strong>{ip.toString()}</strong></td>
<td className="bin"> <td className="bin">
{this.bin(ip.firstByte, 1, ip)}<span className="soft">.</span> {this.bin(ip.firstByte, 1, ip)}<span className="soft">.</span>