0.1.0 • Published 10 months ago

@lcap/nasl-parser v0.1.0

Weekly downloads
-
License
ISC
Repository
-
Last release
10 months ago

仓库目录结构

./grammar 语法文件
./ts  解析器源码
./ts/toAST 到 AST 的转换源码
       -----decorated-nasl-ast    给 NASL 增加了一些必要的中间态字段定义
       -----builtin-namespace     目前是内置函数定义
       -----to-nasl-xxx           语法树到 AST 的初始转换
       -----resolve-global-bindings 收集类型函数等的全局定义
       -----resolve-local-bindings 处理逻辑局部的 name resolution
       -----process-annotations    处理注解

./examples/unit       ----- e2e 单测的 NASL 文件
          ----apps 整个应用的 e2e 的 NASL 文件
          ----enums 枚举的 e2e 的 NASL 文件
          ----structs 数据类型的 e2e 的 NASL 文件
          ----logics的 逻辑的 e2e 的 NASL 文件

./tests/e2e
         ---- logics            e2e 单测的 .spec.ts 文件,远端不存储,每次测试重新生成
               ---- controlled  e2e 单测的 控制组 nasl.json 文件
               ---- real        e2e 单测的 实际 nasl.json 文件,远端不存储,每次测试重新生成

./tests/semantics                一些语义测试,会执行 toAST

./tests/unambiguous-grammar      大量语法测试,不执行 toAST,主要检测语法是否正确,语法树是否唯一

package.json 命令

  1. 编译语法和 ts 文件:npm run build
  2. 运行所有测试文件:npm run test-all
  3. 快速测试:npm run test-parse,会运行 ts/testParse.ts 文件,解析里面的 testCode 字符串,更换字符串内容即可测试
  4. ts/index.ts 里面有个 parseToNaslJson 函数,接受字符串,产出 nasl JSON 的字符串,可作为接口调用。

gen-predicate:一个过时的东西,之后会尽快替换掉。

测试用例摘取(特性和语法)

用例 1

namespace app {
    namespace dataSources {
        namespace defaultDS {
            namespace entities {
                entity LCAPUserDeptMapping() {
                    let userId: Integer;
                    let deptId: Integer;
                }
            }
        }
    }
}

using app::dataSources::defaultDS::entities;  // 引入了 LCAPUserDeptMapping

// 这是一段注释
@(
    description = "这是一段描述",
)
logic aiTest1(list: List<Integer>) => result {
    let userDeptMapList: List<LCAPUserDeptMapping>
    result = null
    if (list.length == 0) {
        result = null
    } else {
        result = ListSum(list) / list.length
    }
}

用例 2

// 这是一段注释
@(
    description = "这是一段描述",
)
logic aiTest1(list: List<Integer>) => result {
    let userDeptMapList: List<app::dataSources::defaultDS::entities::LCAPUserDeptMapping>  // 直接使用类型全称,硬编码支持
    result = null
    if (list.length == 0) {
        result = null
    } else {
        result = ListSum(list) / list.length // 内置函数硬编码支持,调用优先解析到内置函数
    }
    end
}

用例 3

@(
    description = "获取所有的角色名称",
)
logic LCAPGetRoleNameList(roleName: String) => result {
    let search: List<app::structures::LCAPRole>

    if (HasValue(search)) {
        result = ListTransform(search, { item => item.name })
    } else {
        result = []: List<String>
    }

    result = ListTransform(result, { item => ToLower(item) })
    if (HasValue(roleName)) {
        if (Contains(result, ToLower(roleName))) {
            Add(result, roleName);
        } else {
        }
    } else {
    }
    ListDistinct(result)
}

用例 4

namespace app {
    namespace enums {
        @(description = '这不是一个有用的枚举')
        enum MyEnumInt {
            @(label = 'nmb')
            case 0;

            @(label = '2333')
            case 1;
        }
    }
}

namespace WhatEverDoesNotMatter {
    @(description = '这是一个垃圾枚举')
    enum MyEnumStr {
        @(label = '值J')
        case J;

        @(label = '值K')
        case K;
    }
}

using app::enums;
using WhatEverDoesNotMatter;

@(
    transactional = false,
)
logic enumRef() {
    let variable1: MyEnumInt;
    let variable2;
    let variable3;
    let variable4;
    let variable5;
    let variable6;
    let variable7;

    variable1 = MyEnumInt::0
    variable2 = MyEnumInt::1
    variable3 = MyEnumStr::J
    variable4 = MyEnumStr::K
    variable5 = EnumItemToStructure(MyEnumStr::J)
    variable6 = EnumItemToText(MyEnumInt::0)
    end
}

用例 5

logic newComp() {
    let variable1;
    let variable2;

    variable1 = app::structures::SS1 (   // 暂时用 () 不用 {},构造器会生成到 New + 连线
        property1=null,
        property2=111,
    )
    variable2 = app::dataSources::defaultDS::entities::Entity1 (   // 暂时用 () 不用 {},构造器会生成到 New + 连线
        id=222,
        createdTime=null,
        updatedTime=null,
        createdBy='fanzheng',
        updatedBy='bushini',
        property1='fanzheng1',
        property2='bushini1',
    )
    end
}

用例 6

@(
    description = '请输入数据结构描述'
)
struct SS2 {
    let property1: Integer = 0;
    let property2: app::structures::SS1;
}

struct SS1 {
    let property1: app::structures::SS2;
    let property2: Decimal = 0.1;
}

添加测试用例

e2e 用例

  1. examples/unit/???/ 文件夹下添加 nasl 文件
  2. tests/e2e/???/controlled 文件夹下添加正确的 json 文件
  3. ts/prepare-tests.ts 文件里添加测试用例名
  4. npm run test-all 看效果

举例:

  1. examples/unit/logics/asgn.nasl
  2. tests/e2e/logics/controlled/asgn.json
  3. ts/prepare-tests.ts 文件里的 logicUTNames 数组里添加 asgn
  4. 运行

注意,现在 NASL 各种 undefinednull[] 在各个节点表现不同,很难弄一致,还有很多脏数据,除了手动控制用例外,还可以修改 ts/nasl-json-util.ts里面的配置,跳过一些属性的对比。

解析器 parser 用例

写一个 .spec.ts 文件放到 tests/unambiguous-grammar/ 文件夹下即可,文件格式直接参考其他用例

toAST 语义分析用例

写一个 .spec.ts 文件放到 tests/semantics/ 文件夹下即可,文件格式直接参考其他用例。

报错

报错?2 周写的东西,报错是不存在的。语法有问题直接群里找开发者吧。