diff --git a/src/lexer.spec.ts b/src/lexer.spec.ts index 73452e3..03e58f6 100644 --- a/src/lexer.spec.ts +++ b/src/lexer.spec.ts @@ -168,15 +168,18 @@ describe('Lexer', () => { next({ type: 'comma' }); next({ type: 'float', value: '.1' }); next({ type: 'comma' }); - next({ type: 'float', value: '-.1' }); + next({ type: 'op_minus' }); + next({ type: 'float', value: '.1' }); next({ type: 'comma' }); - next({ type: 'float', value: '-0.1' }); + next({ type: 'op_minus' }); + next({ type: 'float', value: '0.1' }); next({ type: 'comma' }); next({ type: 'float', value: '0.1' }); next({ type: 'comma' }); next({ type: 'float', value: '10.' }); next({ type: 'comma' }); - next({ type: 'float', value: '-10.' }); + next({ type: 'op_minus' }); + next({ type: 'float', value: '10.' }); }) it('tokenizes ->', () => { diff --git a/src/lexer.ts b/src/lexer.ts index eafe785..360cbfc 100644 --- a/src/lexer.ts +++ b/src/lexer.ts @@ -51,8 +51,6 @@ export const lexer = compile({ star: '*', comma: ',', space: { match: /[\s\t\n\v\f\r]+/, lineBreaks: true, }, - int: /\-?\d+(?![\.\d])/, - float: /\-?(?:(?:\d*\.\d+)|(?:\d+\.\d*))/, // word: /[a-zA-Z][A-Za-z0-9_\-]*/, lparen: '(', rparen: ')', @@ -71,6 +69,8 @@ export const lexer = compile({ op_membertext: '->>', op_member: '->', op_minus: '-', + int: /\-?\d+(?![\.\d])/, + float: /\-?(?:(?:\d*\.\d+)|(?:\d+\.\d*))/, op_div: /\//, op_not_ilike: /\!~~\*/, // !~~* =ILIKE op_not_like: /\!~~/, // !~~ =LIKE diff --git a/src/syntax/expr.ne b/src/syntax/expr.ne index aff8c67..a7ce40f 100644 --- a/src/syntax/expr.ne +++ b/src/syntax/expr.ne @@ -107,7 +107,13 @@ expr_array_index | expr_member {% unwrap %} expr_member - -> (expr_member | expr_paren) ops_member (string | int) {% x => track(x, { + -> (expr_member | expr_paren) ops_member %op_minus int {% x => track(x, { + type: 'member', + operand: unwrap(x[0]), + op: x[1], + member: -unwrap(x[3]) + }) %} + | (expr_member | expr_paren) ops_member (string | int) {% x => track(x, { type: 'member', operand: unwrap(x[0]), op: x[1], diff --git a/src/syntax/expr.spec.ts b/src/syntax/expr.spec.ts index 5cb2efd..b1e4107 100644 --- a/src/syntax/expr.spec.ts +++ b/src/syntax/expr.spec.ts @@ -46,18 +46,37 @@ describe('Expressions', () => { }); checkTreeExpr(['-0.5', '-.5'], { - type: 'numeric', - value: -0.5, + type: 'unary', + op: '-', + operand: { + type: 'numeric', + value: 0.5, + } }); checkTreeExpr(['-42.', '-42.0'], { - type: 'numeric', - value: -42, + type: 'unary', + op: '-', + operand: { + type: 'numeric', + value: 42, + } }); checkInvalidExpr('42. 51'); - checkInvalidExpr('42.-51'); + checkTreeExpr(['42.-51'], { + type: 'binary', + op: '-', + left: { + type: 'numeric', + value: 42, + }, + right: { + type: 'integer', + value: 51, + }, + }); checkTreeExprLoc(['null'], { _location: { start: 0, end: 4 }, @@ -400,6 +419,19 @@ line`, } }); + checkTreeExpr(['42-51', '42 - 51'], { + type: 'binary', + op: '-', + left: { + type: 'integer', + value: 42, + }, + right: { + type: 'integer', + value: 51, + } + }); + checkTreeExpr(['42*51', '42 * 51'], { type: 'binary', op: '*', diff --git a/src/syntax/simple-statements.ne b/src/syntax/simple-statements.ne index 7677bbf..bc989be 100644 --- a/src/syntax/simple-statements.ne +++ b/src/syntax/simple-statements.ne @@ -40,6 +40,7 @@ simplestatements_set_timezone -> kw_time kw_zone simplestatements_set_timezone_v simplestatements_set_timezone_val -> (string | int) {% x => track(x, { type: 'value', value: unwrap(x[0]) }) %} + | %op_minus int {% x => track(x, { type: 'value', value: -unwrap(x[1]) }) %} | kw_local {% x => track(x, { type: 'local'}) %} | %kw_default {% x => track(x, { type: 'default'}) %} | kw_interval string kw_hour %kw_to kw_minute {% x => track(x, { type: 'interval', value: unbox(x[1]) }) %}