/*
* This file is part of TREB.
*
* TREB is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* TREB is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with TREB. If not, see .
*
* Copyright 2022-2026 trebco, llc.
* info@treb.app
*
*/
/**
* base type, for common data (atm only ID). id is intended to support
* a unique ID within the context of a single parse pass. (NOTE: in theory
* you could use the 'position' field... although that's not present in
* all cases?)
*/
export interface BaseUnit {
id: number;
}
export interface UnitLiteralNumber extends BaseUnit {
type: 'literal';
position: number;
value: number;
text?: string;
}
export interface UnitLiteralString extends BaseUnit {
type: 'literal';
position: number;
value: string;
text?: string;
}
export interface UnitLiteralBoolean extends BaseUnit {
type: 'literal';
position: number;
value: boolean;
text?: string;
}
/**
* expression unit representing a literal: string, number, boolean.
* FIXME: would be nice if we had subtypes so we could specify
* /
export interface UnitLiteral extends BaseUnit {
type: 'literal';
position: number;
value: string | boolean | number;
text?: string;
}
*/
export type UnitLiteral = UnitLiteralNumber|UnitLiteralBoolean|UnitLiteralString;
/**
* testing: complex
*/
export interface UnitComplex extends BaseUnit {
type: 'complex';
position: number;
real: number;
imaginary: number;
text?: string;
/**
* this flag takes the place of the old "imaginary" unit type;
* it's an indication that this unit has been composited, so don't
* do it again. not sure this is actually needed by the parser... is it?
*/
composited?: boolean;
}
/* *
* testing: complex
* this represents just the imaginary part. it's for internal use and should
* never be returned as a value.
* /
export interface UnitImaginary extends BaseUnit {
type: 'imaginary';
position: number;
value: number;
text?: string;
}
*/
/**
* expression unit representing an array of primitive values. array
* can contain mixed values, and holes. array cannot contain arrays,
* or any other complex type (including complex, apparently. we should
* remedy that).
*/
export interface UnitArray extends BaseUnit {
type: 'array';
position: number;
values: Array < Array >;
}
/**
* expression unit representing a missing value, intended for missing
* arguments in function calls.
*/
export interface UnitMissing extends BaseUnit {
type: 'missing';
}
/**
* expression unit representing an opaque name or identifier.
*/
export interface UnitIdentifier extends BaseUnit {
type: 'identifier';
position: number;
name: string;
}
/**
* "structured reference" for offset into named table
*/
export interface UnitStructuredReference extends BaseUnit {
type: 'structured-reference';
label: string;
position: number;
table: string;
/**
* row refers to "this row". "all" means all values, including the
* header. "column" means all values except the header.
*/
scope: 'row'|'all'|'column';
column: string;
}
/**
* expression unit representing a group of units; like parentheses in an
* expression. intended to prevent precendence reordering of operations.
*/
export interface UnitGroup extends BaseUnit {
type: 'group';
elements: ExpressionUnit[];
// this flag indicates whether the group was expressly inserted by
// the user (true) or generated as part of parsing (false). that
// information is used when unparsing (reconstructing formula).
explicit: boolean;
}
/**
* expression unit representing a function call: has call and arguments.
*/
export interface UnitCall extends BaseUnit {
type: 'call';
name: string;
position: number;
args: ExpressionUnit[];
/** testing */
end?: number;
}
/**
* new call type: implicit. we might merge these.
*/
export interface UnitImplicitCall extends BaseUnit {
type: 'implicit-call';
position: number;
args: ExpressionUnit[];
call: ExpressionUnit;
}
/**
* this isn't an output type (unless parsing fails), but it's useful
* to be able to pass these around with the same semantics.
*/
export interface UnitOperator extends BaseUnit {
type: 'operator';
position: number;
operator: string;
}
/**
* also not an output type
*/
export interface UnitGroupSeparator extends BaseUnit {
type: 'group-separator';
position: number;
}
/**
* expression unit representing a binary operation. operations may be
* re-ordered based on precendence.
*/
export interface UnitBinary extends BaseUnit {
type: 'binary';
left: ExpressionUnit;
operator: string;
right: ExpressionUnit;
position: number; // this is the _operator_ position, since that will be the error
}
/**
* expression unit representing a unary operation.
*/
export interface UnitUnary extends BaseUnit {
type: 'unary';
operator: string;
operand: ExpressionUnit;
position: number;
}
/**
* expression unit representing a spreadsheet address
*/
export interface UnitAddress extends BaseUnit {
type: 'address';
sheet?: string;
sheet_id?: number;
label: string;
row: number;
column: number;
absolute_row?: boolean;
absolute_column?: boolean;
/** spill flag (address ends with #) */
spill?: boolean;
/**
* this means the row is a relative offset from the current row. this
* happens if you use R1C1 syntax with square brackets.
*/
offset_row?: boolean;
/**
* this means the column is a relative offset from the current column.
* this happens if you use R1C1 syntax with square brackets.
*/
offset_column?: boolean;
/** the formula was originally in R1C1. we probably want to translate it. */
r1c1?: boolean;
position: number;
}
/**
* expression unit representing a spreadsheet range
*/
export interface UnitRange extends BaseUnit {
type: 'range';
label: string;
start: UnitAddress;
end: UnitAddress;
position: number;
}
export interface UnitDimensionedQuantity extends BaseUnit {
type: 'dimensioned';
expression: BaseExpressionUnit; //