谈谈编译原理和其在WEB开发中的应用2

  上一篇谈到了词法分析,并且给了一小段词法分析上的代码。如果大家对着代码看,可能就会发现我构造了一个对象来对字符串进行读取。

     具体代码是:CharReader src = new CharReader(chars);

     这样子写是为了减少在后面的while语句对字符串数组末尾的判断,起到简化代码的作用;这样的小技巧在写一些比较复杂的算法的时候特别的重要。

     实现完词法分析之后我们就要进行到下一步的语法分析了。教科书的的语法分析一般都是教我们怎么去实现一个抽象语法树,而我个人比较喜欢用所谓的面向对象的方式去实现它,这样子的实现方式代码看起来比较直观,而且扩展也相对容易一些。

  语法分析的前提是我们首先要构建出对应的对象结构。

 

ContractedBlock.gif ExpandedBlockStart.gif ExpressionNode
        private abstract class ExpressionNode
        {
            
private Token _relatedToken;
            
public ExpressionNode(Token relatedToken)
            {
                _relatedToken 
= relatedToken;
            }

            
public Token RelatedToken
            {
                
get { return _relatedToken; }
            }

            
public abstract object Eval(Type targetType);
        }

 

     ExpressionNode是我们的对象结构的最基本的对象,所有的其它的对象都来继承于它。

 

ContractedBlock.gif ExpandedBlockStart.gif ObjectExpression
        private class ObjectExpression : ExpressionNode
        {
            
private IList<NameValue> _elements;

            
public ObjectExpression(Token relatedToken)
                : 
base(relatedToken)
            {
                _elements 
= new List<NameValue>();
            }

            
public IList<NameValue> Elements
            {
                
get { return _elements; }
            }

            
public void Add(string name, ExpressionNode value)
            {
                _elements.Add(
new NameValue(name, value));
            }

            
public override object Eval(Type targetType)
            {
                
            }
        }

 

  ObjectExpression 对象对应的是JSON里的Object对象。

ContractedBlock.gif ExpandedBlockStart.gif ArrayExpression
        private class ArrayExpression : ExpressionNode
        {
            
private IList<ExpressionNode> _elements;
            
public ArrayExpression(Token relatedToken)
                : 
base(relatedToken)
            {
                _elements 
= new List<ExpressionNode>();
            }

            
public IList<ExpressionNode> Elements
            {
                
get { return _elements; }
            }

            
public void Add(ExpressionNode value)
            {
                _elements.Add(value);
            }

            
public override object Eval(Type targetType)
            {
                
            }
        }

 

  ArrayExpression 对象对应的是JSON里的Array对象。

ContractedBlock.gif ExpandedBlockStart.gif NullPrimitive
        private class NullPrimitive : ExpressionNode
        {
            
public NullPrimitive(Token relatedToken)
                : 
base(relatedToken)
            {
            }

            
public override object Eval(Type targetType)
            {
                
if (targetType == null)
                {
                    
return null;
                }
                
else
                {
                    
return ConverFundamentalType(RelatedToken.Data, targetType);
                }
            }
        }

 

  NullPrimitive 对应的是null值。BooleanPrimitive、IntPrimitive、DoublePrimitive、StringPrimitive 所代表的东西一眼就能看出来,不再贴代码,可以自己对着代码去看。

      构建完对象后要进行的工作那就是最终的分析了。JSON的value是最具有普遍性的对象之一,我们就先实现它,代码如下:

 

ContractedBlock.gif ExpandedBlockStart.gif ParseValue
        private ExpressionNode ParseValue(TokenReader src)
        {
            ExpressionNode node;

            
switch (src.CurTok.TokenId)
            {
                
case TokenId.LBracket:
                    {
                        node 
= ParseArray(src);
                        
if (src.CurTok.TokenId == TokenId.RBracket)
                            src.Advance();

                        
break;
                    }
                
case TokenId.LCurly:
                    {
                        node 
= ParseObject(src);
                        src.AssertAndAdvance(TokenId.RCurly);
                        
break;
                    }
                
case TokenId.Ident:
                
case TokenId.String:
                    {
                        node 
= new StringPrimitive(src.CurTok);
                        src.Advance();
                        
break;
                    }
                
case TokenId.Double:
                    {
                        node 
= new DoublePrimitive(src.CurTok);
                        src.Advance();
                        
break;
                    }
                
case TokenId.Int:
                    {
                        node 
= new IntPrimitive(src.CurTok);
                        src.Advance();
                        
break;
                    }
                
case TokenId.True:
                    {
                        node 
= new BooleanPrimitive(true, src.CurTok);
                        src.Advance();
                        
break;
                    }
                
case TokenId.False:
                    {
                        node 
= new BooleanPrimitive(false, src.CurTok);
                        src.Advance();
                        
break;
                    }
                
case TokenId.Null:
                    {
                        node 
= new NullPrimitive(src.CurTok);
                        src.Advance();
                        
break;
                    }
                
default:
                    {
                        
throw new JSONException("Illegal JSON value.");
                    }
            }

            
return node;
        }

 

  其次是对数组的分析:

ContractedBlock.gif ExpandedBlockStart.gif ParseArray
        private ArrayExpression ParseArray(TokenReader src)
        {
            
if (src.CurTok.TokenId == TokenId.LBracket)
                src.Advance();

            ArrayExpression arr 
= new ArrayExpression(src.CurTok);

            
while (src.CurTok.TokenId != TokenId.RBracket && !src.Eof)
            {
                arr.Add(ParseValue(src));

                
if (src.CurTok.TokenId == TokenId.Comma)
                    src.Advance();
            }

            
return arr;
        }

 

  再接着是对Object对象的分析:

 

ContractedBlock.gif ExpandedBlockStart.gif ParseObject
        private ObjectExpression ParseObject(TokenReader src)
        {
            src.AssertAndAdvance(TokenId.LCurly);
            ObjectExpression o 
= new ObjectExpression(src.CurTok);

            
string name = string.Empty;

            
while (src.CurTok.TokenId != TokenId.RCurly && !src.Eof)
            {
                
switch (src.CurTok.TokenId)
                {
                    
case TokenId.Ident:
                    
case TokenId.String:
                        {
                            name 
= src.CurTok.Data;
                            src.Advance();
                            
break;
                        }
                    
case TokenId.Colon:
                        {
                            src.Advance();
                            o.Add(name, ParseValue(src));

                            
if (src.CurTok.TokenId == TokenId.Comma)
                                src.Advance();

                            
break;
                        }
                    
default:
                        {
                            
throw new JSONException("Illegal JSON object.");
                        }
                }
            }

            
return o;
        }

 

  这样子整个语法分析的过程就已经完成,大家可能认为是因为json比较简单才可以用这样的方式来实现,其实不是,目前比较流行的编译器我们也可以用这样的方式来实现了,只是其结构会相对来说比较复杂一些而已。

下一篇:

谈谈编译原理和其在WEB开发中的应用3

posted on 2009-01-22 15:28 黄尚 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/afxcn/archive/2009/01/22/1379932.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值