langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
changeset 32453 8eebd1f0b8ea
parent 31941 8a56abc0778a
child 33361 1c96344ecd49
equal deleted inserted replaced
32341:3c9f5bd909ae 32453:8eebd1f0b8ea
    24  */
    24  */
    25 
    25 
    26 package com.sun.tools.javac.parser;
    26 package com.sun.tools.javac.parser;
    27 
    27 
    28 import java.util.*;
    28 import java.util.*;
       
    29 import java.util.stream.Collectors;
    29 
    30 
    30 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
    31 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
    31 
    32 
    32 import com.sun.tools.javac.code.*;
    33 import com.sun.tools.javac.code.*;
    33 import com.sun.tools.javac.parser.Tokens.*;
    34 import com.sun.tools.javac.parser.Tokens.*;
   508     /** Diagnose a modifier flag from the set, if any. */
   509     /** Diagnose a modifier flag from the set, if any. */
   509     protected void checkNoMods(long mods) {
   510     protected void checkNoMods(long mods) {
   510         if (mods != 0) {
   511         if (mods != 0) {
   511             long lowestMod = mods & -mods;
   512             long lowestMod = mods & -mods;
   512             error(token.pos, "mod.not.allowed.here",
   513             error(token.pos, "mod.not.allowed.here",
   513                       Flags.asFlagSet(lowestMod));
   514                     Flags.asFlagSet(lowestMod));
   514         }
   515         }
   515     }
   516     }
   516 
   517 
   517 /* ---------- doc comments --------- */
   518 /* ---------- doc comments --------- */
   518 
   519 
   944         }
   945         }
   945         Assert.check(top == 0);
   946         Assert.check(top == 0);
   946         t = odStack[0];
   947         t = odStack[0];
   947 
   948 
   948         if (t.hasTag(JCTree.Tag.PLUS)) {
   949         if (t.hasTag(JCTree.Tag.PLUS)) {
   949             StringBuilder buf = foldStrings(t);
   950             t = foldStrings(t);
   950             if (buf != null) {
       
   951                 t = toP(F.at(startPos).Literal(TypeTag.CLASS, buf.toString()));
       
   952             }
       
   953         }
   951         }
   954 
   952 
   955         odStackSupply.add(odStack);
   953         odStackSupply.add(odStack);
   956         opStackSupply.add(opStack);
   954         opStackSupply.add(opStack);
   957         return t;
   955         return t;
   971             }
   969             }
   972         }
   970         }
   973         /** If tree is a concatenation of string literals, replace it
   971         /** If tree is a concatenation of string literals, replace it
   974          *  by a single literal representing the concatenated string.
   972          *  by a single literal representing the concatenated string.
   975          */
   973          */
   976         protected StringBuilder foldStrings(JCTree tree) {
   974         protected JCExpression foldStrings(JCExpression tree) {
   977             if (!allowStringFolding)
   975             if (!allowStringFolding)
   978                 return null;
   976                 return null;
   979             List<String> buf = List.nil();
   977             ListBuffer<JCExpression> opStack = new ListBuffer<>();
       
   978             ListBuffer<JCLiteral> litBuf = new ListBuffer<>();
       
   979             boolean needsFolding = false;
       
   980             JCExpression curr = tree;
   980             while (true) {
   981             while (true) {
   981                 if (tree.hasTag(LITERAL)) {
   982                 if (curr.hasTag(JCTree.Tag.PLUS)) {
   982                     JCLiteral lit = (JCLiteral) tree;
   983                     JCBinary op = (JCBinary)curr;
   983                     if (lit.typetag == TypeTag.CLASS) {
   984                     needsFolding |= foldIfNeeded(op.rhs, litBuf, opStack, false);
   984                         StringBuilder sbuf =
   985                     curr = op.lhs;
   985                             new StringBuilder((String)lit.value);
   986                 } else {
   986                         while (buf.nonEmpty()) {
   987                     needsFolding |= foldIfNeeded(curr, litBuf, opStack, true);
   987                             sbuf.append(buf.head);
   988                     break; //last one!
   988                             buf = buf.tail;
       
   989                         }
       
   990                         return sbuf;
       
   991                     }
       
   992                 } else if (tree.hasTag(JCTree.Tag.PLUS)) {
       
   993                     JCBinary op = (JCBinary)tree;
       
   994                     if (op.rhs.hasTag(LITERAL)) {
       
   995                         JCLiteral lit = (JCLiteral) op.rhs;
       
   996                         if (lit.typetag == TypeTag.CLASS) {
       
   997                             buf = buf.prepend((String) lit.value);
       
   998                             tree = op.lhs;
       
   999                             continue;
       
  1000                         }
       
  1001                     }
       
  1002                 }
   989                 }
  1003                 return null;
   990             }
  1004             }
   991             if (needsFolding) {
  1005         }
   992                 List<JCExpression> ops = opStack.toList();
       
   993                 JCExpression res = ops.head;
       
   994                 for (JCExpression op : ops.tail) {
       
   995                     res = F.at(op.getStartPosition()).Binary(optag(TokenKind.PLUS), res, op);
       
   996                     storeEnd(res, getEndPos(op));
       
   997                 }
       
   998                 return res;
       
   999             } else {
       
  1000                 return tree;
       
  1001             }
       
  1002         }
       
  1003 
       
  1004         private boolean foldIfNeeded(JCExpression tree, ListBuffer<JCLiteral> litBuf,
       
  1005                                                 ListBuffer<JCExpression> opStack, boolean last) {
       
  1006             JCLiteral str = stringLiteral(tree);
       
  1007             if (str != null) {
       
  1008                 litBuf.prepend(str);
       
  1009                 return last && merge(litBuf, opStack);
       
  1010             } else {
       
  1011                 boolean res = merge(litBuf, opStack);
       
  1012                 litBuf.clear();
       
  1013                 opStack.prepend(tree);
       
  1014                 return res;
       
  1015             }
       
  1016         }
       
  1017 
       
  1018         boolean merge(ListBuffer<JCLiteral> litBuf, ListBuffer<JCExpression> opStack) {
       
  1019             if (litBuf.isEmpty()) {
       
  1020                 return false;
       
  1021             } else if (litBuf.size() == 1) {
       
  1022                 opStack.prepend(litBuf.first());
       
  1023                 return false;
       
  1024             } else {
       
  1025                 JCExpression t = F.at(litBuf.first().getStartPosition()).Literal(TypeTag.CLASS,
       
  1026                         litBuf.stream().map(lit -> (String)lit.getValue()).collect(Collectors.joining()));
       
  1027                 storeEnd(t, litBuf.last().getEndPosition(endPosTable));
       
  1028                 opStack.prepend(t);
       
  1029                 return true;
       
  1030             }
       
  1031         }
       
  1032 
       
  1033         private JCLiteral stringLiteral(JCTree tree) {
       
  1034             if (tree.hasTag(LITERAL)) {
       
  1035                 JCLiteral lit = (JCLiteral)tree;
       
  1036                 if (lit.typetag == TypeTag.CLASS) {
       
  1037                     return lit;
       
  1038                 }
       
  1039             }
       
  1040             return null;
       
  1041         }
       
  1042 
  1006 
  1043 
  1007         /** optimization: To save allocating a new operand/operator stack
  1044         /** optimization: To save allocating a new operand/operator stack
  1008          *  for every binary operation, we use supplys.
  1045          *  for every binary operation, we use supplys.
  1009          */
  1046          */
  1010         ArrayList<JCExpression[]> odStackSupply = new ArrayList<>();
  1047         ArrayList<JCExpression[]> odStackSupply = new ArrayList<>();