@eagleoutice/flowr
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
113 lines • 5.04 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.tryNormalizeBinary = tryNormalizeBinary;
const normalizer_data_1 = require("../../normalizer-data");
const parser_1 = require("../../../json/parser");
const normalize_meta_1 = require("../../normalize-meta");
const assert_1 = require("../../../../../../../util/assert");
const log_1 = require("../../../../../../../util/log");
const strings_1 = require("../../../../../../../util/text/strings");
const type_1 = require("../../../../model/type");
const operators_1 = require("../../../../model/operators");
const normalize_single_node_1 = require("../structure/normalize-single-node");
/**
* Parsing binary operations includes the pipe, even though the produced PIPE construct is not a binary operation,
* to ensure it is handled separately from the others (especially in the combination of a pipe bind)
*/
function tryNormalizeBinary(data, [lhs, operator, rhs]) {
(0, log_1.expensiveTrace)(parser_1.parseLog, () => `binary op for ${lhs.name} [${operator.name}] ${rhs.name}`);
if (operator.name === type_1.RawRType.Special || operators_1.OperatorsInRAst.has(operator.name) || operator.name === type_1.RawRType.Pipe) {
return parseBinaryOp(data, lhs, operator, rhs);
}
else {
return undefined;
}
}
function parseBinaryOp(data, lhs, operator, rhs) {
(0, normalize_meta_1.ensureChildrenAreLhsAndRhsOrdered)(lhs.content, rhs.content);
const parsedLhs = (0, normalize_single_node_1.normalizeSingleNode)(data, lhs);
const parsedRhs = (0, normalize_single_node_1.normalizeSingleNode)(data, rhs);
if (parsedLhs.type === type_1.RType.Delimiter || parsedRhs.type === type_1.RType.Delimiter) {
throw new normalizer_data_1.ParseError(`unexpected under-sided binary op, received ${JSON.stringify([parsedLhs, parsedRhs])} for ${JSON.stringify([lhs, operator, rhs])}`);
}
const operationName = (0, normalize_meta_1.retrieveOpName)(operator);
const { location, content } = (0, normalize_meta_1.retrieveMetaStructure)(operator.content);
if ((0, strings_1.startAndEndsWith)(operationName, '%')) {
const lhsLoc = parsedLhs.type === type_1.RType.ExpressionList ? parsedLhs.grouping?.[0].location : parsedLhs.location;
const rhsLoc = parsedRhs.type === type_1.RType.ExpressionList ? parsedRhs.grouping?.[0].location : parsedRhs.location;
(0, assert_1.guard)(lhsLoc !== undefined && rhsLoc !== undefined, () => `special op lhs and rhs must have a locations, but ${JSON.stringify(parsedLhs)} || ${JSON.stringify(lhsLoc)} and ${JSON.stringify(parsedRhs)} || || ${JSON.stringify(rhsLoc)})`);
// parse as infix function call!
return {
type: type_1.RType.FunctionCall,
named: true,
infixSpecial: true,
lexeme: data.currentLexeme ?? content,
location,
functionName: {
type: type_1.RType.Symbol,
location,
lexeme: content,
content,
info: {}
},
arguments: [
{
type: type_1.RType.Argument,
location: lhsLoc,
value: parsedLhs,
name: undefined,
lexeme: parsedLhs.lexeme ?? '',
info: {}
},
{
type: type_1.RType.Argument,
location: rhsLoc,
value: parsedRhs,
name: undefined,
lexeme: parsedRhs.lexeme ?? '',
info: {}
}
],
info: {}
};
}
else if (operator.name === type_1.RawRType.Pipe) {
(0, assert_1.guard)(parsedLhs.location !== undefined, () => `pipe lhs must have a location, but ${JSON.stringify(parsedLhs)})`);
(0, assert_1.guard)(parsedLhs.lexeme !== undefined, () => `pipe lhs must have a full lexeme, but ${JSON.stringify(parsedLhs)})`);
return {
type: type_1.RType.Pipe,
location,
lhs: {
type: type_1.RType.Argument,
location: parsedLhs.location,
value: parsedLhs,
name: undefined,
lexeme: parsedLhs.lexeme,
info: {}
},
rhs: parsedRhs,
lexeme: content,
info: {
fullRange: data.currentRange,
adToks: [],
fullLexeme: data.currentLexeme
}
};
}
else {
return {
type: type_1.RType.BinaryOp,
location,
lhs: parsedLhs,
rhs: parsedRhs,
operator: operationName,
lexeme: content,
info: {
fullRange: data.currentRange,
adToks: [],
fullLexeme: data.currentLexeme
}
};
}
}
//# sourceMappingURL=normalize-binary.js.map