Skip to content

Commit

Permalink
Fix some map parsing cases
Browse files Browse the repository at this point in the history
  • Loading branch information
eemeli committed Dec 20, 2020
1 parent 8ef78e7 commit 71ef008
Showing 1 changed file with 44 additions and 15 deletions.
59 changes: 44 additions & 15 deletions src/parse/parser.ts
Expand Up @@ -84,6 +84,11 @@ export type Token =
| BlockSequence
| FlowCollection

function includesToken(list: SourceToken[], type: SourceToken['type']) {
for (let i = 0; i < list.length; ++i) if (list[i].type === type) return true
return false
}

/** A YAML concrete syntax tree parser */
export class Parser {
push: (token: Token) => void
Expand All @@ -102,7 +107,10 @@ export class Parser {

offset = 0

/** Top indicates the bode that's currently being built */
/** On the same line with a block map key */
onKeyLine = false

/** Top indicates the node that's currently being built */
stack: Token[] = []

/** The source of the current token, set in parse() */
Expand Down Expand Up @@ -236,7 +244,10 @@ export class Parser {
const it = top.items[top.items.length - 1]
if (it.value) top.items.push({ start: [], key: token, sep: [] })
else if (it.sep) it.value = token
else Object.assign(it, { key: token, sep: [] })
else {
Object.assign(it, { key: token, sep: [] })
this.onKeyLine = true
}
break
}
case 'block-seq': {
Expand Down Expand Up @@ -286,10 +297,10 @@ export class Parser {
if (doc.value) return this.lineEnd(doc)
switch (this.type) {
case 'doc-start': {
const hasContent = doc.start.some(
({ type }) =>
type === 'doc-start' || type === 'anchor' || type === 'tag'
)
const hasContent =
includesToken(doc.start, 'doc-start') ||
includesToken(doc.start, 'anchor') ||
includesToken(doc.start, 'tag')
if (hasContent) {
this.pop()
this.step()
Expand Down Expand Up @@ -330,6 +341,7 @@ export class Parser {
indent: scalar.indent,
items: [{ start: [], key: scalar, sep }]
}
this.onKeyLine = true
this.stack[this.stack.length - 1] = map
} else this.lineEnd(scalar)
}
Expand Down Expand Up @@ -365,26 +377,30 @@ export class Parser {
const it = map.items[map.items.length - 1]
// it.sep is true-ish if pair already has key or : separator
switch (this.type) {
case 'newline':
this.onKeyLine = false
// fallthrough
case 'space':
case 'comment':
case 'newline':
if (it.value) map.items.push({ start: [this.sourceToken] })
else if (it.sep) it.sep.push(this.sourceToken)
else it.start.push(this.sourceToken)
return
}
if (this.indent >= map.indent) {
const atNextItem = !this.onKeyLine && this.indent === map.indent
switch (this.type) {
case 'anchor':
case 'tag':
if (it.value) map.items.push({ start: [this.sourceToken] })
if (atNextItem || it.value)
map.items.push({ start: [this.sourceToken] })
else if (it.sep) it.sep.push(this.sourceToken)
else it.start.push(this.sourceToken)
return

case 'explicit-key-ind':
if (!it.sep) it.start.push(this.sourceToken)
else if (it.value || this.indent === map.indent)
else if (atNextItem || it.value)
map.items.push({ start: [this.sourceToken] })
else
this.stack.push({
Expand All @@ -393,30 +409,41 @@ export class Parser {
indent: this.indent,
items: [{ start: [this.sourceToken] }]
})
this.onKeyLine = true
return

case 'map-value-ind':
if (!it.sep) Object.assign(it, { key: null, sep: [this.sourceToken] })
else if (it.value)
else if (
it.value ||
(atNextItem && !includesToken(it.start, 'explicit-key-ind'))
)
map.items.push({ start: [], key: null, sep: [this.sourceToken] })
else if (it.sep.some(tok => tok.type === 'map-value-ind'))
else if (includesToken(it.sep, 'map-value-ind'))
this.stack.push({
type: 'block-map',
offset: this.offset,
indent: this.indent,
items: [{ start: [], key: null, sep: [this.sourceToken] }]
})
else it.sep.push(this.sourceToken)
this.onKeyLine = true
return

case 'alias':
case 'scalar':
case 'single-quoted-scalar':
case 'double-quoted-scalar': {
const fs = this.flowScalar(this.type)
if (it.value) map.items.push({ start: [], key: fs, sep: [] })
else if (it.sep) this.stack.push(fs)
else Object.assign(it, { key: fs, sep: [] })
if (atNextItem || it.value) {
map.items.push({ start: [], key: fs, sep: [] })
this.onKeyLine = true
} else if (it.sep) {
this.stack.push(fs)
} else {
Object.assign(it, { key: fs, sep: [] })
this.onKeyLine = true
}
return
}

Expand Down Expand Up @@ -446,7 +473,7 @@ export class Parser {
return
case 'seq-item-ind':
if (this.indent !== seq.indent) break
if (it.value || it.start.some(tok => tok.type === 'seq-item-ind'))
if (it.value || includesToken(it.start, 'seq-item-ind'))
seq.items.push({ start: [this.sourceToken] })
else it.start.push(this.sourceToken)
return
Expand Down Expand Up @@ -540,13 +567,15 @@ export class Parser {
items: [{ start: [this.sourceToken] }]
} as BlockSequence
case 'explicit-key-ind':
this.onKeyLine = true
return {
type: 'block-map',
offset: this.offset,
indent: this.indent,
items: [{ start: [this.sourceToken] }]
} as BlockMap
case 'map-value-ind':
this.onKeyLine = true
return {
type: 'block-map',
offset: this.offset,
Expand Down

0 comments on commit 71ef008

Please sign in to comment.