扫描器
JavaScript 基于正则的字符串扫描器/ 切换器
安装
npm install --save @desertnet/scanner
使用量
一个示例
const Scanner = require('@desertnet/scanner')
const body = `Hi! [img-1]
[img-2]
Bye[!]`
const embedTagScanner = new Scanner([
{'tag': /\[\w+-\d+\]/},
{'text': /[^\[]+/},
{'bracket': /\[/}
])
let token
embedTagScanner.setSource(body)
while (token = embedTagScanner.nextToken()) {
console.log(token)
}
产出:
Token { type: 'text', value: 'Hi! ', index: 0, line: 1, column: 1 }
Token { type: 'tag', value: '[img-1]', index: 4, line: 1, column: 5 }
Token { type: 'text', value: '\n', index: 11, line: 2, column: 12 }
Token { type: 'tag', value: '[img-2]', index: 12, line: 2, column: 1 }
Token { type: 'text', value: '\nBye', index: 19, line: 3, column: 8 }
Token { type: 'bracket', value: '[', index: 23, line: 3, column: 4 }
Token { type: 'text', value: '!]', index: 24, line: 3, column: 5 }
对话框
在本单元中,a 方言 是命令将一个符号类型映射到描述该符号的正则表达式。 在上述例子中,你会看到 Scanner 对象以数组对象即时化,每个对象包含单个对象 RegExp 属性。 此模式允许您为扫描仪简洁地定义方言 .
我们称方言为有秩序的映射,因为定义符号类型的顺序很重要。 扫描仪会试图将输入字符串与方言中的第一个正格克相匹配. 如果失败了,它将进入名单上的下一个。 匹配完成后,会生成一个与匹配类型相匹配的符号. 没有尝试与方言中任何剩余的正则正则正则正正正方形相匹配.
一般来说,确保您的方言接受所有输入是一个很好的想法。 如果您不这样做,那么一个输入字符串可能会使扫描仪丢出"意外字符"出错. 在示例中通知如何 text 符号描述符合所有非符号 [ 字符,最后一个符号描述匹配一个孤独 [ 字符键。 这将确保所有投入产生一个符号。 另一种方法是用以下符号描述结束你的方言,以匹配任何单个字符:
{'catchall': /[^]/} // This is the same as `qr/./s` in Perl
多声波扫描仪
一种语言通常不会使用单一的方言来描述。 例如,HTML经常包含内置CSS. 或JavaDoc注释在Java评论内部. 即使是像 HTML 属性值这样的简单东西也用 " 和 HTML 属性值 ' 可能需要不同的方言定义.
通过将一个对象传递到 Scanner 建筑师。 这个对象应该是将方言名称与方言定义相映射. 例如,这里是一个相当脱落的 HTML 多透视扫描仪的开始:
const htmlScanner = new Scanner({
// Starting dialect, for content "outside of a tag".
"content": [
{"text": /[^<>]+/},
{"tagStart": /<[a-z][^\t\n\ \/\>]*/i},
{"closeTagStart": /<\/[a-z][^\t\n\ \/\>]*/i},
{"error": /[<>]/}
],
// Dialect for the inside of tags.
"tag": [
{"tagEnd": />/},
{"whitespace": /\s+/},
{"selfClose": /\//},
{"error": /['"<=]/},
{"attributeStart": /[^>=\s\/]+/i}
],
// Initial dialect for attributes.
"attribute": [
{"whitespace": /\s+/},
{"attributeValueQuotedStart": /=['"]/},
{"attributeValueStart": /=/},
{"tagEnd": />/},
{"selfClose": /\//},
{"error": /['"<]/},
],
// Dialect for closing tags.
"closeTag": [
{"tagEnd": />/},
{"whitespace": /\s+/},
{"error": /[^\s>]+/}
],
// ...
})
一旦你有一个多光谱扫描仪 你必须打电话 scanner.pushDialect(dialectName) 以设置初始方言。 当您标注您的字符串时, 您可以打电话 .pushDialect() 财务报告和审定财务报表 .popDialect() 当您输入的语境改变为不同的方言时。 (当然,你可以打电话 .setDialect() 直接,但不要将它与使用扫描仪的方言堆栈相混合. )
API 密码
新扫描仪( 透析定义)
构造一个新的 Scanner 带有指定方言定义的对象。 若为 dialectDefinition 是一个矩阵,然后预计数组包含一个符号描述符列表,这是一个包含一个单一属性的对象,将一个符号类型映射到一个 RegExp。如果它是对象,那么预计每个属性都会将方言名称映射到一系列符号描述符上。 参见上述"Dialects"和"多声扫描仪"的定义.
.set 来源(输入)
设置扫描仪的输入字符串。 如果您正在重用扫描器实例, 调用此方法会将扫描器重置到新字符串的开头 .
. 当前数字( )
返回当前方言名称的字符串 。 对于单射线扫描仪来说 永远是 'main'。 。 。 .
.setDialect(名称)
将当前方言设置为字符串指定的方言 name。您无需使用单相扫描仪。 对于多透视扫描仪来说,使用扫描仪的方言堆栈管理方法可能更好.
.pushDialect(名称)
将名称指定的方言推入扫描器的方言堆栈中,并将其设置为当前方言.
.popDialect () (中文(简体) )
从扫描器的方言堆放出最顶尖的方言,将目前的方言放入现在堆放最顶尖的方言.
.nextToken([预期托肯])
回返a Token 对象,用于源字符串中下一个匹配符号。 要扫描一个字符串,请继续使用这种方法直到它返回 null,表示整个字符串已被扫描。 如果方言无法匹配下个符号, 此方法可能会出错, 所以请确定定义您的方言以覆盖所有输入 .
可选 expectedTokens 参数是当前方言的符号类型名称的数组. 如果只扫描一个符号类型的子集是有意义的,则使用此选项 。 然而,如果你发现自己这样做,也许最好切换到多透视扫描仪.
新扫描仪 。 托肯(类型、值、索引、行、列)
一般情况下 Token 分类不应直接进行即时处理。 然而,建筑师是公开的,因为它可以方便地在测试中即时使用你自己的.
在典型的用法中,它们被归还给你 scanner.nextToken()。它们具有以下可读属性:
type:符号类型的名称. (一弦value: 来自输入的匹配子串.index:输入字符串中符号起始的零基索引.line:指使符从输入字符串开始的单行索引.column: 指使符从行内开始的单行索引.