UNPKG

@lcap/nasl-parser

Version:

Take Nasl text to Nasl AST with the help of generalized parsing.

185 lines (161 loc) 6.81 kB
import * as nasl from '@lcap/nasl'; import { dispatchToNaslExpr, toNaslDefaultValue } from './to-nasl-expression'; import { isEnd } from '@lcap/nasl-concepts/asserts'; import { CstNamespace, UsingNamespace, CstAnnotationArg, SupportedDefinition, CstAnnotation, CstIdentifier } from './decorated-nasl-ast'; import { AstCstPack, PackNaslAndCst, PackNaslAndCstSeq, TYPE, getCst, getNasl, isEmpty, last, projectIdentifier, projectIdentifierAST, wellDefined } from './common-util'; import { createNaslPrimitiveType } from './to-nasl-type'; export const toNaslVarsAndStmts = ([vars, stmts]) => { return { nasl: {vars: vars.nasl, stmts: stmts.nasl } , cst: {vars: vars.cst, stmts: stmts.cst} } } export const toNaslLogicSig = (name, tyVars, params, _ret, anns) => { tyVars = tyVars ?? [] const ret = _ret ? new nasl.Return({ name: _ret.nasl.name, typeAnnotation: _ret.nasl.typeAnnotation, defaultValue: _ret.nasl.defaultValue }) : null; return PackNaslAndCst({ name , tyVars: tyVars.nasl , params: params.nasl , ret , anns: anns?.map(getNasl)} , TYPE('LogicSig', { name , tyVars: tyVars.cst , params: params.cst , ret: _ret?.cst , anns: anns?.map(getCst)}) ); } export const toNaslLogic = ([_sig, _body]) => { const sig = _sig.nasl; const body = _body.nasl; const nl = new nasl.Logic(); nl.name = sig.name; nl.typeParams = sig.tyVars; // null 与 IDE 兼容,绝妙!=> 3.11 又不兼容了 又要改成 undefined nl.params = sig.params ?? []; // [] 与 IDE 兼容,绝妙! nl.returns = sig.ret ? [sig.ret] : []; nl.annotations = sig.annotations; nl.body = [new nasl.Start({label: '开始'}), ...body.stmts]; // 不写 label 还真就不加了,🐂 if (!isEnd(last(nl.body))) { nl.body.push(new nasl.End({label: '结束'})); // 不写 label 还真就不加了,🐂 } nl.variables = body.vars; // 无法自由创建局部变量,都在逻辑开头处 nl.annotations = sig.anns; return PackNaslAndCst(nl, TYPE('Logic', { sig: _sig.cst, body: _body.cst })); } // transform type variables introduced in <·> to type parameters // not to be confused with types used <·> at the use site const toNaslTypeParam = (n) => new nasl.TypeParam({ name: n }); export const toNaslStructure = (tyIntro, pCtor, supTy, body, anns) => { const ns = new nasl.Structure({ name: tyIntro.tyCon, // description: , // origin: 'CallQueryComponent'; ??? typeParams: tyIntro.tyVars.map(toNaslTypeParam), properties: pCtor?.nasl ? pCtor.nasl.concat(body?.nasl.props) : body?.nasl.props, }); ns.annotations = anns?.map(getNasl); const cst = TYPE("Struct", {anns: anns?.map(getCst), ty: tyIntro, props: body.cst.props, logics: body.cst.logics, ctors: body.cst.ctors }) return PackNaslAndCst(ns, cst); } export const toNaslStructureProperty = (vd, anns?) => { const nsp = new nasl.StructureProperty({ // sp.nasl : nasl.Variable name: vd.nasl.name, typeAnnotation: vd.nasl.typeAnnotation, defaultValue: vd.nasl.defaultValue, // label: TODO // jsonName: TODO // description: TODO // required 看起来废弃了 }); nsp.annotations = anns?.map(getNasl); return PackNaslAndCst(nsp, TYPE("StructProperty", { prop: vd.cst, anns: anns?.map(getCst) })); } export const pCtorToProperty = ([vds]) => { if (isEmpty(vds)) { return PackNaslAndCst([], []) } return PackNaslAndCstSeq(vds?.nasl?.map(toNaslStructureProperty)); } export function toNaslEnum(name, defs, anns?) { const body = PackNaslAndCstSeq(defs); const isInt = /^\d+$/.test(body.nasl[0].value); const ne = new nasl.Enum({ name, enumItems: body.nasl, valueType: createNaslPrimitiveType(isInt ? 'Long' : 'String'), // ne.label = e.label; 似乎是废弃属性 }); ne.annotations = anns?.map(getNasl); return PackNaslAndCst(ne, TYPE("Enum", { name, body: body.cst, anns: anns?.map(getCst) })); } export const toNaslEnumItem = (prop: string | AstCstPack, anns?) => { if (typeof prop !== 'string') { // @ts-ignore prop = prop.nasl.value; } const nei = new nasl.EnumItem({ // @ts-ignore value: prop, // label: title, 后续 ProcessAnnotation 流程统一处理 }); nei.annotations = anns?.map(getNasl); return PackNaslAndCst(nei, TYPE("EnumItem", { value: prop, anns: anns?.map(getCst) })) } export const toNaslVarInit = ([name, ty, val]) => { const nv = new nasl.Variable({ name: name, typeAnnotation: ty?.nasl, defaultValue: val?.nasl ? new nasl.DefaultValue({expression: val?.nasl}) : undefined, }); return PackNaslAndCst(nv, TYPE("VarInit", { name, ty: ty?.cst, val: val?.cst })); } export function toNaslUsingNamespace(_qName: CstIdentifier) { const nsp = _qName.namespace.concat(_qName.name); return PackNaslAndCst( new UsingNamespace(nsp), TYPE("UsingNamespace", { namespace: nsp }) ); } export function toNaslLogicDeclare(_sig) { const decl = new nasl.LogicDeclaration({ name: _sig.nasl.name, typeParams: _sig.nasl.tyVars, params: _sig.nasl.params, returns: _sig.nasl.ret, }); return PackNaslAndCst(decl, TYPE('LogicDeclare', _sig.cst)); } export function toNaslCstAnn(type: 'Builtin' | 'Custom', name, args) { const cAnn = new CstAnnotation(type, name, args.nasl); return PackNaslAndCst(cAnn, TYPE('Annotation', { type, name, args: args.cst })); } export function toNaslCstAnnArg(name: string, val: any) { const cAArg = new CstAnnotationArg(name, val?.nasl); return PackNaslAndCst(cAArg, TYPE('AnnotationArg', { name: name, val: val?.cst }) ); } export function toNaslNamespace(name: string, defs: Array<any>) { const packed = PackNaslAndCstSeq(defs); const nsp = new CstNamespace(name, packed.nasl); return PackNaslAndCst(nsp, TYPE('Namespace', { defs: packed.cst })); } // pctor: primary constructor export function toNaslEntity(tyIntro, pctor, props, anns?) { const ne = new nasl.Entity({ name: tyIntro.tyCon, properties: props.nasl, annotations: anns?.map(getNasl) }); const cst = TYPE('Entity', { ty: tyIntro, pctor: null, // 暂不支持 props: props.cst, anns: anns?.map(getCst) }); return PackNaslAndCst(ne, cst); }