diff --git a/src/core/calc.test.ts b/src/core/calc.test.ts index 97e1ed3..05c892c 100644 --- a/src/core/calc.test.ts +++ b/src/core/calc.test.ts @@ -1,5 +1,5 @@ import calc from './calc'; -import { BitwiseOperationExpression, NumericOperand, ExpressionOperand } from '../expression/expression'; +import { BitwiseOperationExpression, ScalarOperand, ExpressionOperand } from '../expression/expression'; import exp from 'constants'; describe("calc", () => { @@ -18,9 +18,9 @@ describe("calc", () => { var result = calc.calcExpression(new BitwiseOperationExpression( "1|2&3", [ - new NumericOperand(1), - new ExpressionOperand("|2", new NumericOperand(2), "|"), - new ExpressionOperand("&3", new NumericOperand(3), "&"), + new ScalarOperand(1), + new ExpressionOperand("|2", new ScalarOperand(2), "|"), + new ExpressionOperand("&3", new ScalarOperand(3), "&"), ] )); diff --git a/src/expression/ExpressionOperand.test.ts b/src/expression/ExpressionOperand.test.ts index 695c41c..8346c91 100644 --- a/src/expression/ExpressionOperand.test.ts +++ b/src/expression/ExpressionOperand.test.ts @@ -1,8 +1,8 @@ -import NumericOperand from "./NumericOperand"; +import ScalarOperand from "./ScalarOperand"; import ExpressionOperand from './ExpressionOperand'; it('can apply ~ operand', () => { - var op = new NumericOperand(10, 'dec'); + var op = new ScalarOperand(10, 'dec'); var expr = new ExpressionOperand("~10", op, "~"); var result = expr.evaluate(); expect(result.value).toBe(-11); @@ -10,8 +10,8 @@ it('can apply ~ operand', () => { }); it('can apply & operand', () => { - var op1 = new NumericOperand(3, 'dec'); - var op2 = new NumericOperand(4, 'dec'); + var op1 = new ScalarOperand(3, 'dec'); + var op2 = new ScalarOperand(4, 'dec'); var expr = new ExpressionOperand("|3", op1, "|"); var result = expr.evaluate(op2); expect(result.value).toBe(7); diff --git a/src/expression/ExpressionOperand.ts b/src/expression/ExpressionOperand.ts index 63e8e1c..0fb250b 100644 --- a/src/expression/ExpressionOperand.ts +++ b/src/expression/ExpressionOperand.ts @@ -1,4 +1,4 @@ -import NumericOperand from './NumericOperand'; +import ScalarOperand from './ScalarOperand'; import { ExpressionInputItem } from './expression-interfaces'; export default class ExpressionOperand implements ExpressionInputItem { @@ -18,7 +18,7 @@ export default class ExpressionOperand implements ExpressionInputItem { this.isNotExpression = this.sign === '~'; } - evaluate(operand?: NumericOperand) : NumericOperand { + evaluate(operand?: ScalarOperand) : ScalarOperand { if (operand instanceof ExpressionOperand) { throw new Error('value shouldnt be expression'); } @@ -35,10 +35,10 @@ export default class ExpressionOperand implements ExpressionInputItem { str = operand.value + this.sign + evaluatedOperand.value; } - return NumericOperand.create(eval(str), evaluatedOperand.base); + return ScalarOperand.create(eval(str), evaluatedOperand.base); } - getUnderlyingOperand() : NumericOperand { + getUnderlyingOperand() : ScalarOperand { return this.operand.getUnderlyingOperand(); } diff --git a/src/expression/ExpressionParser.test.ts b/src/expression/ExpressionParser.test.ts new file mode 100644 index 0000000..da36764 --- /dev/null +++ b/src/expression/ExpressionParser.test.ts @@ -0,0 +1,68 @@ +import { NumericLiteral } from "typescript"; +import ExpressionOperand from "./ExpressionOperand"; +import { ScalarOperand } from "./expression"; +import { ExpressionInputItem } from "./expression-interfaces"; + +const NUMBER_REGEX = /./; + +class ExpressionParser +{ + input: string; + pos: number; + + constructor(input: string) { + this.input = input; + this.pos = 0; + } + + tryParse () : ExpressionInputItem[] | null { + return null; + } + + parse() : ExpressionInputItem[] { + const s = this.input; + const p = this.pos; + const items : ExpressionInputItem[] = []; + + while(p < s.length) { + + + + } + + return items; + } + + parseSingle(): ExpressionInputItem { + const s = this.input; + const p = this.pos; + + const ch = s[p]; + + if(ch == '~') + { + this.move(1); + const inner = this.parseSingle() + return new ExpressionOperand("~" + inner, inner, "~"); + } + + const ss = s.substring(p); + const scalar = ScalarOperand.tryParse(ss); + + if(scalar == null) + throw new Error(`Expected scalar value at pos ${p}: ${ss}`); + + return {} as ExpressionInputItem; + } + + move(step : number) { + this.pos += step; + } + + +} + +it("parses simple expression", () => { + const input = "1+1"; + +}) \ No newline at end of file diff --git a/src/expression/ListOfNumbersExpression.test.ts b/src/expression/ListOfNumbersExpression.test.ts index a415baf..546e297 100644 --- a/src/expression/ListOfNumbersExpression.test.ts +++ b/src/expression/ListOfNumbersExpression.test.ts @@ -1,7 +1,7 @@ -import NumericOperand from "./NumericOperand"; +import ScalarOperand from "./ScalarOperand"; import ListOfNumbersExpression from "./ListOfNumbersExpression"; it('calculates max bits length', () => { - var expr = new ListOfNumbersExpression("10 0xabef 0b01010", [NumericOperand.parse("10"), NumericOperand.parse("0xabef"), NumericOperand.parse("0b01010")]) + var expr = new ListOfNumbersExpression("10 0xabef 0b01010", [ScalarOperand.parse("10"), ScalarOperand.parse("0xabef"), ScalarOperand.parse("0b01010")]) expect(expr.maxBitsLength).toBe(16); }); diff --git a/src/expression/ListOfNumbersExpression.ts b/src/expression/ListOfNumbersExpression.ts index f28a086..775cf75 100644 --- a/src/expression/ListOfNumbersExpression.ts +++ b/src/expression/ListOfNumbersExpression.ts @@ -1,12 +1,12 @@ -import NumericOperand from "./NumericOperand"; +import ScalarOperand from "./ScalarOperand"; import { ExpressionInput, ExpressionInputItem } from "./expression-interfaces"; export default class ListOfNumbersExpression implements ExpressionInput { - numbers: NumericOperand[]; + numbers: ScalarOperand[]; expressionString: string; maxBitsLength: number; - constructor(expressionString: string, numbers: NumericOperand[]) { + constructor(expressionString: string, numbers: ScalarOperand[]) { this.expressionString = expressionString; this.numbers = numbers; this.maxBitsLength = numbers.map(n => n.lengthInBits).reduce((n , c) => n >= c ? n : c, 0); diff --git a/src/expression/NumericOperand.test.ts b/src/expression/NumericOperand.test.ts deleted file mode 100644 index 22b46fa..0000000 --- a/src/expression/NumericOperand.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import NumericOperand, { INT_MAX_VALUE } from './NumericOperand'; - -it('parsed from string', () => { - var op = NumericOperand.parse('123'); - expect(op.base).toBe('dec'); - expect(op.value).toBe(123); -}); - -it('can get other kind', () => { - var op = new NumericOperand(10, 'dec'); - expect(op.getOtherBase('hex')).toBe('dec'); - expect(op.getOtherBase('bin')).toBe('hex'); -}); - -it('negtive value binary string', () => { - expect(NumericOperand.toBaseString(-1, 'bin')).toBe('11111111111111111111111111111111'); -}); - -it('64 bit operand binary string', () => { - expect(NumericOperand.toBaseString(68719476735, 'bin')).toBe('111111111111111111111111111111111111'); -}); - -it('throws on negative 64 bit numbers', () => { - var bigN = -(INT_MAX_VALUE+1); - expect(() => new NumericOperand(bigN)).toThrowError("BitwiseCmd currently doesn't support 64 bit negative numbers such as " + bigN); -}) \ No newline at end of file diff --git a/src/expression/ScalarOperand.test.ts b/src/expression/ScalarOperand.test.ts new file mode 100644 index 0000000..154befe --- /dev/null +++ b/src/expression/ScalarOperand.test.ts @@ -0,0 +1,26 @@ +import ScalarOperand, { INT_MAX_VALUE } from './ScalarOperand'; + +it('parsed from string', () => { + var op = ScalarOperand.parse('123'); + expect(op.base).toBe('dec'); + expect(op.value).toBe(123); +}); + +it('can get other kind', () => { + var op = new ScalarOperand(10, 'dec'); + expect(op.getOtherBase('hex')).toBe('dec'); + expect(op.getOtherBase('bin')).toBe('hex'); +}); + +it('negtive value binary string', () => { + expect(ScalarOperand.toBaseString(-1, 'bin')).toBe('11111111111111111111111111111111'); +}); + +it('64 bit operand binary string', () => { + expect(ScalarOperand.toBaseString(68719476735, 'bin')).toBe('111111111111111111111111111111111111'); +}); + +it('throws on negative 64 bit numbers', () => { + var bigN = -(INT_MAX_VALUE+1); + expect(() => new ScalarOperand(bigN)).toThrowError("BitwiseCmd currently doesn't support 64 bit negative numbers such as " + bigN); +}) \ No newline at end of file diff --git a/src/expression/NumericOperand.ts b/src/expression/ScalarOperand.ts similarity index 79% rename from src/expression/NumericOperand.ts rename to src/expression/ScalarOperand.ts index 3faf28e..5761575 100644 --- a/src/expression/NumericOperand.ts +++ b/src/expression/ScalarOperand.ts @@ -7,8 +7,8 @@ const INT_MAX_VALUE = 2147483647; export {INT_MAX_VALUE}; -// Represents numeric value -export default class NumericOperand implements ExpressionInputItem { +// Represents scalar numeric value +export default class ScalarOperand implements ExpressionInputItem { id: number; value: number; base: NumberBase; @@ -19,10 +19,10 @@ export default class NumericOperand implements ExpressionInputItem { this.id = globalId++; this.value = value; this.base = base || "dec"; - this.lengthInBits = NumericOperand.getBitLength(this.value); + this.lengthInBits = ScalarOperand.getBitLength(this.value); this.isExpression = false; - if(value < 0 && !NumericOperand.is32Bit(value)) + if(value < 0 && !ScalarOperand.is32Bit(value)) throw new Error("BitwiseCmd currently doesn't support 64 bit negative numbers such as " + value); } @@ -44,7 +44,7 @@ export default class NumericOperand implements ExpressionInputItem { }; toString(base?: NumberBase) : string { - return NumericOperand.toBaseString(this.value, base || this.base); + return ScalarOperand.toBaseString(this.value, base || this.base); } toOtherKindString() : string { @@ -65,14 +65,14 @@ export default class NumericOperand implements ExpressionInputItem { setValue(value : number) { this.value = value; - this.lengthInBits = NumericOperand.getBitLength(value); + this.lengthInBits = ScalarOperand.getBitLength(value); } - evaluate() : NumericOperand { + evaluate() : ScalarOperand { return this; } - getUnderlyingOperand() : NumericOperand { + getUnderlyingOperand() : ScalarOperand { return this } @@ -89,12 +89,12 @@ export default class NumericOperand implements ExpressionInputItem { }; static create(value : number, base? : NumberBase) { - return new NumericOperand(value, base || "dec"); + return new ScalarOperand(value, base || "dec"); }; - static parse(input: string) : NumericOperand { + static parse(input: string) : ScalarOperand { - var parsed = NumericOperand.tryParse(input); + var parsed = ScalarOperand.tryParse(input); if(parsed == null) { throw new Error(input + " is not a valid number"); @@ -103,7 +103,7 @@ export default class NumericOperand implements ExpressionInputItem { return parsed; } - static tryParse(input: string) : NumericOperand | null { + static tryParse(input: string) : ScalarOperand | null { var parsed = numberParser.parse(input); @@ -111,7 +111,7 @@ export default class NumericOperand implements ExpressionInputItem { return null; } - return new NumericOperand(parsed.value, parsed.base); + return new ScalarOperand(parsed.value, parsed.base); } static toBaseString(value : number, base : NumberBase) : string { @@ -122,7 +122,7 @@ export default class NumericOperand implements ExpressionInputItem { case 'bin': // >>> 0 is used to get an actual bit representation of the negative numbers // https://stackoverflow.com/questions/5747123/strange-javascript-operator-expr-0 - const is32Bit = NumericOperand.is32Bit(value); + const is32Bit = ScalarOperand.is32Bit(value); return (is32Bit && value < 0 ? (value >>> 0) : value).toString(2); case 'dec': return value.toString(10); diff --git a/src/expression/components/BitwiseExpressionModel.ts b/src/expression/components/BitwiseExpressionModel.ts index ee1734f..31f0a6e 100644 --- a/src/expression/components/BitwiseExpressionModel.ts +++ b/src/expression/components/BitwiseExpressionModel.ts @@ -1,4 +1,4 @@ -import { NumericOperand, ListOfNumbersExpression, BitwiseOperationExpression, ExpressionOperand } from '../expression'; +import { ScalarOperand, ListOfNumbersExpression, BitwiseOperationExpression, ExpressionOperand } from '../expression'; import { ExpressionInputItem, ExpressionInput } from '../expression-interfaces'; type Config = { @@ -41,11 +41,11 @@ export default class BitwiseExpressionViewModel { i = 0, len = expr.expressionItems.length, ex, m = new BitwiseExpressionViewModel(config); - var prev : NumericOperand | null = null; + var prev : ScalarOperand | null = null; for (;i { return this.props.expressionItem.evaluate().toOtherKindString(); } - getLabelString (op: NumericOperand) : string { + getLabelString (op: ScalarOperand) : string { return op.toString(op.base == 'bin' ? 'dec' : op.base); } diff --git a/src/expression/expression-interfaces.ts b/src/expression/expression-interfaces.ts index 0a470d2..106dba0 100644 --- a/src/expression/expression-interfaces.ts +++ b/src/expression/expression-interfaces.ts @@ -1,4 +1,4 @@ -import { NumericOperand } from "./expression"; +import { ScalarOperand } from "./expression"; export interface ExpressionInput { @@ -8,8 +8,8 @@ export interface ExpressionInput export interface ExpressionInputItem { isExpression: boolean; - getUnderlyingOperand: () => NumericOperand; - evaluate(operand? : NumericOperand): NumericOperand; + getUnderlyingOperand: () => ScalarOperand; + evaluate(operand? : ScalarOperand): ScalarOperand; } export type NumberBase = 'dec' | 'hex' | 'bin'; diff --git a/src/expression/expression.test.ts b/src/expression/expression.test.ts index 206a58d..c88dc08 100644 --- a/src/expression/expression.test.ts +++ b/src/expression/expression.test.ts @@ -1,5 +1,5 @@ import { OperationCanceledException } from "typescript"; -import { parser, ListOfNumbersExpression, BitwiseOperationExpression, NumericOperand, ExpressionOperand } from "./expression"; +import { parser, ListOfNumbersExpression, BitwiseOperationExpression, ScalarOperand, ExpressionOperand } from "./expression"; describe("expression parser", () => { @@ -37,16 +37,16 @@ describe("expression parser", () => { const first = result.expressionItems[0]; const second = result.expressionItems[1]; - expect(first).toBeInstanceOf(NumericOperand); + expect(first).toBeInstanceOf(ScalarOperand); - expect((first as NumericOperand).value).toBe(1); + expect((first as ScalarOperand).value).toBe(1); expect(second).toBeInstanceOf(ExpressionOperand); var secondOp = second as ExpressionOperand; expect(secondOp.sign).toBe("^"); - expect(secondOp.operand).toBeInstanceOf(NumericOperand); - var childOp = secondOp.operand as NumericOperand; + expect(secondOp.operand).toBeInstanceOf(ScalarOperand); + var childOp = secondOp.operand as ScalarOperand; expect(childOp.value).toBe(2); }); diff --git a/src/expression/expression.ts b/src/expression/expression.ts index dc3ceaf..4897697 100644 --- a/src/expression/expression.ts +++ b/src/expression/expression.ts @@ -1,10 +1,10 @@ -import NumericOperand from './NumericOperand'; +import ScalarOperand from './ScalarOperand'; import ExpressionOperand from './ExpressionOperand' import ListOfNumbersExpression from './ListOfNumbersExpression'; import BitwiseOperationExpression from './BitwiseOperationExpression'; import { ExpressionInput, ExpressionInputItem, NumberBase } from './expression-interfaces'; -export { default as NumericOperand } from './NumericOperand'; +export { default as ScalarOperand } from './ScalarOperand'; export { default as ExpressionOperand } from './ExpressionOperand'; export { default as ListOfNumbersExpression } from './ListOfNumbersExpression'; export { default as BitwiseOperationExpression } from './BitwiseOperationExpression'; @@ -46,12 +46,12 @@ class ExpressionParser { return null; }; - parseOperand (input : string) : NumericOperand { - return NumericOperand.parse(input); + parseOperand (input : string) : ScalarOperand { + return ScalarOperand.parse(input); }; - createOperand (number : number, base : NumberBase) : NumericOperand { - return NumericOperand.create(number, base); + createOperand (number : number, base : NumberBase) : ScalarOperand { + return ScalarOperand.create(number, base); }; addFactory (factory: IExpressionParserFactory) { @@ -69,7 +69,7 @@ class ListOfNumbersExpressionFactory implements IExpressionParserFactory return input.split(' ') .filter(p => p.length > 0) - .map(p => NumericOperand.tryParse(p)) + .map(p => ScalarOperand.tryParse(p)) .filter(n => n == null) .length == 0; }; @@ -78,7 +78,7 @@ class ListOfNumbersExpressionFactory implements IExpressionParserFactory const numbers = input.split(' ') .filter(p => p.length > 0) - .map(m => NumericOperand.parse(m)); + .map(m => ScalarOperand.parse(m)); return new ListOfNumbersExpression(input, numbers); } @@ -116,16 +116,16 @@ class BitwiseOperationExpressionFactory implements IExpressionParserFactory { var parsed = null; if(num.indexOf('~') == 0) { - parsed = new ExpressionOperand(num, NumericOperand.parse(num.substring(1)), '~'); + parsed = new ExpressionOperand(num, ScalarOperand.parse(num.substring(1)), '~'); } else { - parsed = NumericOperand.parse(num); + parsed = ScalarOperand.parse(num); } if(sign == null) { return parsed as ExpressionOperand; } else { - return new ExpressionOperand(input, parsed as NumericOperand, sign); + return new ExpressionOperand(input, parsed as ScalarOperand, sign); } };