(2016.6.24)
蓦然发现,我需要支持json格式!字典风格数组就是json object风格,object字面量还是json object风格,所以我的语法分析器必须原生支持json格式!我的天,又要加不少东西了。各种语法糖支持,都是个复杂的状态机,这意味着我又要人肉做状态分析和转移了!
其实我很不喜欢写状态机啊摔!
这就是我所不喜欢的业务逻辑部分!
结果读了很久的json解析器源码,然后开始写自己的json解析器。写起来还是有些痛苦,为了将Array的元素存到Stack上纠结了很久,最后还是决定存三种数据,Dictionary,Array和JsExpression,没办法,Array和Dictionary如果写成自定义结构各种麻烦,涉及一些类型转换问题。没办法只有用C#原生数据结构了。这样在代码解释核心处还需要特殊处理,因为C#数据结构本来不应该出现在js的数据结构JsExpression里,但是又没有办法,唯一的办法是我要封装出同样的数据结构,并自定义解释规则,这样又麻烦又低效,还不如特殊处理呢。
因为报错信息太不明确,没办法只好回去改词法分析器,给Token加了行号和列号,又把字符指示器自增操作提到了前边,优化了一下代码。这么一改可不得了,搞得源代码code字符串越界了,My God!查了很久才发现是要把字符指示器自增操作放最后才可以,但是我没有这么做,这样要改很多处。将while循环条件改了一下顺利解决。
while(count < code.Length)
改成了
while(count < code.Length-1)
真是一不小心就改错。
为了json解析器,顺便添加了Bool Token类型和Null Token 类型,这两个以前是在解释器里直接解释的,现在为了类型匹配,不得不正式提取出来。结果导致了一些小问题,因为以前bool类型和null类型直接被当做Identity处理的。debug一下顺利解决。
在ParseProgram里面,在
case TokenType.IDENTIFY:
上边加了
case TokenType.TRUE:
case TokenType.FALSE:
case TokenType.NULL:
case TokenType.UNDEFINED:
接下来可以集中精力解决json解析问题了。一旦解决这个问题,就实现了Array的基本类型,字典风格Array类型和Object字面量类型。目前写好的部分:
public static JsExpression ParseDictArray(List<Token> list)
{
Stack<object> stack = new Stack<object>();
JsExpression arrayExp = new JsExpression(list[index].name, current);//[ | {
current = arrayExp;
int state =
(int)ArrayState.State_Expect_Begin_Array | //[
(int)ArrayState.State_Expect_Begin_Object | //{
(int)ArrayState.State_Expect_Single_Value; //num|string|bool|null
while (list[index].type != TokenType.SemiColon)
{
index++;
switch (list[index].type)
{
case TokenType.NUMBER: //num
if(hasState(state,ArrayState.State_Expect_Single_Value))
{
}
if (hasState(state, ArrayState.State_Expect_Begin_Object))
{
}
if(hasState(state,ArrayState.State_Expect_Begin_Array))
{
}
break;
case TokenType.STRING:
if (hasState(state, ArrayState.State_Expect_Single_Value))
{
stack.Push(list[index]);
state = (int)ArrayState.State_Expect_End_Document;
continue;
}
else if(hasState(state,ArrayState.State_Expect_Object_Key))
{
stack.Push(list[index]);
state = (int)ArrayState.State_Expect_Colon;
continue;
}
else if (hasState(state, ArrayState.State_Expect_Object_Value))
{
JsExpression key = stack.Pop() as JsExpression;
(stack.Peek() as Dictionary<JsExpression,JsExpression>)
.Add(key,new JsExpression(list[index].name,current));
state = (int)ArrayState.State_Expect_Comma |
(int)ArrayState.State_Expect_End_Object;
}
else if (hasState(state, ArrayState.State_Expect_Array_Value))
{
JsExpression val = new JsExpression(list[index].name, current);
(stack.Peek() as List<JsExpression>).Add(val);
state = (int)ArrayState.State_Expect_Comma |
(int)ArrayState.State_Expect_End_Array
;
}
break;
case TokenType.TRUE:
case TokenType.FALSE: //bool
break;
case TokenType.NULL: // null
break;
case TokenType.IDENTIFY: //identy
break;
case TokenType.OpenBrace: //{
break;
case TokenType.OpenBracket: //[
if(hasState(state,ArrayState.State_Expect_Begin_Array))
{
stack.Push(new List<JsExpression>());
//STATUS_EXPECT_ARRAY_VALUE | STATUS_EXPECT_BEGIN_OBJECT | STATUS_EXPECT_BEGIN_ARRAY | STATUS_EXPECT_END_ARRAY;
state = (int)ArrayState.State_Expect_Array_Value |
(int)ArrayState.State_Expect_Begin_Object |
(int)ArrayState.State_Expect_Begin_Array |
(int)ArrayState.State_Expect_End_Array;
continue;
}
break;
case TokenType.CloseBrace: //}
break;
case TokenType.CloseBracket: //]
break;
case TokenType.COLON: //:
break;
case TokenType.COMMA: //,
break;
default: // end of array or dict
break;
}
}
return null;
}








网友评论