浏览器是如何读懂HTML的-词法分析

什么是词法分析

词法分析:根据词法规则,识别出字符序列 中的单词 ,并输出单词序列。
HTML词法分析就是根据HTML词法规则,识别出HTML文档字符流中的token,并输出token序列。

HTML的token有哪些

为了简化分析,本文使用最简单的情况进行描述:一个HTML元素由开始标签、元素内容和结束标签三部分组成。

<p>
    hello world
</p>

例如上文中,包含的token有:

  • "<p>"表示:p元素的开始标签;
  • "hello world"表示:p元素的内容;
  • "</p>"表示:p元素的结束标签;

为什么需要词法解析

img

HTML文档字符流经过词法分析得到的token序列,为后续的语法分析(DOM树构建)提供了原材料。

怎么实现词法解析

<p>hello world</p>

从左往右扫描字符序列,根据HTML词法规则,对以上p元素进行分析:

  1. 读到"<“字符,表示开始标签或结束标签的开始。读到"p"字符,表示开始标签p,读到”>"字符表示标签结束。这样就得到token 开始标签p

  2. ">“字符后面读到字符"h"表示 元素内容,直到遇到”<"字符,元素内容结束。这样就得到token 元素内容hello world

  3. 读到"<“字符,表示开始标签或结束标签的开始。读到”/“字符,表示结束标签的开始。读到"p"字符,表示结束标签p,读到”>"字符表示标签结束。这样就得到token 结束标签p

总结:按顺序扫描字符序列,然后根据HTML词法规则对输入每个字符进行判断,并且每次判断都跟当前的状态有关,最终识别出每个token并输出相应token的描述对象。

有限状态机

有限状态机通常由多个状态组成,每个状态会对输入事件进行判断并执行对应动作,然后转移到下一个状态

根据上面的概念,我们可以把词法分析的过程用有限状态机来实现:

把每个HTML token的特征看成是一个状态,每个状态会对输入的字符进行判断并输出token,最后根据词法规则转移到下一个状态。

img

<p>hello world</p>

用有限状态机模式解析上面的p元素:

  1. 初始状态为“data state”,当遇到“<”字符,状态变为“tag open state”。

  2. “tag open state”状态,当遇到a-z字符(这里为p)将创建开始开始标签token,状态变为“tag name state”。

  3. “tag name state”状态,当遇到“>”,则输出了一个token。重新回到“data state”状态。

  4. “data state”状态,当遇到a-z字符,则输出 元素内容token,直到遇到“<”(这里会创建字符hello world),状态变为“tag open state”。

  5. “tag open state”状态,当遇到“/”字符将创建结束标签token,状态变为“tag name state”。执行上面第三步骤,创建</p>标签。

代码实现

将每个状态封装成状态函数,在函数中对输入字符进行判断,然后返回下一个状态函数,并通过emitToken 函数输出解析好的 token。

// 初始data状态
var data = function(c){
    if(c=="<") {
        return tagOpen;
    }
    else if(c==EOF) {
        emitToken(EOF);
        return data;
    }
    else {
        emitToken(new TextToken(c));
        return data;
    }
};
// 标签开始状态
var tagOpen = function tagOpenState(c){
    if(c=="/") {
        return endTagOpen;
    }
    if(c.match(/[a-z]/)) {
        // 创建开始标签符号
        token = new StartTagToken();
        token.name = c;
        return tagName;
    }
};
// 标签符号状态
var tagName = function tagNameState(c){
    if(c==">") {
        // 输出一个token
        emitToken(token);
        return data;
    }else if(c.match(/[a-z]/)) {
        token.name += c;
        return tagName;
    }
};
// 结束标签状态
var endTagOpen = function endTagOpenState(c){
    if(c.match(/[a-z]/)) {
        // 创建结束标签符号
        token = new EndTagToken();
        token.name = c;
        return tagName;
    }
};


var state = data;
var char = "";
while(char = getInput())
    state = state(char);  // 通过状态转移函数,连接各个状态并输出对应的token
小C语言的词法分析程序主要用于对源程序进行分析,将源程序中的各种单词进行分类提取。根据引用和引用中提供的信息,词法分析程序可以将源程序中的关键字、自定义标识符、整数、界符和运算符进行分析和提取。 关键字包括main、if、else、for、while和int等。自定义标识符是除了关键字之外的标识符。整数是无符号的整数。界符包括大括号{}、小括号()、逗号,和分号;。运算符包括等号=、减号-、乘号*、除号/、小于号<、左移运算符<<、大于等于>=、等于==和不等于!=等。 在编写词法分析程序时,可以使用字符串处理函数,例如gets、strcpy和strcmp等,来从键盘获取源程序输入,并对字符串进行复制和比较操作,以便进行单词的分类和提取。 通过词法分析程序,可以将源程序中的各种单词按照其类型进行分类,并提取出来,从而为后续的语法分析和语义分析提供基础。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [小C语言--词法分析程序](https://blog.csdn.net/wq3699823668/article/details/100599572)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [A - 小C语言--词法分析程序](https://blog.csdn.net/Mercury_Lc/article/details/108685127)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [词法分析源程序(c语言编写)](https://download.csdn.net/download/wviyong/1797051)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值