1 /* |
1 /* |
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * |
4 * |
5 * This code is free software; you can redistribute it and/or modify it |
5 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as |
6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. Oracle designates this |
7 * published by the Free Software Foundation. Oracle designates this |
277 protected DCTree blockTag() { |
277 protected DCTree blockTag() { |
278 int p = bp; |
278 int p = bp; |
279 try { |
279 try { |
280 nextChar(); |
280 nextChar(); |
281 if (isIdentifierStart(ch)) { |
281 if (isIdentifierStart(ch)) { |
282 int namePos = bp; |
282 Name name = readIdentifier(); |
283 nextChar(); |
|
284 while (isIdentifierPart(ch)) |
|
285 nextChar(); |
|
286 int nameLen = bp - namePos; |
|
287 |
|
288 Name name = names.fromChars(buf, namePos, nameLen); |
|
289 TagParser tp = tagParsers.get(name); |
283 TagParser tp = tagParsers.get(name); |
290 if (tp == null) { |
284 if (tp == null) { |
291 List<DCTree> content = blockContent(); |
285 List<DCTree> content = blockContent(); |
292 return m.at(p).UnknownBlockTag(name, content); |
286 return m.at(p).UnknownBlockTag(name, content); |
293 } else { |
287 } else { |
332 protected DCTree inlineTag() { |
326 protected DCTree inlineTag() { |
333 int p = bp - 1; |
327 int p = bp - 1; |
334 try { |
328 try { |
335 nextChar(); |
329 nextChar(); |
336 if (isIdentifierStart(ch)) { |
330 if (isIdentifierStart(ch)) { |
337 int namePos = bp; |
331 Name name = readIdentifier(); |
338 nextChar(); |
|
339 while (isIdentifierPart(ch)) |
|
340 nextChar(); |
|
341 int nameLen = bp - namePos; |
|
342 skipWhitespace(); |
332 skipWhitespace(); |
343 |
333 |
344 Name name = names.fromChars(buf, namePos, nameLen); |
|
345 TagParser tp = tagParsers.get(name); |
334 TagParser tp = tagParsers.get(name); |
346 if (tp == null) { |
335 if (tp == null) { |
347 DCTree text = inlineText(); |
336 DCTree text = inlineText(); |
348 if (text != null) { |
337 if (text != null) { |
349 nextChar(); |
338 nextChar(); |
573 protected DCIdentifier identifier() throws ParseException { |
562 protected DCIdentifier identifier() throws ParseException { |
574 skipWhitespace(); |
563 skipWhitespace(); |
575 int pos = bp; |
564 int pos = bp; |
576 |
565 |
577 if (isJavaIdentifierStart(ch)) { |
566 if (isJavaIdentifierStart(ch)) { |
578 nextChar(); |
567 Name name = readJavaIdentifier(); |
579 while (isJavaIdentifierPart(ch)) |
568 return m.at(pos).Identifier(name); |
580 nextChar(); |
|
581 return m.at(pos).Identifier(names.fromChars(buf, pos, bp - pos)); |
|
582 } |
569 } |
583 |
570 |
584 throw new ParseException("dc.identifier.expected"); |
571 throw new ParseException("dc.identifier.expected"); |
585 } |
572 } |
586 |
573 |
701 * {@literal &identifier; } or {@literal &#digits; } or {@literal &#xhex-digits; } |
688 * {@literal &identifier; } or {@literal &#digits; } or {@literal &#xhex-digits; } |
702 */ |
689 */ |
703 protected DCTree entity() { |
690 protected DCTree entity() { |
704 int p = bp; |
691 int p = bp; |
705 nextChar(); |
692 nextChar(); |
706 int namep = bp; |
693 Name name = null; |
707 boolean checkSemi = false; |
694 boolean checkSemi = false; |
708 if (ch == '#') { |
695 if (ch == '#') { |
|
696 int namep = bp; |
709 nextChar(); |
697 nextChar(); |
710 if (isDecimalDigit(ch)) { |
698 if (isDecimalDigit(ch)) { |
711 nextChar(); |
699 nextChar(); |
712 while (isDecimalDigit(ch)) |
700 while (isDecimalDigit(ch)) |
713 nextChar(); |
701 nextChar(); |
714 checkSemi = true; |
702 name = names.fromChars(buf, namep, bp - namep); |
715 } else if (ch == 'x' || ch == 'X') { |
703 } else if (ch == 'x' || ch == 'X') { |
716 nextChar(); |
704 nextChar(); |
717 if (isHexDigit(ch)) { |
705 if (isHexDigit(ch)) { |
718 nextChar(); |
706 nextChar(); |
719 while (isHexDigit(ch)) |
707 while (isHexDigit(ch)) |
720 nextChar(); |
708 nextChar(); |
721 checkSemi = true; |
709 name = names.fromChars(buf, namep, bp - namep); |
722 } |
710 } |
723 } |
711 } |
724 } else if (isIdentifierStart(ch)) { |
712 } else if (isIdentifierStart(ch)) { |
|
713 name = readIdentifier(); |
|
714 } |
|
715 |
|
716 if (name == null) |
|
717 return erroneous("dc.bad.entity", p); |
|
718 else { |
|
719 if (ch != ';') |
|
720 return erroneous("dc.missing.semicolon", p); |
725 nextChar(); |
721 nextChar(); |
726 while (isIdentifierPart(ch)) |
722 return m.at(p).Entity(name); |
727 nextChar(); |
|
728 checkSemi = true; |
|
729 } |
|
730 |
|
731 if (checkSemi && ch == ';') { |
|
732 nextChar(); |
|
733 return m.at(p).Entity(names.fromChars(buf, namep, bp - namep - 1)); |
|
734 } else { |
|
735 String code = checkSemi |
|
736 ? "dc.missing.semicolon" |
|
737 : "dc.bad.entity"; |
|
738 return erroneous(code, p); |
|
739 } |
723 } |
740 } |
724 } |
741 |
725 |
742 /** |
726 /** |
743 * Read the start or end of an HTML tag, or an HTML comment |
727 * Read the start or end of an HTML tag, or an HTML comment |
745 */ |
729 */ |
746 protected DCTree html() { |
730 protected DCTree html() { |
747 int p = bp; |
731 int p = bp; |
748 nextChar(); |
732 nextChar(); |
749 if (isIdentifierStart(ch)) { |
733 if (isIdentifierStart(ch)) { |
750 int namePos = bp; |
734 Name name = readIdentifier(); |
751 nextChar(); |
|
752 while (isIdentifierPart(ch)) |
|
753 nextChar(); |
|
754 int nameLen = bp - namePos; |
|
755 List<DCTree> attrs = htmlAttrs(); |
735 List<DCTree> attrs = htmlAttrs(); |
756 if (attrs != null) { |
736 if (attrs != null) { |
757 boolean selfClosing = false; |
737 boolean selfClosing = false; |
758 if (ch == '/') { |
738 if (ch == '/') { |
759 nextChar(); |
739 nextChar(); |
760 selfClosing = true; |
740 selfClosing = true; |
761 } |
741 } |
762 if (ch == '>') { |
742 if (ch == '>') { |
763 nextChar(); |
743 nextChar(); |
764 Name name = names.fromChars(buf, namePos, nameLen); |
|
765 return m.at(p).StartElement(name, attrs, selfClosing); |
744 return m.at(p).StartElement(name, attrs, selfClosing); |
766 } |
745 } |
767 } |
746 } |
768 } else if (ch == '/') { |
747 } else if (ch == '/') { |
769 nextChar(); |
748 nextChar(); |
770 if (isIdentifierStart(ch)) { |
749 if (isIdentifierStart(ch)) { |
771 int namePos = bp; |
750 Name name = readIdentifier(); |
772 nextChar(); |
|
773 while (isIdentifierPart(ch)) |
|
774 nextChar(); |
|
775 int nameLen = bp - namePos; |
|
776 skipWhitespace(); |
751 skipWhitespace(); |
777 if (ch == '>') { |
752 if (ch == '>') { |
778 nextChar(); |
753 nextChar(); |
779 Name name = names.fromChars(buf, namePos, nameLen); |
|
780 return m.at(p).EndElement(name); |
754 return m.at(p).EndElement(name); |
781 } |
755 } |
782 } |
756 } |
783 } else if (ch == '!') { |
757 } else if (ch == '!') { |
784 nextChar(); |
758 nextChar(); |
820 skipWhitespace(); |
794 skipWhitespace(); |
821 |
795 |
822 loop: |
796 loop: |
823 while (isIdentifierStart(ch)) { |
797 while (isIdentifierStart(ch)) { |
824 int namePos = bp; |
798 int namePos = bp; |
825 nextChar(); |
799 Name name = readIdentifier(); |
826 while (isIdentifierPart(ch)) |
|
827 nextChar(); |
|
828 int nameLen = bp - namePos; |
|
829 skipWhitespace(); |
800 skipWhitespace(); |
830 List<DCTree> value = null; |
801 List<DCTree> value = null; |
831 ValueKind vkind = ValueKind.EMPTY; |
802 ValueKind vkind = ValueKind.EMPTY; |
832 if (ch == '=') { |
803 if (ch == '=') { |
833 ListBuffer<DCTree> v = new ListBuffer<DCTree>(); |
804 ListBuffer<DCTree> v = new ListBuffer<DCTree>(); |
860 addPendingText(v, bp - 1); |
831 addPendingText(v, bp - 1); |
861 } |
832 } |
862 skipWhitespace(); |
833 skipWhitespace(); |
863 value = v.toList(); |
834 value = v.toList(); |
864 } |
835 } |
865 Name name = names.fromChars(buf, namePos, nameLen); |
|
866 DCAttribute attr = m.at(namePos).Attribute(name, vkind, value); |
836 DCAttribute attr = m.at(namePos).Attribute(name, vkind, value); |
867 attrs.add(attr); |
837 attrs.add(attr); |
868 } |
838 } |
869 |
839 |
870 return attrs.toList(); |
840 return attrs.toList(); |
924 |
894 |
925 protected boolean isIdentifierStart(char ch) { |
895 protected boolean isIdentifierStart(char ch) { |
926 return Character.isUnicodeIdentifierStart(ch); |
896 return Character.isUnicodeIdentifierStart(ch); |
927 } |
897 } |
928 |
898 |
929 protected boolean isIdentifierPart(char ch) { |
899 protected Name readIdentifier() { |
930 return Character.isUnicodeIdentifierPart(ch); |
900 int start = bp; |
|
901 nextChar(); |
|
902 while (bp < buflen && Character.isUnicodeIdentifierPart(ch)) |
|
903 nextChar(); |
|
904 return names.fromChars(buf, start, bp - start); |
931 } |
905 } |
932 |
906 |
933 protected boolean isJavaIdentifierStart(char ch) { |
907 protected boolean isJavaIdentifierStart(char ch) { |
934 return Character.isJavaIdentifierStart(ch); |
908 return Character.isJavaIdentifierStart(ch); |
935 } |
909 } |
936 |
910 |
937 protected boolean isJavaIdentifierPart(char ch) { |
911 protected Name readJavaIdentifier() { |
938 return Character.isJavaIdentifierPart(ch); |
912 int start = bp; |
|
913 nextChar(); |
|
914 while (bp < buflen && Character.isJavaIdentifierPart(ch)) |
|
915 nextChar(); |
|
916 return names.fromChars(buf, start, bp - start); |
939 } |
917 } |
940 |
918 |
941 protected boolean isDecimalDigit(char ch) { |
919 protected boolean isDecimalDigit(char ch) { |
942 return ('0' <= ch && ch <= '9'); |
920 return ('0' <= ch && ch <= '9'); |
943 } |
921 } |