001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.transformer.cfml.expression;
020
021import lucee.runtime.exp.TemplateException;
022import lucee.transformer.bytecode.Page;
023import lucee.transformer.bytecode.Position;
024import lucee.transformer.bytecode.expression.ExprString;
025import lucee.transformer.bytecode.expression.Expression;
026import lucee.transformer.bytecode.literal.LitString;
027import lucee.transformer.cfml.ExprTransformer;
028import lucee.transformer.cfml.TransfomerSettings;
029import lucee.transformer.cfml.evaluator.EvaluatorPool;
030import lucee.transformer.library.function.FunctionLib;
031import lucee.transformer.library.tag.TagLib;
032import lucee.transformer.library.tag.TagLibTag;
033import lucee.transformer.util.CFMLString;
034
035/**
036 * Zum lesen von Attributen bei dem CFML expressions nicht geparst werden sollen (cfloop condition) 
037 */
038public final class SimpleExprTransformer implements ExprTransformer {
039        
040        private char specialChar;
041
042        public SimpleExprTransformer(char specialChar) {
043                this.specialChar=specialChar;
044        }
045
046        @Override
047        public Expression transformAsString(Page page,EvaluatorPool ep,TagLib[][] tld,FunctionLib[] fld,TagLibTag[] scriptTags, CFMLString cfml, TransfomerSettings settings,boolean allowLowerThan) throws TemplateException {
048                return transform(page,ep,tld,fld,scriptTags, cfml,settings);
049        }
050        
051        @Override
052        public Expression transform(Page page,EvaluatorPool ep,TagLib[][] tld,FunctionLib[] fld,TagLibTag[] scriptTags, CFMLString cfml, TransfomerSettings settings) throws TemplateException {
053                        Expression expr=null;
054                        // String
055                                if((expr=string(cfml))!=null) {
056                                        return expr;
057                                }
058                        // Simple
059                                return simple(cfml);
060        }
061        /**
062         * Liest den String ein
063         * @return Element 
064         * @throws TemplateException
065         */
066        public Expression string(CFMLString cfml)
067                throws TemplateException {
068                cfml.removeSpace();
069                char quoter=cfml.getCurrentLower();
070                if(quoter!='"' && quoter!='\'')
071                        return null;
072                StringBuffer str=new StringBuffer();
073                boolean insideSpecial=false;
074        
075                Position line = cfml.getPosition();
076                while(cfml.hasNext()) {
077                        cfml.next();
078                        // check special
079                        if(cfml.isCurrent(specialChar)) {
080                                insideSpecial=!insideSpecial;
081                                str.append(specialChar);
082                                                        
083                        }
084                        // check quoter
085                        else if(!insideSpecial && cfml.isCurrent(quoter)) {
086                                // Ecaped sharp
087                                if(cfml.isNext(quoter)){
088                                        cfml.next();
089                                        str.append(quoter);
090                                }
091                                // finsish
092                                else {
093                                        break;
094                                }                               
095                        }
096                        // all other character
097                        else {
098                                str.append(cfml.getCurrent());
099                        }
100                }               
101
102
103                if(!cfml.forwardIfCurrent(quoter))
104                        throw new TemplateException(cfml,"Invalid Syntax Closing ["+quoter+"] not found");
105        
106                ExprString rtn = LitString.toExprString(str.toString(),line,cfml.getPosition());
107                cfml.removeSpace();
108                return rtn;
109        }
110        
111        /**
112         * Liest ein
113         * @return Element
114         * @throws TemplateException
115         */
116        public Expression simple(CFMLString cfml) throws TemplateException {
117                StringBuffer sb=new StringBuffer();
118                Position line = cfml.getPosition();
119                while(cfml.isValidIndex()) {
120                        if(cfml.isCurrent(' ') || cfml.isCurrent('>') || cfml.isCurrent("/>")) break;
121                        else if(cfml.isCurrent('"') || cfml.isCurrent('#') || cfml.isCurrent('\'')) {
122                                throw new TemplateException(cfml,"simple attribute value can't contain ["+cfml.getCurrent()+"]");
123                        }
124                        else sb.append(cfml.getCurrent());
125                        cfml.next();
126                }
127                cfml.removeSpace();
128                
129                return LitString.toExprString(sb.toString(),line,cfml.getPosition());
130        }
131        
132
133}