Skip to content

Commit

Permalink
实现解析三种联合类型
Browse files Browse the repository at this point in the history
  • Loading branch information
jindy committed Jun 21, 2022
1 parent 3d3f7e4 commit 4aa6a11
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 27 deletions.
100 changes: 73 additions & 27 deletions src/compiler-core/src/parse.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,70 @@
import { NodeTypes } from "./ast"

const enum TagType {
Start,
End,
}

export function baseParse(content: string) {
const context = createParseContext(content)
return createRoot(parseChildren(context))
return createRoot(parseChildren(context, []))
}

function parseChildren(context) {
function parseChildren(context, ancestors) {
const nodes: any = []
let node
const s = context.source
if (s.startsWith("{{")) {
node = parseInterpolation(context)
} else if (s[0] === "<") {
if (/[a-z]/i.test(s[1])) {
node = parseElement(context)
while (!isEnd(context, ancestors)) {
let node
const s = context.source
if (s.startsWith("{{")) {
node = parseInterpolation(context)
} else if (s[0] === "<") {
if (/[a-z]/i.test(s[1])) {
node = parseElement(context, ancestors)
}
}
}

if (!node) {
node = parseText(context)
if (!node) {
node = parseText(context)
}
nodes.push(node)
}

nodes.push(node)
return nodes
}

function isEnd(context, ancestors) {
console.log("isEnd:", ancestors)
const s = context.source
// 2.遇到为结束标签
// if (ancestors && s.startsWith(`</${ancestors}>`)) {
// return true
// }
if (s.startsWith("</")) {
for (let index = 0; index < ancestors.length; index++) {
const tag = ancestors[index].tag
// if (s.slice(2, 2 + tag.length) === tag) {
if (startsWithEndTagOpen(s, tag)) {
return true
}
}
}
// 1.source 有值
return !s
}

function parseText(context) {
const endTokens = ["<", "{{"]
let endIndex = context.source.length

for (let i = 0; i < endTokens.length; i++) {
const index = context.source.indexOf(endTokens[i])
if (index !== -1 && endIndex > index) {
endIndex = index
}
}

//1.获取内容 content
const content = parseTextData(context, context.source.length)
const content = parseTextData(context, endIndex)
// 2. 推进 -》 删除处理完成的代码???
// advanceBy(context, content.length)

Expand All @@ -46,31 +83,39 @@ function parseTextData(context, length) {
return content
}

const enum TagType {
START,
END,
}

function parseElement(context) {
const element = parseTag(context, TagType.START)

parseTag(context, TagType.END)
function parseElement(context, ancestors) {
const element: any = parseTag(context, TagType.Start)
ancestors.push(element)
element.children = parseChildren(context, ancestors)
ancestors.pop()
if (startsWithEndTagOpen(context.source, element.tag)) {
parseTag(context, TagType.End)
} else {
throw new Error(`${element.tag}缺少结束标签`)
}

// console.log(context.source, "1111")

return element
}

function parseTag(context: any, TagType) {
function startsWithEndTagOpen(source, tag) {
return (
source.startsWith("</") &&
source.slice(2, 2 + tag.length).toLowerCase() === tag.toLowerCase()
)
}

function parseTag(context: any, type) {
// 1.解析tag
const match: any = /^<\/?([a-z]*)/i.exec(context.source)
console.log(match)
// console.log(match, "match")
const tag = match[1]
// 2.删除处理完成的代码
advanceBy(context, match[0].length)
advanceBy(context, 1)
// console.log(context.source)
if (TagType === TagType.END) return
if (type === TagType.End) return
return {
type: NodeTypes.ELEMENT,
tag,
Expand All @@ -87,6 +132,7 @@ function parseInterpolation(context) {
)
// context.source = context.source.slice(openDelimiter.length)
advanceBy(context, openDelimiter.length)
// advanceBy(context, 2)

const rawContentLength = closeIndex - openDelimiter.length
const rawContent = parseTextData(context, rawContentLength) //context.source.slice(0, rawContentLength)
Expand All @@ -100,7 +146,7 @@ function parseInterpolation(context) {
type: NodeTypes.INTERPOLATION,
content: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: content,
content,
},
}
}
Expand Down
57 changes: 57 additions & 0 deletions src/compiler-core/tests/parse.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe("Parse", () => {
expect(ast.children[0]).toStrictEqual({
type: NodeTypes.ELEMENT,
tag: "div",
children: [],
})
})
})
Expand All @@ -36,4 +37,60 @@ describe("Parse", () => {
})
})
})

test("hello, world", () => {
const ast: any = baseParse("<div>hi,{{massage}}</div>")

expect(ast.children[0]).toStrictEqual({
type: NodeTypes.ELEMENT,
tag: "div",
children: [
{
type: NodeTypes.TEXT,
content: "hi,",
},
{
type: NodeTypes.INTERPOLATION,
content: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: "massage",
},
},
],
})
})

test("Nested element", () => {
const ast: any = baseParse("<div><p>hi</p>{{massage}}</div>")

expect(ast.children[0]).toStrictEqual({
type: NodeTypes.ELEMENT,
tag: "div",
children: [
{
type: NodeTypes.ELEMENT,
tag: "p",
children: [
{
type: NodeTypes.TEXT,
content: "hi",
},
],
},
{
type: NodeTypes.INTERPOLATION,
content: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: "massage",
},
},
],
})
})

test("should throw error when lack end tag", () => {
expect(() => {
baseParse("<div><span></div>")
}).toThrow("span缺少结束标签")
})
})

0 comments on commit 4aa6a11

Please sign in to comment.