cddl 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/LICENSE +1 -1
  2. package/build/parser.d.ts.map +1 -1
  3. package/build/parser.js +26 -2
  4. package/package.json +5 -1
  5. package/.release-it.ts +0 -10
  6. package/docs/README.md +0 -47
  7. package/docs/arrays.md +0 -356
  8. package/docs/ast-structure.md +0 -166
  9. package/docs/basic-types.md +0 -243
  10. package/docs/cddl-cheatsheet.md +0 -231
  11. package/docs/comments.md +0 -307
  12. package/docs/groups.md +0 -351
  13. package/docs/operators.md +0 -466
  14. package/docs/properties.md +0 -334
  15. package/docs/ranges.md +0 -339
  16. package/docs/references.md +0 -340
  17. package/docs/variables.md +0 -335
  18. package/src/ast.ts +0 -180
  19. package/src/cli/commands/repl.ts +0 -33
  20. package/src/cli/commands/validate.ts +0 -44
  21. package/src/cli/constants.ts +0 -1
  22. package/src/cli/index.ts +0 -18
  23. package/src/constants.ts +0 -16
  24. package/src/index.ts +0 -12
  25. package/src/lexer.ts +0 -238
  26. package/src/parser.ts +0 -967
  27. package/src/tokens.ts +0 -50
  28. package/src/utils.ts +0 -96
  29. package/tests/__snapshots__/complex_types.test.ts.snap +0 -80
  30. package/tests/__snapshots__/examples.test.ts.snap +0 -1077
  31. package/tests/__snapshots__/group-choices.test.ts.snap +0 -278
  32. package/tests/__snapshots__/parser.test.ts.snap +0 -3045
  33. package/tests/__snapshots__/webdriver-local.test.ts.snap +0 -11192
  34. package/tests/__snapshots__/webdriver-remote.test.ts.snap +0 -16350
  35. package/tests/commands/repl.test.ts +0 -52
  36. package/tests/commands/validate.test.ts +0 -66
  37. package/tests/complex_types.test.ts +0 -18
  38. package/tests/examples.test.ts +0 -25
  39. package/tests/group-choices.test.ts +0 -103
  40. package/tests/lexer.test.ts +0 -63
  41. package/tests/module.test.ts +0 -21
  42. package/tests/parser.test.ts +0 -44
  43. package/tests/utils.test.ts +0 -211
  44. package/tests/webdriver-local.test.ts +0 -15
  45. package/tests/webdriver-remote.test.ts +0 -15
  46. package/tsconfig.json +0 -11
package/src/ast.ts DELETED
@@ -1,180 +0,0 @@
1
- /**
2
- * a group definition
3
- * ```
4
- * person = {
5
- * age: int,
6
- * name: tstr,
7
- * employer: tstr,
8
- * }
9
- * ```
10
- */
11
- export type Group = {
12
- Type: 'group'
13
- Name: string
14
- IsChoiceAddition: boolean
15
- Properties: (Property|Property[])[]
16
- Comments: Comment[]
17
- }
18
-
19
- /**
20
- * an array definition
21
- * ```
22
- * Geography = [
23
- * city: tstr
24
- * ]
25
- * ```
26
- */
27
- export type Array = {
28
- Type: 'array'
29
- Name: string
30
- Values: (Property|Property[])[]
31
- Comments: Comment[]
32
- }
33
-
34
- /**
35
- * a tag definition
36
- * ```
37
- * #6.32(tstr)
38
- * ```
39
- */
40
- export type Tag = {
41
- NumericPart: number
42
- TypePart: string
43
- }
44
-
45
- /**
46
- * a variable assignment
47
- * ```
48
- * device-address = byte
49
- * ```
50
- */
51
- export type Variable = {
52
- Type: 'variable'
53
- Name: string
54
- IsChoiceAddition: boolean
55
- PropertyType: PropertyType | PropertyType[]
56
- Operator?: Operator
57
- Comments: Comment[]
58
- }
59
-
60
- /**
61
- * a comment statement
62
- * ```
63
- * ; This is a comment
64
- * ```
65
- */
66
- export type Comment = {
67
- Type: 'comment'
68
- Content: string
69
- Leading: boolean
70
- }
71
-
72
- export type Occurrence = {
73
- n: number
74
- m: number
75
- }
76
-
77
- export type Property = {
78
- HasCut: boolean
79
- Occurrence: Occurrence
80
- Name: PropertyName
81
- Type: PropertyType | PropertyType[]
82
- Comments: Comment[]
83
- Operator?: Operator
84
- }
85
-
86
- export enum Type {
87
- /**
88
- * any types
89
- */
90
- ANY = 'any',
91
-
92
- /**
93
- * boolean types
94
- */
95
- // Boolean value (major type 7, additional information 20 or 21).
96
- BOOL = 'bool',
97
-
98
- /**
99
- * numeric types
100
- */
101
- // An unsigned integer or a negative integer.
102
- INT = 'int',
103
- // An unsigned integer (major type 0).
104
- UINT = 'uint',
105
- // A negative integer (major type 1).
106
- NINT = 'nint',
107
- // One of float16, float32, or float64.
108
- FLOAT = 'float',
109
- // A number representable as an IEEE 754 half-precision float
110
- FLOAT16 = 'float16',
111
- // A number representable as an IEEE 754 single-precision
112
- FLOAT32 = 'float32',
113
- // A number representable as an IEEE 754 double-precision
114
- FLOAT64 = 'float64',
115
-
116
- /**
117
- * string types
118
- */
119
- // A byte string (major type 2).
120
- BSTR = 'bstr',
121
- // A byte string (major type 2).
122
- BYTES = 'bytes',
123
- // Text string (major type 3)
124
- TSTR = 'tstr',
125
- // Text string (major type 3)
126
- TEXT = 'text',
127
-
128
- /**
129
- * null types
130
- */
131
- NIL = 'nil',
132
- NULL = 'null'
133
- }
134
-
135
- /**
136
- * can be a number, e.g. "foo = 0..10"
137
- * ```
138
- * {
139
- * Type: "int",
140
- * Value: 6
141
- * }
142
- * ```
143
- * or a literal, e.g. "foo = 0..max-byte"
144
- * ```
145
- * {
146
- * Type: "literal",
147
- * Value: "max-byte"
148
- * }
149
- * ```
150
- */
151
- export type RangePropertyReference = number | string
152
-
153
- export type Range = {
154
- Min: RangePropertyReference
155
- Max: RangePropertyReference
156
- Inclusive: boolean
157
- }
158
-
159
- export type OperatorType = 'default' | 'size' | 'regexp' | 'bits' | 'and' | 'within' | 'eq' | 'ne' | 'lt' | 'le' | 'gt' | 'ge'
160
- export interface Operator {
161
- Type: OperatorType
162
- Value: PropertyType
163
- }
164
-
165
- export type PropertyReferenceType = 'literal' | 'group' | 'group_array' | 'array' | 'range' | 'tag'
166
- export type PropertyReference = {
167
- Type: PropertyReferenceType
168
- Value: string | number | boolean | Group | Array | Range | Tag
169
- Unwrapped: boolean
170
- Operator?: Operator
171
- }
172
-
173
- export interface NativeTypeWithOperator {
174
- Type: Type | PropertyReference
175
- Operator?: Operator
176
- }
177
-
178
- export type Assignment = Group | Array | Variable
179
- export type PropertyType = Assignment | Array | PropertyReference | string | NativeTypeWithOperator
180
- export type PropertyName = string
@@ -1,33 +0,0 @@
1
- import repl from 'node:repl'
2
- import type { Argv } from 'yargs'
3
-
4
- import { CLI_EPILOGUE } from '../constants.js'
5
- import Lexer from '../../lexer.js'
6
- import { Tokens } from '../../tokens.js'
7
-
8
- export const command = 'repl'
9
- export const desc = 'Run CDDL repl'
10
- export const builder = (yargs: Argv<{}>) => {
11
- return yargs
12
- .epilogue(CLI_EPILOGUE)
13
- .help()
14
- }
15
-
16
- export const handler = () => {
17
- repl.start({
18
- prompt: '> ',
19
- eval: evaluate
20
- })
21
- }
22
-
23
- export function evaluate (evalCmd: string, _: any, _file: string, callback: (err: Error | null, result: any) => void) {
24
- if (!evalCmd) {
25
- return callback(new Error('No input'), null)
26
- }
27
-
28
- const l = new Lexer(evalCmd)
29
- for (let tok = l.nextToken(); tok.Type !== Tokens.EOF; tok = l.nextToken()) {
30
- console.log(tok)
31
- }
32
- return callback(null, null)
33
- }
@@ -1,44 +0,0 @@
1
- import fs from 'node:fs'
2
- import path from 'node:path'
3
- import type { Argv, ArgumentsCamelCase } from 'yargs'
4
-
5
- import { CLI_EPILOGUE } from '../constants.js'
6
- import { parse } from '../../index.js'
7
-
8
- interface ValidateArguments {
9
- filePath: string
10
- }
11
-
12
- export const command = 'validate <filePath>'
13
- export const desc = 'Validate a *.cddl file'
14
- export const builder = (yargs: Argv<{}>) => {
15
- return yargs
16
- .epilogue(CLI_EPILOGUE)
17
- .help()
18
- }
19
-
20
- export const handler = (argv: ArgumentsCamelCase<ValidateArguments>) => {
21
- const filePath = argv.filePath.startsWith('/')
22
- ? argv.filePath
23
- : path.resolve(process.cwd(), argv.filePath)
24
-
25
- if (!fs.existsSync(filePath)) {
26
- console.error(`Couldn't find CDDL file at ${filePath}`)
27
- return process.exit(1)
28
- }
29
-
30
- try {
31
- parse(filePath)
32
-
33
-
34
- /**
35
- * ToDo check for
36
- * - missing group declarations
37
- */
38
-
39
- console.log('✅ Valid CDDL file!')
40
- } catch (err: unknown) {
41
- console.error(`⚠️ Invalid CDDL file (${filePath})\n\n${(err as Error).stack}`)
42
- process.exit(1)
43
- }
44
- }
@@ -1 +0,0 @@
1
- export const CLI_EPILOGUE = `Copyright 2023 - Christian Bromann`
package/src/cli/index.ts DELETED
@@ -1,18 +0,0 @@
1
- import yargs from 'yargs/yargs'
2
- import { hideBin } from 'yargs/helpers'
3
-
4
- import * as replCommand from './commands/repl.js'
5
- import * as validateCommand from './commands/validate.js'
6
- import { CLI_EPILOGUE } from './constants.js'
7
-
8
- export default async function () {
9
- const argv = yargs(hideBin(process.argv))
10
- .command(replCommand)
11
- .command(validateCommand as any)
12
- .example('$0 repl', 'Start CDDL repl')
13
- .epilogue(CLI_EPILOGUE)
14
- .demandCommand()
15
- .help()
16
-
17
- return argv.argv
18
- }
package/src/constants.ts DELETED
@@ -1,16 +0,0 @@
1
- export const WHITESPACE_CHARACTERS = [' ', '\t', '\n', '\r']
2
- export const BOOLEAN_LITERALS = ['true', 'false']
3
-
4
- /**
5
- * as defined in Appendix D
6
- * https://tools.ietf.org/html/draft-ietf-cbor-cddl-08#appendix-D
7
- */
8
- export const PREDEFINED_IDENTIFIER = [
9
- 'any', 'uint', 'nint', 'int', 'bstr', 'bytes', 'tstr', 'text',
10
- 'tdate', 'time', 'number', 'biguint', 'bignint', 'bigint',
11
- 'integer', 'unsigned', 'decfrac', 'bigfloat', 'eb64url',
12
- 'eb64legacy', 'eb16', 'encoded-cbor', 'uri', 'b64url',
13
- 'b64legacy', 'regexp', 'mime-message', 'cbor-any', 'float16',
14
- 'float32', 'float64', 'float16-32', 'float32-64', 'float',
15
- 'false', 'true', 'bool', 'nil', 'null', 'undefined'
16
- ]
package/src/index.ts DELETED
@@ -1,12 +0,0 @@
1
- import Lexer from './lexer.js'
2
- import Parser from './parser.js'
3
-
4
- export function parse (filePath: string) {
5
- const parser = new Parser(filePath)
6
- return parser.parse()
7
- }
8
-
9
- export default { parse }
10
- export { Lexer, Parser }
11
- export * from './ast.js'
12
- export * from './utils.js'
package/src/lexer.ts DELETED
@@ -1,238 +0,0 @@
1
- import { Token, Tokens } from './tokens.js';
2
- import { isLetter, isAlphabeticCharacter, isDigit, hasSpecialNumberCharacter } from './utils.js'
3
- import { WHITESPACE_CHARACTERS } from './constants.js';
4
-
5
- export default class Lexer {
6
- input: string
7
- position: number = 0
8
- readPosition: number = 0
9
- ch: number = 0
10
-
11
- constructor (source: string) {
12
- this.input = source
13
-
14
- this.readChar()
15
- }
16
-
17
- private readChar (): void {
18
- if (this.readPosition >= this.input.length) {
19
- this.ch = 0
20
- } else {
21
- this.ch = this.input[this.readPosition].charCodeAt(0)
22
- }
23
- this.position = this.readPosition
24
- this.readPosition++
25
- }
26
-
27
- getLocation () {
28
- const position = this.position - 2
29
- const sourceLines = this.input.split('\n')
30
- const sourceLineLength = sourceLines.map((l) => l.length)
31
- let i = 0
32
-
33
- for (const [line, lineLength] of Object.entries(sourceLineLength)) {
34
- i += lineLength + 1
35
- if (i > position) {
36
- const lineBegin = i - lineLength
37
- return {
38
- line: parseInt(line, 10),
39
- position: position - lineBegin + 1
40
- }
41
- }
42
- }
43
-
44
- return { line: 0, position: 0 }
45
- }
46
-
47
- getLine (lineNumber: number) {
48
- return this.input.split('\n')[lineNumber]
49
- }
50
-
51
- getLocationInfo () {
52
- const loc = this.getLocation()
53
- const line = loc ? this.getLine(loc.line) : ''
54
- let locationInfo = line + '\n'
55
- locationInfo += ' '.repeat(loc?.position || 0) + '^\n'
56
- locationInfo += ' '.repeat(loc?.position || 0) + '|\n'
57
- return locationInfo
58
- }
59
-
60
- nextToken (): Token {
61
- let token: Token
62
- this.skipWhitespace()
63
-
64
- const Literal = String.fromCharCode(this.ch)
65
- switch (this.ch) {
66
- case '='.charCodeAt(0):
67
- token = { Type: Tokens.ASSIGN, Literal }
68
- break
69
- case '('.charCodeAt(0):
70
- token = { Type: Tokens.LPAREN, Literal }
71
- break
72
- case ')'.charCodeAt(0):
73
- token = { Type: Tokens.RPAREN, Literal }
74
- break
75
- case '{'.charCodeAt(0):
76
- token = { Type: Tokens.LBRACE, Literal }
77
- break
78
- case '}'.charCodeAt(0):
79
- token = { Type: Tokens.RBRACE, Literal }
80
- break
81
- case '['.charCodeAt(0):
82
- token = { Type: Tokens.LBRACK, Literal }
83
- break
84
- case ']'.charCodeAt(0):
85
- token = { Type: Tokens.RBRACK, Literal }
86
- break
87
- case '<'.charCodeAt(0):
88
- token = { Type: Tokens.LT, Literal }
89
- break
90
- case '>'.charCodeAt(0):
91
- token = { Type: Tokens.GT, Literal }
92
- break
93
- case '+'.charCodeAt(0):
94
- token = { Type: Tokens.PLUS, Literal }
95
- break
96
- case ','.charCodeAt(0):
97
- token = { Type: Tokens.COMMA, Literal }
98
- break
99
- case '.'.charCodeAt(0):
100
- token = { Type: Tokens.DOT, Literal }
101
- break
102
- case ':'.charCodeAt(0):
103
- token = { Type: Tokens.COLON, Literal }
104
- break
105
- case '?'.charCodeAt(0):
106
- token = { Type: Tokens.QUEST, Literal }
107
- break
108
- case '/'.charCodeAt(0):
109
- token = { Type: Tokens.SLASH, Literal }
110
- break
111
- case '*'.charCodeAt(0):
112
- token = { Type: Tokens.ASTERISK, Literal }
113
- break
114
- case '^'.charCodeAt(0):
115
- token = { Type: Tokens.CARET, Literal }
116
- break
117
- case '#'.charCodeAt(0):
118
- token = { Type: Tokens.HASH, Literal }
119
- break
120
- case '~'.charCodeAt(0):
121
- token = { Type: Tokens.TILDE, Literal }
122
- break
123
- case '"'.charCodeAt(0):
124
- token = { Type: Tokens.STRING, Literal: this.readString() }
125
- break
126
- case ';'.charCodeAt(0):
127
- token = { Type: Tokens.COMMENT, Literal: this.readComment() }
128
- break
129
- case 0:
130
- token = { Type: Tokens.EOF, Literal: '' }
131
- break
132
- default: {
133
- if (isAlphabeticCharacter(Literal)) {
134
- return { Type: Tokens.IDENT, Literal: this.readIdentifier() }
135
- } else if (
136
- // positive number
137
- isDigit(Literal) ||
138
- // negative number
139
- (this.ch === Tokens.MINUS.charCodeAt(0) && isDigit(this.input[this.readPosition]))
140
- ) {
141
- const numberOrFloat = this.readNumberOrFloat()
142
- return {
143
- Type: numberOrFloat.includes(Tokens.DOT) ? Tokens.FLOAT : Tokens.NUMBER,
144
- Literal: numberOrFloat
145
- }
146
- }
147
- token = { Type: Tokens.ILLEGAL, Literal: '' }
148
- }
149
- }
150
-
151
- this.readChar()
152
- return token
153
- }
154
-
155
- private readIdentifier (): string {
156
- const position = this.position
157
-
158
- /**
159
- * an identifier can contain
160
- * see https://tools.ietf.org/html/draft-ietf-cbor-cddl-08#section-3.1
161
- */
162
- while (
163
- // a letter (a-z, A-Z)
164
- isLetter(String.fromCharCode(this.ch)) ||
165
- // a digit (0-9)
166
- isDigit(String.fromCharCode(this.ch)) ||
167
- // and special characters (-, _, @, ., $)
168
- [
169
- Tokens.MINUS.charCodeAt(0),
170
- Tokens.UNDERSCORE.charCodeAt(0),
171
- Tokens.ATSIGN.charCodeAt(0),
172
- Tokens.DOT.charCodeAt(0),
173
- Tokens.DOLLAR.charCodeAt(0)
174
- ].includes(this.ch)
175
- ) {
176
- this.readChar()
177
- }
178
-
179
- return this.input.slice(position, this.position)
180
- }
181
-
182
- private readComment (): string {
183
- const position = this.position
184
-
185
- while (this.ch && String.fromCharCode(this.ch) !== '\n') {
186
- this.readChar()
187
- }
188
-
189
- return this.input.slice(position, this.position).trim()
190
- }
191
-
192
- private readString (): string {
193
- const position = this.position
194
-
195
- this.readChar() // eat "
196
- while (this.ch && String.fromCharCode(this.ch) !== Tokens.QUOT) {
197
- this.readChar() // eat any character until "
198
- }
199
-
200
- return this.input.slice(position + 1, this.position).trim()
201
- }
202
-
203
- private readNumberOrFloat (): string {
204
- const position = this.position
205
- let foundSpecialCharacter = false
206
-
207
- /**
208
- * a number of float can contain
209
- */
210
- while (
211
- // a number
212
- isDigit(String.fromCharCode(this.ch)) ||
213
- // a special character, e.g. ".", "x" and "b"
214
- hasSpecialNumberCharacter(this.ch)
215
- ) {
216
- /**
217
- * ensure we respect ranges, e.g. 0..10
218
- * so break after the second dot and adjust read position
219
- */
220
- if (hasSpecialNumberCharacter(this.ch) && foundSpecialCharacter) {
221
- this.position--
222
- this.readPosition--
223
- break
224
- }
225
-
226
- foundSpecialCharacter = hasSpecialNumberCharacter(this.ch)
227
- this.readChar() // eat any character until a non digit or a 2nd dot
228
- }
229
-
230
- return this.input.slice(position, this.position).trim()
231
- }
232
-
233
- private skipWhitespace () {
234
- while (WHITESPACE_CHARACTERS.includes(String.fromCharCode(this.ch))) {
235
- this.readChar()
236
- }
237
- }
238
- }