@lcap/nasl-parser
Version:
Take Nasl text to Nasl AST with the help of generalized parsing.
388 lines • 17 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.toNaslPrefix = exports.toNaslTyParam = exports.toNaslLogicParam = exports.toNaslLamParam = exports.toNaslLambda = exports.toNaslSubLogic = exports.toNaslDefaultValue = exports.toNaslValArgList = exports.toNaslValArg = exports.toNaslCallLogic = exports.toNaslSQLFilterSuffix = exports.toNaslMemberAccessSuffix = exports.toNaslArrayAccessSuffix = exports.toNaslCallSuffix = exports.BuildBinary = exports.toNaslBinaryExpr = exports.toNaslCallQueryComponent = exports.toNaslAnonymousFunc = exports.toNaslEmptyBrackets = exports.toNaslEnumIntRef = exports.toNaslMapLit = exports.toNaslArrayLit = exports.toNaslUnparsed = exports.toNaslStringInterpolation = exports.toNaslStringLit = exports.toNaslBooleanLit = exports.toNaslNullLit = exports.toNaslDecimalLit = exports.toNaslIntegerLit = exports.toNaslIdentifier = exports.toNaslPostfix = void 0;
exports.dispatchToNaslExpr = dispatchToNaslExpr;
const to_nasl_type_1 = require("./to-nasl-type");
// toNaslPat, toNaslStatement,
const to_nasl_statement_1 = require("./to-nasl-statement");
const common_util_1 = require("./common-util");
const nasl = __importStar(require("./decorated-nasl-ast"));
const console_1 = require("console");
const asserts_1 = require("@lcap/nasl-concepts/asserts");
// import { toNaslCallQueryComponentImpl } from './to-nasl-call-query';
let toNaslCallQueryComponentImpl = undefined;
const binaryOpToName = new Map([
['+', 'Add'],
['-', 'Sub'],
['*', 'Mul'],
['/', 'Div'],
['%', 'Mod'],
// ['^', 'Pow'],
['&&', 'And'],
['||', 'Or'],
['==', 'Eq'],
['!=', 'Ne'],
['>', 'Gt'],
['<', 'Lt'],
['>=', 'Ge'],
['<=', 'Le'],
['in', 'In'],
['not in', 'NotIn'],
['is', 'Is'],
['is not', 'IsNot'],
]);
const toNaslPostfix = ([expr, sfx]) => {
// please refactor the four if to switch
switch (sfx.cst.__type) {
case 'CallSuffix':
return (0, exports.toNaslCallLogic)(expr, sfx);
case 'ArrayAccessSuffix':
return toNaslArrayAccess(expr, sfx);
case 'MemberAccessSuffix':
return toNaslMemberAccess(expr, sfx);
case 'SQLFilterSuffix':
return toNaslSQLFilter(expr);
default:
throw new console_1.error('panic: should not reach here in postfixToNasl1');
}
};
exports.toNaslPostfix = toNaslPostfix;
function dispatchToNaslExpr(e) {
// if (isUnaryExpr(e)) {
// let expr : nasl.LogicItem;
// if (isPostfixable(e.expr)) {
// if (!isEmpty(e.suffix)) {
// let res = postfixToNasl1(e.expr, e.suffix.pop())
// e.suffix.forEach(sfx => {
// // @ts-ignore
// res = postfixToNasl2(res, sfx)
// })
// expr = res;
// } else {
// expr = toNaslExpr(e.expr);
// }
// e.prefix.forEach(pfx => {
// expr = new nasl.UnaryExpression({
// operator: '!',
// argument: expr
// })
// });
// return expr;
// } else {
// return toNaslExpr(e.expr);
// }
// }
// if (isBinaryExpression(e)) {
// return toNaslBinaryExpr(e);
// }
return new nasl.Identifier();
throw new console_1.error('panic: unimplemented in dispatchToNaslExpr.');
}
const toNaslIdentifier = ([e]) => {
const ni = new nasl.Identifier({
name: e.name
});
ni.qName = e; // 非本身的属性,不能直接在初始化时构造
return (0, common_util_1.PackNaslAndCst)(ni, (0, common_util_1.TYPE)('TermRef', e));
};
exports.toNaslIdentifier = toNaslIdentifier;
const toNaslIntegerLit = (e) => {
const nil = new nasl.NumericLiteral({
value: String(e),
typeAnnotation: (0, common_util_1.getNasl)((0, to_nasl_type_1.namedTypeToNaslTypeAnno)((0, common_util_1.createQIdentifier)('Integer'), [])),
});
return (0, common_util_1.PackNaslAndCst)(nil, e);
};
exports.toNaslIntegerLit = toNaslIntegerLit;
const toNaslDecimalLit = (e) => {
const ndl = new nasl.NumericLiteral({
value: String(e),
typeAnnotation: (0, common_util_1.getNasl)((0, to_nasl_type_1.namedTypeToNaslTypeAnno)((0, common_util_1.createQIdentifier)('Decimal'), [])),
});
return (0, common_util_1.PackNaslAndCst)(ndl, e);
};
exports.toNaslDecimalLit = toNaslDecimalLit;
const toNaslNullLit = ([e]) => {
return (0, common_util_1.PackNaslAndCst)(new nasl.NullLiteral(), e);
};
exports.toNaslNullLit = toNaslNullLit;
// 这里就是两层[[.]]
const toNaslBooleanLit = ([[e]]) => {
const nb = new nasl.BooleanLiteral({
value: String(e.value)
});
return (0, common_util_1.PackNaslAndCst)(nb, e.value);
};
exports.toNaslBooleanLit = toNaslBooleanLit;
// fromStringLit
const toNaslStringLit = ([e]) => {
const ns = new nasl.StringLiteral({ value: e[0].value });
return (0, common_util_1.PackNaslAndCst)(ns, e[0].value);
};
exports.toNaslStringLit = toNaslStringLit;
const toNaslStringInterpolation = (d) => {
let res = { __type: 'StringInterpolation', parts: [] };
let buf = '';
d.forEach((elem, idx) => {
if (elem.__type !== 'Expression') {
buf += elem.str;
}
else {
if (buf.length > 0) {
res.parts.push((0, common_util_1.PackNaslAndCst)(new nasl.StringLiteral({ value: buf }), { __type: 'String', str: buf }));
buf = '';
}
res.parts.push(elem.expr);
}
});
if (buf.length > 0) {
res.parts.push((0, common_util_1.PackNaslAndCst)(new nasl.StringLiteral({ value: buf }), { __type: 'String', str: buf }));
}
const nInterpolation = new nasl.StringInterpolation({ expressions: res.parts.map(common_util_1.getNasl) });
return (0, common_util_1.PackNaslAndCst)(nInterpolation, (0, common_util_1.TYPE)('StringInterpolation', res.parts.map(common_util_1.getCst)));
};
exports.toNaslStringInterpolation = toNaslStringInterpolation;
const toNaslUnparsed = (str) => (0, common_util_1.PackNaslAndCst)(new nasl.Unparsed({ "code": str }), { __type: 'JSString', str });
exports.toNaslUnparsed = toNaslUnparsed;
const toNaslArrayLit = (exprs, ty) => {
const nL = new nasl.NewList({ items: exprs?.nasl });
if (ty) {
nL.typeAnnotation = ty.nasl;
nL.typeAnnotation.inferred = false;
}
return (0, common_util_1.PackNaslAndCst)(nL, (0, common_util_1.TYPE)('ArrayLit', { exprs: exprs?.cst, ty: ty?.cst ?? undefined }));
};
exports.toNaslArrayLit = toNaslArrayLit;
const toNaslMapLit = ([entries]) => {
const nm = new nasl.NewMap({
keys: entries.nasl.map(entry => entry.key), // 我™还是得给打散成 pair……
values: entries.nasl.map(entry => entry.val)
});
return (0, common_util_1.PackNaslAndCst)(nm, (0, common_util_1.TYPE)('MapLit', entries.cst));
};
exports.toNaslMapLit = toNaslMapLit;
// isEnumIntRef. please generate code without
const toNaslEnumIntRef = ([namespaceArr, _digitName]) => {
let enumTypeName = namespaceArr[0];
// 暂时先支持两种写法吧
if (namespaceArr.length > 2 && namespaceArr[0] === 'app' && namespaceArr[1] === 'enums') {
enumTypeName = namespaceArr[2];
}
const value = _digitName.nasl.value;
const enumIntRef = new nasl.CstIntEnumRef(enumTypeName, value);
return (0, common_util_1.PackNaslAndCst)(enumIntRef, (0, common_util_1.TYPE)('EnumIntRef', { namespace: namespaceArr, name: _digitName.cst }));
};
exports.toNaslEnumIntRef = toNaslEnumIntRef;
const toNaslEmptyBrackets = _ => (0, common_util_1.PackNaslAndCst)(new nasl.EmptyBrackets(), (0, common_util_1.TYPE)('EmptyBrackets', { expr: '[]' }));
exports.toNaslEmptyBrackets = toNaslEmptyBrackets;
// CompoundLambda or AnonymousStructure
// export const toNaslEmptyBraces = _ => PackNaslAndCst(new nasl.EmptyBraces(), TYPE('EmptyBraces', { expr: '{}' }))
const toNaslAnonymousFunc = (e) => {
const nl = new nasl.AnonymousFunction({
params: e.params.map(to_nasl_statement_1.toNaslValueParam),
// @ts-ignore
body: dispatchToNaslExpr(e.nasl.expr), // last expression
});
return (0, common_util_1.PackNaslAndCst)(nl, (0, common_util_1.TYPE)('AnonymousFunction', e));
};
exports.toNaslAnonymousFunc = toNaslAnonymousFunc;
const toNaslCallQueryComponent = (e) => (0, common_util_1.PackNaslAndCst)(toNaslCallQueryComponentImpl(e.nasl), (0, common_util_1.TYPE)('CallQueryComponent', e.cst));
exports.toNaslCallQueryComponent = toNaslCallQueryComponent;
const toNaslBinaryExpr = (left, op, right) => {
const nb = new nasl.BinaryExpression();
// @ts-ignore Nasl 未定义 Pow 幂运算 运算符 ^
nb.operator = op.toLowerCase(); // 牛的,必须用 startwith 而非 startWith
nb.left = left.nasl;
nb.right = right.nasl;
return (0, common_util_1.PackNaslAndCst)(nb, (0, common_util_1.TYPE)(binaryOpToName.get(op), { left: left.cst, op, right: right.cst }));
};
exports.toNaslBinaryExpr = toNaslBinaryExpr;
const BuildBinary = ([left, op, _1, right]) => {
if (Array.isArray(op)) {
op = op[0].value;
}
else {
op = op.value;
}
return (0, exports.toNaslBinaryExpr)(left, op, right);
};
exports.BuildBinary = BuildBinary;
const toNaslCallSuffix = ([tyArgs, valArgs]) => {
const res = (0, common_util_1.AutoPackNaslAndCst)({ tyArgs, valArgs });
(0, common_util_1.TYPE)('CallSuffix', res.cst);
return res;
};
exports.toNaslCallSuffix = toNaslCallSuffix;
const toNaslArrayAccessSuffix = ([expr]) => (0, common_util_1.PackNaslAndCst)(expr.nasl, (0, common_util_1.TYPE)('ArrayAccessSuffix', { expr: expr.cst }));
exports.toNaslArrayAccessSuffix = toNaslArrayAccessSuffix;
const toNaslMemberAccessSuffix = (rawIdent) => (0, common_util_1.PackNaslAndCst)((0, exports.toNaslIdentifier)([(0, common_util_1.createQIdentifier)(rawIdent)]).nasl, (0, common_util_1.TYPE)('MemberAccessSuffix', { rawIdent }));
exports.toNaslMemberAccessSuffix = toNaslMemberAccessSuffix;
const toNaslSQLFilterSuffix = () => (0, common_util_1.PackNaslAndCst)(null, (0, common_util_1.TYPE)('SQLFilterSuffix', {}));
exports.toNaslSQLFilterSuffix = toNaslSQLFilterSuffix;
// 第一轮 toAST 先简单处理,后续 refine-nasl-ast 会细分不同的 call
const toNaslCallLogic = (callee, sfx) => {
if ((0, asserts_1.isAnonymousFunction)(callee.nasl)) {
throw new Error('Nasl AST 暂时无法承载, AnonymousFunction cannot be called');
}
// console.log('CALLER NASL NAMESPACE', caller.nasl);
const callerNsp = callee.nasl.qName.namespace.join(common_util_1.NAMESPACE_SEP_AST);
const nc = new nasl.CallLogic({
calleeName: callee.nasl.name,
calleeNamespace: callerNsp ?? common_util_1.APP_LOGICS_AST,
arguments: sfx.nasl.valArgs,
typeArguments: sfx.nasl.tyArgs,
});
if ((0, asserts_1.isIdentifier)(callee.nasl)) {
nc.qName = callee.nasl.qName;
}
else {
// lambda literal { -> }(x)
// Nasl AST 暂时无法承载
// nc.simpleLambda = caller;
}
// if (isEmpty(nc.typeArguments)) {
// nc.typeArguments = null;
// }
nc.handleError = false;
return (0, common_util_1.PackNaslAndCst)(nc, (0, common_util_1.TYPE)('CallLogic', { caller: callee.cst, sfx: sfx.cst }));
};
exports.toNaslCallLogic = toNaslCallLogic;
const toNaslArrayAccess = (expr, sfx) => {
const valArg = (0, exports.toNaslValArg)(sfx);
const ncf = new nasl.CallFunction({
calleeName: 'Get',
arguments: [
new nasl.Argument({ expression: expr.nasl }),
valArg.nasl
]
});
return (0, common_util_1.PackNaslAndCst)(ncf, (0, common_util_1.TYPE)('ArrayAccess', { expr: expr.cst, suffix: valArg.cst }));
};
const toNaslMemberAccess = (expr, sfx) => {
const nme = new nasl.MemberExpression({
object: expr.nasl,
property: sfx.nasl
});
return (0, common_util_1.PackNaslAndCst)(nme, (0, common_util_1.TYPE)('MemberAccess', { obj: expr.cst, prop: sfx.cst }));
};
const toNaslSQLFilter = (expr) => {
const nue = new nasl.UnaryExpression({
operator: 'isNull', // 这里又有大写啦
argument: expr.nasl
});
return (0, common_util_1.PackNaslAndCst)(nue, (0, common_util_1.TYPE)('SQLFilter', { expr: expr.cst }));
};
const toNaslValArg = (expr, name) => {
const na = new nasl.Argument({
expression: expr.nasl
});
if (name) {
na.keyword = name;
}
// console.log('toNaslValArg', na.keyword);
return (0, common_util_1.PackNaslAndCst)(na, (0, common_util_1.TYPE)('ValueArg', { expr: expr.cst, name }));
};
exports.toNaslValArg = toNaslValArg;
const toNaslValArgList = (args, lam) => {
if (!args?.nasl) {
args = {};
args.nasl = [];
args.cst = [];
}
if (lam) {
return (0, common_util_1.PackNaslAndCst)(args.nasl.concat(lam.nasl), args.cst.concat(lam.cst));
}
else {
return (0, common_util_1.PackNaslAndCst)(args.nasl, args.cst);
}
};
exports.toNaslValArgList = toNaslValArgList;
// export const toNaslTyArg = ([arg]) =>
// PackNaslAndCst(arg.nasl, TYPE('TypeArg', arg.cst))
// export const toNaslTyArgList = ([args]) => PackNaslAndCst(args.nasl, args.cst)
exports.toNaslDefaultValue = undefined;
const toNaslSubLogic = (body, params) => {
const nl = new nasl.Logic({
name: null,
params: params?.nasl,
returns: [], // TODO
body: [new nasl.Start(), body.nasl.stmts, new nasl.End()],
variables: body.nasl.vars
});
return (0, common_util_1.PackNaslAndCst)(nl, (0, common_util_1.TYPE)('SubLogic', { params: params?.cst, body: body.cst }));
};
exports.toNaslSubLogic = toNaslSubLogic;
const toNaslLambda = (expr, params) => {
const nl = new nasl.AnonymousFunction({
params: params?.nasl,
body: expr.nasl
});
// const nb = new nasl.BinaryExpression();
// // @ts-ignore Nasl 未定义 Pow 幂运算 运算符 ^
// nb.operator = op.toLowerCase(); // 牛的,必须用 startwith 而非 startWith
// nb.left = left.nasl;
// nb.right = right.nasl;
// return PackNaslAndCst(nb, TYPE(binaryOpToName.get(op), { left: left.cst, op, right: right.cst }));
return (0, common_util_1.PackNaslAndCst)(nl, (0, common_util_1.TYPE)('Lambda', { expr: expr.cst, params: params?.cst }));
};
exports.toNaslLambda = toNaslLambda;
const toNaslLamParam = (name, ty) => {
const np = new nasl.Param({
name: name,
typeAnnotation: ty?.nasl ?? null, // 难伺候
// defaultValue: null
});
return (0, common_util_1.PackNaslAndCst)(np, (0, common_util_1.TYPE)('Param', { name, ty: ty?.cst }));
};
exports.toNaslLamParam = toNaslLamParam;
const toNaslLogicParam = ([varInit]) => {
const nv = varInit.nasl;
const np = new nasl.Param({
name: nv.name,
typeAnnotation: nv.typeAnnotation,
defaultValue: nv.defaultValue,
defaultExpression: nv.defaultValue?.expression
});
// if (e.anns) {
// // @ts-ignore
// np.annotations = e.anns;
// }
return (0, common_util_1.PackNaslAndCst)(np, (0, common_util_1.TYPE)('Param', varInit.cst));
};
exports.toNaslLogicParam = toNaslLogicParam;
// transform type variables introduced in <·> to type parameters
// not to be confused with types used <·> at the use site
const toNaslTyParam = (ty) => (0, common_util_1.PackNaslAndCst)(new nasl.TypeParam({ name: ty }), (0, common_util_1.TYPE)("TypeParam", { ty }));
exports.toNaslTyParam = toNaslTyParam;
const toNaslPrefix = (expr) => {
const e = new nasl.UnaryExpression({
operator: '!',
argument: expr.nasl
});
return (0, common_util_1.PackNaslAndCst)(e, (0, common_util_1.TYPE)('Prefix', expr.cst));
};
exports.toNaslPrefix = toNaslPrefix;
//# sourceMappingURL=to-nasl-expression.js.map