所谓的状态机实质其实很很简单,其存在的目的也是把大量复杂的处理分散,使处理变得简单化一些。状态机只有一个当前状态,并且在当前状态下根据输入进行处理,然后再决定是否改变当前状态,然后再处理下一个输入,如此往复直到所有输入结束。
  所以,相同的输入在不同的当前状态下的处理是不一样的,以字符串的处理为例,我们来看看怎么处理下面这条语句:

str="123\"abc";

  我们需要得到的结果序列应该是:
    标识符str,标点符号=,字面量"123\"abc",标点符号;

  首先我们会建立起几种处理的状态(这里只是针对这个列子,实际开发的状态比这多得多T_T):
    a.一般状态处理;
    b.标识符状态处理;
    c.标点符号状态处理;
    d.双引号字符串字面量状态处理;
    e.双引号字符串字面量遇到\符号时的状态处理;

  建立完成状态处理方法后,我们将语句作为字符串输入流,一个个字符地进行输入处理:
    1)输入s,首先进入状态a进行一般处理,判断出该字符符合js标识符规则,记录当前字符,将当前状态转换为状态b;
    2)继续输入下一个字符t,进入状态b进行字符处理,字符t符合js标识符规则,记录当前字符,并且当前状态还是状态b,不发生改变;
    3)继续输入下一个字符r,进入状态b进行字符处理,字符r符合js标识符规则,记录当前字符,并且当前状态还是状态b,不发生改变;
    4)继续输入下一个字符=,进入状态b进行字符处理,字符=不符合当前状态需要的js标识符规则,于是保存之前记录的字符集,并标记为id类型,即["id","str"]。再将当前状态转换为状态a;
    5)在当前状态a下继续输入刚才未处理的字符=,判断出其符合js标点符号规则,记录当前字符,并将当前状态转换为状态c;
    6)继续输入下一个字符",进入状态c进行标点符号处理,判读出字符"并不符合标点符号规则,于是保存记录的字符集,并标记为标点符号类型["pun","="]。再将当前状态转换为状态a;
    7)在当前状态a下继续输入刚才未处理的字符",判断出其符合js字符串字面量规则,记录当前字符,并将当前状态转换为状态d;
    8)继续输入下一个字符,在状态d下处理,符合js字符串字面量规则,记录当前字符;
    9)继续输入下一个字符,在状态d下处理,符合js字符串字面量规则,记录当前字符;
    10)继续输入下一个字符,在状态d下处理,符合js字符串字面量规则,记录当前字符;
    11)继续输入下一个字符\,在状态d下处理,\字符在状态d里会触发状态转换,记录当前字符,将当前状态转换为状态e;
    12)继续输入下一个字符",在状态e下处理,判断符合当前的处理规则,记录当前字符",将状态转换为状态d;
    13)继续输入下一个字符a,在状态d下处理,符合js字符串字面量规则,记录当前字符;
    14)继续输入下一个字符b,在状态d下处理,符合js字符串字面量规则,记录当前字符;
    15)继续输入下一个字符c,在状态d下处理,符合js字符串字面量规则,记录当前字符;
    16) 继续输入下一个字符",在状态d下处理,状态d接收到"时就可以判断出当前状态结束了,于是保存当前的记录的字符集,并标记为字符串字面量类型["str","\"123\\\"abc\""],再将当前状态转换为状态a;
    17)继续输入下一个字符;,在状态a下处理,判断出其符合js标点符号规则,记录当前字符,将状态转换为状态c;
    18)现在所有字符都扫描完了,我们可以人为加一个终止符,当再读到最后的终止符时,判断出不符合标点符号规则,保存字符集,标记为标点符号类型["pun",";"];
    19)处理结束。

  于是我们就得到了我们需要的词法序列:
    [["id","str"], ["pun","="], ["str","\"123\\\"abc\""], ["pun",";""]]

  简化版的代码看起来大概就是这个样子:  

   var Reader= function(str){
var index=0;
var stream=str; stream +=" "; var me={
get char(){
return stream[index];
}, get length(){
return stream.length;
}, get stream(){
return stream;
}, get pchar(){
return stream[index-1];
}, get nchar(){
return stream[index+1];
}, get eof(){
return index === stream.length;
}, next : function(){
index++;
}, prev : function(){
index--;
} }; return me;
}; var statement="str=\"123\\\"abc\";";
var reader=Reader(statement);
var l=reader.length;
var i;
var newState;
var state;
var tokenList=[];
var word=""; var punctuatorList=["{", "}", "(", ")", "[", "]", ".", ";", ",", "<", ">", "<=",
">=", "==", "!=", "===", "!==", "+", "-", "*", "%", "++", "--",
"<<", ">>", ">>>", "&", "|", "^", "!", "~", "&&", "||", "?", ":",
"=", "+=", "-=", "*=", "%=", "<<=", ">>=", ">>>=", "&=", "|=", "^="]; function checkUnicodeLetter(c){
return c.match(/[a-z]/i); //囧oz
} function checkUnicodeNumber(c){
return (c.charCodeAt() >= "\u0030".charCodeAt() && c.charCodeAt() <= "\u0039".charCodeAt())
|| (c.charCodeAt() >= "\u1D7CE".charCodeAt() && c.charCodeAt() <= "\u1D7FF".charCodeAt()); } function emitToken(type){
tokenList.push([type, word]);
word="";
} function dataState(c){
if(punctuatorList.indexOf(c) > -1){
word=c;
return punctuatorState; }else if(checkUnicodeLetter(c) || c==="_" || c==="$" || c==="\\"){
word=c;
return identifierState; }else if(c==="\""){
word=c;
return doubleStringLiteralState;
}
} function punctuatorState(c){
if(punctuatorList.indexOf(word+c) === -1){
emitToken("pun");
reader.prev();
return dataState;
}else{
word += c;
}
} function identifierState(c){
if(checkUnicodeLetter(c) || checkUnicodeNumber(c)){
word += c; }else{ emitToken("id");
reader.prev();
return dataState;
}
} function doubleStringLiteralState(c){
if(c==="\\"){
word += c;
return doubleStringLiteralEscapeSequenceState; }else if(c==="\""){
word += c;
emitToken("str");
return dataState;
}else{
word += c;
}
}
function doubleStringLiteralEscapeSequenceState(c){
word+=c;
return doubleStringLiteralState;
} state=dataState;
while(!reader.eof){
newState=state(reader.char);
newState && (state=newState);
reader.next();
} alert(JSON.stringify(tokenList));

  这就是状态机的运作方式,不过要写全各种状态这种事真特么不是人干的~~

状态机——Javascript词法扫描示例的更多相关文章

  1. JavaScript 词法 All In One

    JavaScript 词法 All In One JavaScript 词法 这部分描述了JavaScript 的词法(lexical grammar). ECMAScript 源码文本会被从左到右扫 ...

  2. XAMARIN ANDROID 二维码扫描示例

    现在二维码的应用越来越普及,二维码扫描也成为手机应用程序的必备功能了.本文将基于 Xamarin.Android 平台使用 ZXing.Net.Mobile  做一个简单的 Android 条码扫描示 ...

  3. Javascript调用ActiveX示例

      Javascript调用ActiveX示例   写一个ActiveX控件比如叫做MyNameSpace.SecreteInfo,安装在客户机器上,这样可以通过c++获取到机器的几乎任何信息. 在网 ...

  4. 第二章:Javascript词法结构

    编程语言的词法结构是一套基础性的规则,用来描述你如何编写这门语言.作为语法的基础,它规定了变量名是怎么样的,如何写注释,以及语句之间是如何区分的.本节用很短的篇幅来介绍javascript的词法结构. ...

  5. 网易JS面试题与Javascript词法作用域说明

    调用对象位于作用域链的前端,局部变量(在函数内部用var声明的变量).函数参数及Arguments对象都在函数内的作用域中--这意味着它们隐藏了作用域链更上层的任何同名的属性. 2010年9月14日, ...

  6. JavaScript 词法句法

    JavaScript 中的几个重要概念 JavaScript 遵循 ECMA-262 规范,目前其最新版是 ECMAScript 2018,而获得所有主流浏览器完全支持的则是 ECMAScript 5 ...

  7. 【译】Spring 4 自动装配、自动检测、组件扫描示例

    前言 译文链接:http://websystique.com/spring/spring-auto-detection-autowire-component-scanning-example-with ...

  8. 将百度坐标转换的javascript api官方示例改写成传统的回调函数形式

    改写前: 百度地图中坐标转换的JavaScript API示例官方示例如下: var points = [new BMap.Point(116.3786889372559,39.90762965106 ...

  9. javascript 词法结构小结

    作为一名前端程序员,自然学习了一些框架,但是学的越多越发现自己基础的不足,于是想系统的学习一下js基础,然后把它记录下来. 如其他编程语言一样,词法结构是一门语言的基础,它规定了诸如如何给变量起名字. ...

随机推荐

  1. 修改mysql默认字符集的方案

    mysql默认字符集能否进行修改呢?答案是肯定的,下面就将教您两种修改mysql默认字符集的方法,希望对您学习mysql默认字符集方面能有所启迪. (1) 最简单的修改方法,就是修改mysql的my. ...

  2. oc-基本语法

    一.第一个oc程序 #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { NSLog(@& ...

  3. java Timer(定时调用、实现固定时间执行)

    最近需要用到定时调用的功能.可以通过java的Timer类来进行定时调用,下面是有关Timer的一些相关知识. 其实就Timer来讲就是一个调度器,而TimerTask呢只是一个实现了run方法的一个 ...

  4. linux文件压缩与打包

    在linux中常见的压缩命令 首先,在linux中压缩文件的扩展名大多是 *.gz gzip程序压缩的文件 *.bz2 bzip2程序压缩的文件 *.tar tar程序打包的数据,并没有压缩过 *.t ...

  5. c++ Windows Socket实现最简单的C/S网络通信(TCP)

    1.服务器端代码: #include<iostream> #include<WinSock2.h> #pragma comment(lib, "ws2_32.lib& ...

  6. SQL SERVER 2012 使用订阅发布同步数据库

    软件做大了,客户就多了,一个数据库服务器是远远不够的,当有一台数据服务器卦掉,那整个系统就会崩溃,所以必须考虑到数据库的自动同步与备份,当一台数据库服务 器宕机,自然就有用一台数据服务器启动起来保证整 ...

  7. uva 839 not so mobile——yhx

    Not so Mobile  Before being an ubiquous communications gadget, a mobile was just a structure made of ...

  8. 【Android 基础】Animation 动画介绍和实现

    在前面PopupWindow 实现显示仿腾讯新闻底部弹出菜单有用到Animation动画效果来实现菜单的显示和隐藏,本文就来介绍下吧. 1.Animation 动画类型 Android的animati ...

  9. UVA-10652 (凸包)

    题意: 给n个矩形,问包含这些矩形的尽量小的凸多边形的面积是多少; 思路: 由于给的矩形的形式是给出了中心的坐标,长和宽以及旋转的角度,所以先转换成四个点的坐标,然后求一遍凸包就好了,第一次写凸包,代 ...

  10. poj1274 The Perfect Stall (二分最大匹配)

    Description Farmer John completed his new barn just last week, complete with all the latest milking ...