Skip to content

Commit

Permalink
feat: parse
Browse files Browse the repository at this point in the history
  • Loading branch information
cuixiaorui committed Sep 29, 2021
1 parent 69f77ca commit a09c594
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 25 deletions.
62 changes: 53 additions & 9 deletions src/compiler-core/__tests__/parse.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,39 @@ describe("parser", () => {
content: "some text",
});
});

test("simple text with invalid end tag", () => {
const ast = baseParse("some text</div>");
const text = ast.children[0];

expect(text).toStrictEqual({
type: NodeTypes.TEXT,
content: "some text",
});
});

test("text with interpolation", () => {
const ast = baseParse("some {{ foo + bar }} text");
const text1 = ast.children[0];
const text2 = ast.children[2];

// ast.children[1] 应该是 interpolation
expect(text1).toStrictEqual({
type: NodeTypes.TEXT,
content: "some ",
});
expect(text2).toStrictEqual({
type: NodeTypes.TEXT,
content: " text",
});
});
});

describe("Interpolation", () => {
test("simple interpolation", () => {
// 1. 看看是不是一个 {{ 开头的
// 2. 是的话,那么就作为 插值来处理
// 3. 获取内部 message 的内容即可

const ast = baseParse("{{message}}");
const interpolation = ast.children[0];

Expand All @@ -35,20 +60,39 @@ describe("parser", () => {

describe("Element", () => {
test("simple div", () => {
const ast = baseParse("<div></div>");
const ast = baseParse("<div>hello</div>");
const element = ast.children[0];

expect(element).toStrictEqual({
type: NodeTypes.ELEMENT,
tag: "div",
tagType: ElementTypes.ELEMENT,
children: [
{
type: NodeTypes.TEXT,
content: "hello",
},
],
});
});

test("element with interpolation", () => {
const ast = baseParse("<div>{{ msg }}</div>");
const element = ast.children[0];

expect(element).toStrictEqual({
type: NodeTypes.ELEMENT,
tag: "div",
tagType: ElementTypes.ELEMENT,
// TODO 解析 children
// children: [
// {
// type: NodeTypes.TEXT,
// content: "hello",
// },
// ],
children: [
{
type: NodeTypes.INTERPOLATION,
content: {
type: NodeTypes.SIMPLE_EXPRESSION,
content: `msg`,
},
},
],
});
});
});
Expand Down
65 changes: 49 additions & 16 deletions src/compiler-core/src/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,35 +20,52 @@ function createParserContext(content) {
function parseChildren(context) {
console.log("开始解析 children");
const nodes: any = [];
const s = context.source;

let node;
while (!isEnd(context)) {
let node;
const s = context.source;

if (startsWith(s, "{{")) {
// 看看如果是 {{ 开头的话,那么就是一个插值, 那么去解析他
node = parseInterpolation(context);
} else if (s[0] === "<") {
if (s[1] === "/") {
// 处理结束标签
if (/[a-z]/i.test(s[2])) {
// 匹配 </div>
// 需要改变 context.source 的值 -> 也就是需要移动光标
parseTag(context, TagType.End);
// 结束标签就以为这都已经处理完了,所以就可以跳出本次循环了
continue;
}
} else if (/[a-z]/i.test(s[1])) {
node = parseElement(context);
}
}

if (startsWith(s, "{{")) {
// 看看如果是 {{ 开头的话,那么就是一个插值, 那么去解析他
node = parseInterpolation(context);
} else if (s[0] === "<") {
if (/[a-z]/i.test(s[1])) {
node = parseElement(context);
if (!node) {
node = parseText(context);
}
}

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

nodes.push(node);

return nodes;
}

function isEnd(context: any) {
// 看看 context.source 还有没有值
return !context.source;
}

function parseElement(context) {
// 应该如何解析 tag 呢
// <div></div>
// 先解析开始 tag
const element = parseTag(context, TagType.Start);

// TODO 解析 children
const children = parseChildren(context);

// 解析 end tag 是为了检测语法是不是正确的
// 检测是不是和 start tag 一致
if (startsWithEndTagOpen(context.source, element.tag)) {
Expand All @@ -57,6 +74,8 @@ function parseElement(context) {
// TODO 报错
}

element.children = children;

return element;
}

Expand All @@ -72,7 +91,7 @@ function startsWithEndTagOpen(source: string, tag: string) {
function parseTag(context: any, type: TagType): any {
// 发现如果不是 > 的话,那么就把字符都收集起来 ->div
// 正则
const match = /^<\/?([a-z][^\r\n\t\f />]*)/i.exec(context.source);
const match: any = /^<\/?([a-z][^\r\n\t\f />]*)/i.exec(context.source);
const tag = match[1];

// 移动光标
Expand Down Expand Up @@ -133,7 +152,21 @@ function parseInterpolation(context: any) {

function parseText(context): any {
console.log("解析 text", context);
const endIndex = context.source.length;

// endIndex 应该看看有没有对应的 <
// 比如 hello</div>
// 像这种情况下 endIndex 就应该是在 o 这里
// {
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;
}
}

const content = parseTextData(context, endIndex);

return {
Expand Down

0 comments on commit a09c594

Please sign in to comment.