Esempio n. 1
0
function js_beautify($js_source_text, $tab_size = 4)
{
    global $output, $token_text, $last_type, $last_text, $in, $ins, $indent, $tab_string;
    global $input, $input_length;
    $tab_string = str_repeat(' ', $tab_size);
    $input = $js_source_text;
    $input_length = strlen($input);
    $last_word = '';
    // last TK_WORD passed
    $last_type = TK_START_EXPR;
    // last token type
    $last_text = '';
    // last token text
    $output = '';
    // words which should always start on new line.
    // simple hack for cases when lines aren't ending with semicolon.
    // feel free to tell me about the ones that need to be added.
    $line_starters = explode(',', 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function');
    // states showing if we are currently in expression (i.e. "if" case) - IN_EXPR, or in usual block (like, procedure), IN_BLOCK.
    // some formatting depends on that.
    $in = IN_BLOCK;
    $ins = array($in);
    $indent = 0;
    $pos = 0;
    // parser position
    $in_case = false;
    // flag for parser that case/default has been processed, and next colon needs special attention
    while (true) {
        list($token_text, $token_type) = get_next_token($pos);
        if ($token_type == TK_EOF) {
            break;
        }
        // $output .= " [$token_type:$last_type]";
        switch ($token_type) {
            case TK_START_EXPR:
                in(IN_EXPR);
                if ($last_type == TK_END_EXPR or $last_type == TK_START_EXPR) {
                    // do nothing on (( and )( and ][ and ]( ..
                } elseif ($last_type != TK_WORD and $last_type != TK_OPERATOR) {
                    space();
                } elseif (in_array($last_word, $line_starters) and $last_word != 'function') {
                    space();
                }
                token();
                break;
            case TK_END_EXPR:
                token();
                in_pop();
                break;
            case TK_START_BLOCK:
                in(IN_BLOCK);
                if ($last_type != TK_OPERATOR and $last_type != TK_START_EXPR) {
                    if ($last_type == TK_START_BLOCK) {
                        nl();
                    } else {
                        space();
                    }
                }
                token();
                indent();
                break;
            case TK_END_BLOCK:
                if ($last_type == TK_END_EXPR) {
                    unindent();
                    nl();
                } elseif ($last_type == TK_END_BLOCK) {
                    unindent();
                    nl();
                } elseif ($last_type == TK_START_BLOCK) {
                    // nothing
                    unindent();
                } else {
                    unindent();
                    nl();
                }
                token();
                in_pop();
                break;
            case TK_WORD:
                if ($token_text == 'case' or $token_text == 'default') {
                    if ($last_text == ':') {
                        // switch cases following one another
                        remove_indent();
                    } else {
                        $indent--;
                        nl();
                        $indent++;
                    }
                    token();
                    $in_case = true;
                    break;
                }
                $prefix = PRINT_NONE;
                if ($last_type == TK_END_BLOCK) {
                    if (!in_array($token_text, array('else', 'catch', 'finally'))) {
                        $prefix = PRINT_NL;
                    } else {
                        $prefix = PRINT_SPACE;
                        space();
                    }
                } elseif ($last_type == TK_END_COMMAND && $in == IN_BLOCK) {
                    $prefix = PRINT_NL;
                } elseif ($last_type == TK_END_COMMAND && $in == IN_EXPR) {
                    $prefix = PRINT_SPACE;
                } elseif ($last_type == TK_WORD) {
                    if ($last_word == 'else') {
                        // else if
                        $prefix = PRINT_SPACE;
                    } else {
                        $prefix = PRINT_SPACE;
                    }
                } elseif ($last_type == TK_START_BLOCK) {
                    $prefix = PRINT_NL;
                } elseif ($last_type == TK_END_EXPR) {
                    space();
                }
                if (in_array($token_text, $line_starters) or $prefix == PRINT_NL) {
                    if ($last_text == 'else') {
                        // no need to force newline on else break
                        // DONOTHING
                        space();
                    } elseif (($last_type == TK_START_EXPR or $last_text == '=') and $token_text == 'function') {
                        // no need to force newline on 'function': (function
                        // DONOTHING
                    } elseif ($last_type == TK_WORD and ($last_text == 'return' or $last_text == 'throw')) {
                        // no newline between 'return nnn'
                        space();
                    } else {
                        if ($last_type != TK_END_EXPR) {
                            if (($last_type != TK_START_EXPR or $token_text != 'var') and $last_text != ':') {
                                // no need to force newline on 'var': for (var x = 0...)
                                if ($token_text == 'if' and $last_type == TK_WORD and $last_word == 'else') {
                                    // no newline for } else if {
                                    space();
                                } else {
                                    nl();
                                }
                            }
                        }
                    }
                } elseif ($prefix == PRINT_SPACE) {
                    space();
                }
                token();
                $last_word = $token_text;
                break;
            case TK_END_COMMAND:
                token();
                break;
            case TK_STRING:
                if ($last_type == TK_START_BLOCK or $last_type == TK_END_BLOCK) {
                    nl();
                } elseif ($last_type == TK_WORD) {
                    space();
                }
                token();
                break;
            case TK_OPERATOR:
                $start_delim = true;
                $end_delim = true;
                if ($token_text == ':' and $in_case) {
                    token();
                    // colon really asks for separate treatment
                    nl();
                    $expecting_case = false;
                    break;
                }
                $in_case = false;
                if ($token_text == ',') {
                    if ($last_type == TK_END_BLOCK) {
                        token();
                        nl();
                    } else {
                        if ($in == IN_BLOCK) {
                            token();
                            nl();
                        } else {
                            token();
                            space();
                        }
                    }
                    break;
                } elseif ($token_text == '--' or $token_text == '++') {
                    // unary operators special case
                    if ($last_text == ';') {
                        // space for (;; ++i)
                        $start_delim = true;
                        $end_delim = false;
                    } else {
                        $start_delim = false;
                        $end_delim = false;
                    }
                } elseif ($token_text == '!' and $last_type == TK_START_EXPR) {
                    // special case handling: if (!a)
                    $start_delim = false;
                    $end_delim = false;
                } elseif ($last_type == TK_OPERATOR) {
                    $start_delim = false;
                    $end_delim = false;
                } elseif ($last_type == TK_END_EXPR) {
                    $start_delim = true;
                    $end_delim = true;
                } elseif ($token_text == '.') {
                    // decimal digits or object.property
                    $start_delim = false;
                    $end_delim = false;
                } elseif ($token_text == ':') {
                    // zz: xx
                    // can't differentiate ternary op, so for now it's a ? b: c; without space before colon
                    $start_delim = false;
                }
                if ($start_delim) {
                    space();
                }
                token();
                if ($end_delim) {
                    space();
                }
                break;
            case TK_BLOCK_COMMENT:
                nl();
                token();
                nl();
                break;
            case TK_COMMENT:
                //if ($last_type != TK_COMMENT) {
                nl();
                //}
                token();
                nl();
                break;
            case TK_UNKNOWN:
                token();
                break;
        }
        if ($token_type != TK_COMMENT) {
            $last_type = $token_type;
            $last_text = $token_text;
        }
    }
    // clean empty lines from redundant spaces
    $output = preg_replace('/^ +$/m', '', $output);
    return $output;
}
Esempio n. 2
0
 function install_rule(lime $lime, $lhs)
 {
     // This is the part that has to break the rule into subrules if necessary.
     $rhs = $this->rhs;
     // First, make sure this thing is well-formed.
     if (!end($rhs) instanceof lime_action) {
         $rhs[] = new lime_action('', null);
     }
     $prec_sym = null;
     if ($this->prec_glyph) {
         $prec_sym = $lime->sym($this->prec_glyph);
     }
     // Now, split it into chunks based on the actions.
     $lang = $lime->language();
     $result_code = $lang->default_result();
     $look = -1;
     $subrule = array();
     $subsymbol = '';
     $preamble = '';
     while ($rhs) {
         $it = array_shift($rhs);
         ++$look;
         if ($it instanceof lime_glyph) {
             $subrule[] = $it->data;
         } elseif ($it instanceof lime_action) {
             $code = unindent($it->data);
             // It's an action.
             // Is it the last one?
             if ($rhs) {
                 // no.
                 $subsymbol = $lime->trump_up_bogus_lhs($lhs);
                 $action = $lang->default_result() . $preamble . $code;
                 $lime->add_raw_rule($subsymbol, $subrule, $action, $look, false, $prec_sym);
                 $subrule = array($subsymbol);
             } else {
                 // yes.
                 $action = $result_code . $preamble . $code;
                 $lime->add_raw_rule($lhs, $subrule, $action, $look, true, $prec_sym);
             }
         } else {
             impossible();
         }
         if ($it->name == '$') {
             $result_code = $lang->result_pos($look);
         } elseif ($it->name) {
             $preamble .= $lang->bind($it->name, $look);
         }
     }
 }