Author: vsiveton Date: Wed Mar 12 04:26:31 2008 New Revision: 636283 URL: http://svn.apache.org/viewvc?rev=636283&view=rev Log: o increased visibility of some methods/fields o improved the readingness
Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java Modified: maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java URL: http://svn.apache.org/viewvc/maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java?rev=636283&r1=636282&r2=636283&view=diff ============================================================================== --- maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java (original) +++ maven/doxia/doxia/trunk/doxia-modules/doxia-module-apt/src/main/java/org/apache/maven/doxia/module/apt/AptParser.java Wed Mar 12 04:26:31 2008 @@ -125,7 +125,7 @@ "COMMENT_BLOCK" }; /** An array of spaces. */ - private static final char SPACES[] = { + protected static final char SPACES[] = { ' ', ' ', ' ', @@ -219,18 +219,9 @@ // Instance fields // ---------------------------------------------------------------------- - /** sourceContent. */ - private String sourceContent; - /** the AptSource. */ private AptSource source; - /** the sink to receive the events. */ - private Sink sink; - - /** a line of AptSource. */ - private String line; - /** a block of AptSource. */ private Block block; @@ -240,6 +231,15 @@ /** blockLineNumber. */ private int blockLineNumber; + /** sourceContent. */ + protected String sourceContent; + + /** the sink to receive the events. */ + protected Sink sink; + + /** a line of AptSource. */ + protected String line; + // ---------------------------------------------------------------------- // Public methods // ---------------------------------------------------------------------- @@ -313,208 +313,611 @@ } // ---------------------------------------------------------------------- - // Private methods + // Protected methods // ---------------------------------------------------------------------- /** - * Parse the head of the Apt source document. + * Parse the next line of the Apt source document. * * @throws AptParseException if something goes wrong. */ - private void traverseHead() + protected void nextLine() throws AptParseException { - sink.head(); - - if ( block != null && block.getType() == TITLE ) - { - block.traverse(); - nextBlock(); - } - - sink.head_(); + line = source.getNextLine(); } /** - * Parse the body of the Apt source document. + * Parse the given text. * + * @param text the text to parse. + * @param begin offset. + * @param end offset. + * @param sink the sink to receive the events. * @throws AptParseException if something goes wrong. */ - private void traverseBody() + protected void doTraverseText( String text, int begin, int end, Sink sink ) throws AptParseException { - sink.body(); - - if ( block != null ) - { - traverseSectionBlocks(); - } + boolean anchor = false; + boolean link = false; + boolean italic = false; + boolean bold = false; + boolean monospaced = false; + StringBuffer buffer = new StringBuffer( end - begin ); - while ( block != null ) + for ( int i = begin; i < end; ++i ) { - traverseSection( 0 ); - } + char c = text.charAt( i ); + switch ( c ) + { + case BACKSLASH: + if ( i + 1 < end ) + { + char escaped = text.charAt( i + 1 ); + switch ( escaped ) + { + case SPACE: + ++i; + flushTraversed( buffer, sink ); + sink.nonBreakingSpace(); + break; + case '\r': + case '\n': + ++i; + // Skip white space which may follow a line break. + while ( i + 1 < end && Character.isWhitespace( text.charAt( i + 1 ) ) ) + { + ++i; + } + flushTraversed( buffer, sink ); + sink.lineBreak(); + break; + case BACKSLASH: + case PIPE: + case COMMENT: + case EQUAL: + case MINUS: + case PLUS: + case STAR: + case LEFT_SQUARE_BRACKET: + case RIGHT_SQUARE_BRACKET: + case LESS_THAN: + case GREATER_THAN: + case LEFT_CURLY_BRACKET: + case RIGHT_CURLY_BRACKET: + ++i; + buffer.append( escaped ); + break; + case 'x': + if ( i + 3 < end && isHexChar( text.charAt( i + 2 ) ) + && isHexChar( text.charAt( i + 3 ) ) ) + { + int value = '?'; + try + { + value = Integer.parseInt( text.substring( i + 2, i + 4 ), 16 ); + } + catch ( NumberFormatException e ) + { + if ( getLog().isDebugEnabled() ) + { + getLog().debug( "Not a number: " + text.substring( i + 2, i + 4 ) ); + } + } - sink.body_(); - } + i += 3; + buffer.append( (char) value ); + } + else + { + buffer.append( BACKSLASH ); + } + break; + case 'u': + if ( i + 5 < end && isHexChar( text.charAt( i + 2 ) ) + && isHexChar( text.charAt( i + 3 ) ) && isHexChar( text.charAt( i + 4 ) ) + && isHexChar( text.charAt( i + 5 ) ) ) + { + int value = '?'; + try + { + value = Integer.parseInt( text.substring( i + 2, i + 6 ), 16 ); + } + catch ( NumberFormatException e ) + { + if ( getLog().isDebugEnabled() ) + { + getLog().debug( "Not a number: " + text.substring( i + 2, i + 6 ) ); + } + } - /** - * Parse a section of the Apt source document. - * - * @param level The section level. - * @throws AptParseException if something goes wrong. - */ - private void traverseSection( int level ) - throws AptParseException - { - if ( block == null ) - { - return; - } + i += 5; + buffer.append( (char) value ); + } + else + { + buffer.append( BACKSLASH ); + } + break; + default: + if ( isOctalChar( escaped ) ) + { + int octalChars = 1; + if ( isOctalChar( charAt( text, end, i + 2 ) ) ) + { + ++octalChars; + if ( isOctalChar( charAt( text, end, i + 3 ) ) ) + { + ++octalChars; + } + } + int value = '?'; + try + { + value = Integer.parseInt( text.substring( i + 1, i + 1 + octalChars ), 8 ); + } + catch ( NumberFormatException e ) + { + if ( getLog().isDebugEnabled() ) + { + getLog().debug( + "Not a number: " + + text.substring( i + 1, i + 1 + octalChars ) ); + } + } - int type = SECTION1 + level; + i += octalChars; + buffer.append( (char) value ); + } + else + { + buffer.append( BACKSLASH ); + } + } + } + else + { + buffer.append( BACKSLASH ); + } + break; - expectedBlock( type ); + case LEFT_CURLY_BRACKET: /*}*/ + if ( !anchor && !link ) + { + if ( i + 1 < end && text.charAt( i + 1 ) == LEFT_CURLY_BRACKET /*}*/) + { + ++i; + link = true; + flushTraversed( buffer, sink ); - switch ( level ) - { - case 0: - sink.section1(); - break; - case 1: - sink.section2(); - break; - case 2: - sink.section3(); - break; - case 3: - sink.section4(); - break; - case 4: - sink.section5(); - break; - default: - break; - } + String linkAnchor = null; - block.traverse(); + if ( i + 1 < end && text.charAt( i + 1 ) == LEFT_CURLY_BRACKET /*}*/) + { + ++i; + StringBuffer buf = new StringBuffer(); + i = skipTraversedLinkAnchor( text, i + 1, end, buf ); + linkAnchor = buf.toString(); + } - nextBlock(); + if ( linkAnchor == null ) + { + linkAnchor = getTraversedLink( text, i + 1, end ); + } - traverseSectionBlocks(); + sink.link( linkAnchor ); + } + else + { + anchor = true; + flushTraversed( buffer, sink ); + sink.anchor( getTraversedAnchor( text, i + 1, end ) ); + } + } + else + { + buffer.append( c ); + } + break; - while ( block != null ) - { - if ( block.getType() <= type ) - { - break; - } + case /*{*/RIGHT_CURLY_BRACKET: + if ( link && i + 1 < end && text.charAt( i + 1 ) == /*{*/RIGHT_CURLY_BRACKET ) + { + ++i; + link = false; + flushTraversed( buffer, sink ); + sink.link_(); + } + else if ( anchor ) + { + anchor = false; + flushTraversed( buffer, sink ); + sink.anchor_(); + } + else + { + buffer.append( c ); + } + break; - traverseSection( level + 1 ); + case LESS_THAN: + if ( !italic && !bold && !monospaced ) + { + if ( i + 1 < end && text.charAt( i + 1 ) == LESS_THAN ) + { + if ( i + 2 < end && text.charAt( i + 2 ) == LESS_THAN ) + { + i += 2; + monospaced = true; + flushTraversed( buffer, sink ); + sink.monospaced(); + } + else + { + ++i; + bold = true; + flushTraversed( buffer, sink ); + sink.bold(); + } + } + else + { + italic = true; + flushTraversed( buffer, sink ); + sink.italic(); + } + } + else + { + buffer.append( c ); + } + break; + + case GREATER_THAN: + if ( monospaced && i + 2 < end && text.charAt( i + 1 ) == GREATER_THAN + && text.charAt( i + 2 ) == GREATER_THAN ) + { + i += 2; + monospaced = false; + flushTraversed( buffer, sink ); + sink.monospaced_(); + } + else if ( bold && i + 1 < end && text.charAt( i + 1 ) == GREATER_THAN ) + { + ++i; + bold = false; + flushTraversed( buffer, sink ); + sink.bold_(); + } + else if ( italic ) + { + italic = false; + flushTraversed( buffer, sink ); + sink.italic_(); + } + else + { + buffer.append( c ); + } + break; + + default: + if ( Character.isWhitespace( c ) ) + { + buffer.append( SPACE ); + + // Skip to the last char of a sequence of white spaces. + while ( i + 1 < end && Character.isWhitespace( text.charAt( i + 1 ) ) ) + { + ++i; + } + } + else + { + buffer.append( c ); + } + } } - switch ( level ) + if ( monospaced ) { - case 0: - sink.section1_(); - break; - case 1: - sink.section2_(); - break; - case 2: - sink.section3_(); - break; - case 3: - sink.section4_(); - break; - case 4: - sink.section5_(); - break; - default: - break; + throw new AptParseException( "missing '" + MONOSPACED_END_MARKUP + "'" ); + } + if ( bold ) + { + throw new AptParseException( "missing '" + BOLD_END_MARKUP + "'" ); + } + if ( italic ) + { + throw new AptParseException( "missing '" + ITALIC_END_MARKUP + "'" ); } + if ( link ) + { + throw new AptParseException( "missing '" + LINK_END_MARKUP + "'" ); + } + if ( anchor ) + { + throw new AptParseException( "missing '" + ANCHOR_END_MARKUP + "'" ); + } + + flushTraversed( buffer, sink ); } + // ----------------------------------------------------------------------- + /** - * Parse the section blocks of the Apt source document. + * Returns the character at position i of the given string. * - * @throws AptParseException if something goes wrong. + * @param string the string. + * @param length length. + * @param i offset. + * @return the character, or '\0' if i > length. */ - private void traverseSectionBlocks() - throws AptParseException + protected static char charAt( String string, int length, int i ) { - loop: while ( block != null ) + return ( i < length ) ? string.charAt( i ) : '\0'; + } + + /** + * Skip spaces. + * + * @param string string. + * @param length length. + * @param i offset. + * @return int. + */ + protected static int skipSpace( String string, int length, int i ) + { + loop: for ( ; i < length; ++i ) { - switch ( block.getType() ) + switch ( string.charAt( i ) ) { - case PARAGRAPH: - case VERBATIM: - case FIGURE: - case TABLE: - case HORIZONTAL_RULE: - case PG_BREAK: - case MACRO: - case COMMENT_BLOCK: - block.traverse(); - nextBlock(); - break; - - case LIST_ITEM: - traverseList(); - break; - - case NUMBERED_LIST_ITEM: - traverseNumberedList(); - break; - - case DEFINITION_LIST_ITEM: - traverseDefinitionList(); - break; - - case LIST_BREAK: - // May be this is a list break which has not been indented - // very precisely. - nextBlock(); + case SPACE: + case TAB: break; - default: - // A section block which starts a new section. break loop; } } + return i; } /** - * Parse a list of the Apt source document. + * Replace part of a string. * - * @throws AptParseException if something goes wrong. + * @param string the string + * @param oldSub the substring to replace + * @param newSub the replacement string + * @return String */ - private void traverseList() - throws AptParseException + protected static String replaceAll( String string, String oldSub, String newSub ) { - if ( block == null ) + StringBuffer replaced = new StringBuffer(); + int oldSubLength = oldSub.length(); + int begin, end; + + begin = 0; + while ( ( end = string.indexOf( oldSub, begin ) ) >= 0 ) { - return; + if ( end > begin ) + { + replaced.append( string.substring( begin, end ) ); + } + replaced.append( newSub ); + begin = end + oldSubLength; + } + if ( begin < string.length() ) + { + replaced.append( string.substring( begin ) ); } - expectedBlock( LIST_ITEM ); - - int listIndent = block.getIndent(); - - sink.list(); - - sink.listItem(); + return replaced.toString(); + } - block.traverse(); + // ---------------------------------------------------------------------- + // Private methods + // ---------------------------------------------------------------------- - nextBlock(); + /** + * Parse the head of the Apt source document. + * + * @throws AptParseException if something goes wrong. + */ + private void traverseHead() + throws AptParseException + { + sink.head(); - loop: while ( block != null ) + if ( block != null && block.getType() == TITLE ) { - int blockIndent = block.getIndent(); + block.traverse(); + nextBlock(); + } - switch ( block.getType() ) - { + sink.head_(); + } + + /** + * Parse the body of the Apt source document. + * + * @throws AptParseException if something goes wrong. + */ + private void traverseBody() + throws AptParseException + { + sink.body(); + + if ( block != null ) + { + traverseSectionBlocks(); + } + + while ( block != null ) + { + traverseSection( 0 ); + } + + sink.body_(); + } + + /** + * Parse a section of the Apt source document. + * + * @param level The section level. + * @throws AptParseException if something goes wrong. + */ + private void traverseSection( int level ) + throws AptParseException + { + if ( block == null ) + { + return; + } + + int type = SECTION1 + level; + + expectedBlock( type ); + + switch ( level ) + { + case 0: + sink.section1(); + break; + case 1: + sink.section2(); + break; + case 2: + sink.section3(); + break; + case 3: + sink.section4(); + break; + case 4: + sink.section5(); + break; + default: + break; + } + + block.traverse(); + + nextBlock(); + + traverseSectionBlocks(); + + while ( block != null ) + { + if ( block.getType() <= type ) + { + break; + } + + traverseSection( level + 1 ); + } + + switch ( level ) + { + case 0: + sink.section1_(); + break; + case 1: + sink.section2_(); + break; + case 2: + sink.section3_(); + break; + case 3: + sink.section4_(); + break; + case 4: + sink.section5_(); + break; + default: + break; + } + } + + /** + * Parse the section blocks of the Apt source document. + * + * @throws AptParseException if something goes wrong. + */ + private void traverseSectionBlocks() + throws AptParseException + { + loop: while ( block != null ) + { + switch ( block.getType() ) + { + case PARAGRAPH: + case VERBATIM: + case FIGURE: + case TABLE: + case HORIZONTAL_RULE: + case PG_BREAK: + case MACRO: + case COMMENT_BLOCK: + block.traverse(); + nextBlock(); + break; + + case LIST_ITEM: + traverseList(); + break; + + case NUMBERED_LIST_ITEM: + traverseNumberedList(); + break; + + case DEFINITION_LIST_ITEM: + traverseDefinitionList(); + break; + + case LIST_BREAK: + // May be this is a list break which has not been indented + // very precisely. + nextBlock(); + break; + + default: + // A section block which starts a new section. + break loop; + } + } + } + + /** + * Parse a list of the Apt source document. + * + * @throws AptParseException if something goes wrong. + */ + private void traverseList() + throws AptParseException + { + if ( block == null ) + { + return; + } + + expectedBlock( LIST_ITEM ); + + int listIndent = block.getIndent(); + + sink.list(); + + sink.listItem(); + + block.traverse(); + + nextBlock(); + + loop: while ( block != null ) + { + int blockIndent = block.getIndent(); + + switch ( block.getType() ) + { case PARAGRAPH: if ( blockIndent < listIndent ) { @@ -774,17 +1177,6 @@ } /** - * Parse the next line of the Apt source document. - * - * @throws AptParseException if something goes wrong. - */ - private void nextLine() - throws AptParseException - { - line = source.getNextLine(); - } - - /** * Parse the next block of the Apt source document. * * @throws AptParseException if something goes wrong. @@ -836,551 +1228,197 @@ { nextLine(); } - } - - blockFileName = source.getName(); - blockLineNumber = source.getLineNumber(); - block = null; - switch ( line.charAt( i ) ) - { - case STAR: - if ( indent == 0 ) - { - if ( charAt( line, length, i + 1 ) == MINUS && charAt( line, length, i + 2 ) == MINUS ) - { - block = new Table( indent, line ); - } - else if ( charAt( line, length, i + 1 ) == STAR ) - { - if ( charAt( line, length, i + 2 ) == STAR ) - { - if ( charAt( line, length, i + 3 ) == STAR ) - { - block = new Section5( indent, line ); - } - else - { - block = new Section4( indent, line ); - } - } - else - { - block = new Section3( indent, line ); - } - } - else - { - block = new Section2( indent, line ); - } - } - else - { - block = new ListItem( indent, line ); - } - break; - case LEFT_SQUARE_BRACKET: - if ( charAt( line, length, i + 1 ) == RIGHT_SQUARE_BRACKET ) - { - block = new ListBreak( indent, line ); - } - else - { - if ( indent == 0 ) - { - block = new Figure( indent, line ); - } - else - { - if ( charAt( line, length, i + 1 ) == LEFT_SQUARE_BRACKET ) - { - int numbering; - - switch ( charAt( line, length, i + 2 ) ) - { - case NUMBERING_LOWER_ALPHA_CHAR: - numbering = Sink.NUMBERING_LOWER_ALPHA; - break; - case NUMBERING_UPPER_ALPHA_CHAR: - numbering = Sink.NUMBERING_UPPER_ALPHA; - break; - case NUMBERING_LOWER_ROMAN_CHAR: - numbering = Sink.NUMBERING_LOWER_ROMAN; - break; - case NUMBERING_UPPER_ROMAN_CHAR: - numbering = Sink.NUMBERING_UPPER_ROMAN; - break; - case NUMBERING: - default: - // The first item establishes the numbering - // scheme for the whole list. - numbering = Sink.NUMBERING_DECIMAL; - } - - block = new NumberedListItem( indent, line, numbering ); - } - else - { - block = new DefinitionListItem( indent, line ); - } - } - } - break; - case MINUS: - if ( charAt( line, length, i + 1 ) == MINUS && charAt( line, length, i + 2 ) == MINUS ) - { - if ( indent == 0 ) - { - block = new Verbatim( indent, line ); - } - else - { - if ( firstBlock ) - { - block = new Title( indent, line ); - } - } - } - break; - case PLUS: - if ( indent == 0 && charAt( line, length, i + 1 ) == MINUS && charAt( line, length, i + 2 ) == MINUS ) - { - block = new Verbatim( indent, line ); - } - break; - case EQUAL: - if ( indent == 0 && charAt( line, length, i + 1 ) == EQUAL && charAt( line, length, i + 2 ) == EQUAL ) - { - block = new HorizontalRule( indent, line ); - } - break; - case PAGE_BREAK: - if ( indent == 0 ) - { - block = new PageBreak( indent, line ); - } - break; - case PERCENT: - if ( indent == 0 && charAt( line, length, i + 1 ) == LEFT_CURLY_BRACKET ) - { - block = new MacroBlock( indent, line ); - } - break; - case COMMENT: - if ( indent == 0 && charAt( line, length, i + 1 ) == COMMENT ) - { - block = new Comment( line.substring( 2 ).trim() ); - } - break; - default: - break; - } - - if ( block == null ) - { - if ( indent == 0 ) - { - block = new Section1( indent, line ); - } - else - { - block = new Paragraph( indent, line ); - } - } - } - - /** - * Checks that the current block is of the expected type. - * - * @param type the expected type. - * @throws AptParseException if something goes wrong. - */ - private void expectedBlock( int type ) - throws AptParseException - { - int blockType = block.getType(); - - if ( blockType != type ) - { - throw new AptParseException( "expected " + TYPE_NAMES[type] + ", found " + TYPE_NAMES[blockType] ); - } - } - - // ----------------------------------------------------------------------- - - /** - * Determin if c is an octal character. - * - * @param c the character. - * @return boolean - */ - private static boolean isOctalChar( char c ) - { - return ( c >= '0' && c <= '7' ); - } - - /** - * Determin if c is an hex character. - * - * @param c the character. - * @return boolean - */ - private static boolean isHexChar( char c ) - { - return ( ( c >= '0' && c <= '9' ) || ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'F' ) ); - } - - /** - * Returns the character at position i of the given string. - * - * @param string the string. - * @param length length. - * @param i offset. - * @return the character, or '\0' if i > length. - */ - private static char charAt( String string, int length, int i ) - { - return ( i < length ) ? string.charAt( i ) : '\0'; - } - - /** - * Skip spaces. - * - * @param string string. - * @param length length. - * @param i offset. - * @return int. - */ - private static int skipSpace( String string, int length, int i ) - { - loop: for ( ; i < length; ++i ) - { - switch ( string.charAt( i ) ) - { - case SPACE: - case TAB: - break; - default: - break loop; - } - } - return i; - } - - /** - * Parse the given text. - * - * @param text the text to parse. - * @param begin offset. - * @param end offset. - * @param sink the sink to receive the events. - * @throws AptParseException if something goes wrong. - */ - private void doTraverseText( String text, int begin, int end, Sink sink ) - throws AptParseException - { - boolean anchor = false; - boolean link = false; - boolean italic = false; - boolean bold = false; - boolean monospaced = false; - StringBuffer buffer = new StringBuffer( end - begin ); - - for ( int i = begin; i < end; ++i ) - { - char c = text.charAt( i ); - switch ( c ) - { - case BACKSLASH: - if ( i + 1 < end ) - { - char escaped = text.charAt( i + 1 ); - switch ( escaped ) - { - case SPACE: - ++i; - flushTraversed( buffer, sink ); - sink.nonBreakingSpace(); - break; - case '\r': - case '\n': - ++i; - // Skip white space which may follow a line break. - while ( i + 1 < end && Character.isWhitespace( text.charAt( i + 1 ) ) ) - { - ++i; - } - flushTraversed( buffer, sink ); - sink.lineBreak(); - break; - case BACKSLASH: - case PIPE: - case COMMENT: - case EQUAL: - case MINUS: - case PLUS: - case STAR: - case LEFT_SQUARE_BRACKET: - case RIGHT_SQUARE_BRACKET: - case LESS_THAN: - case GREATER_THAN: - case LEFT_CURLY_BRACKET: - case RIGHT_CURLY_BRACKET: - ++i; - buffer.append( escaped ); - break; - case 'x': - if ( i + 3 < end && isHexChar( text.charAt( i + 2 ) ) - && isHexChar( text.charAt( i + 3 ) ) ) - { - int value = '?'; - try - { - value = Integer.parseInt( text.substring( i + 2, i + 4 ), 16 ); - } - catch ( NumberFormatException e ) - { - if ( getLog().isDebugEnabled() ) - { - getLog().debug( "Not a number: " + text.substring( i + 2, i + 4 ) ); - } - } - - i += 3; - buffer.append( (char) value ); - } - else - { - buffer.append( BACKSLASH ); - } - break; - case 'u': - if ( i + 5 < end && isHexChar( text.charAt( i + 2 ) ) - && isHexChar( text.charAt( i + 3 ) ) && isHexChar( text.charAt( i + 4 ) ) - && isHexChar( text.charAt( i + 5 ) ) ) - { - int value = '?'; - try - { - value = Integer.parseInt( text.substring( i + 2, i + 6 ), 16 ); - } - catch ( NumberFormatException e ) - { - if ( getLog().isDebugEnabled() ) - { - getLog().debug( "Not a number: " + text.substring( i + 2, i + 6 ) ); - } - } - - i += 5; - buffer.append( (char) value ); - } - else - { - buffer.append( BACKSLASH ); - } - break; - default: - if ( isOctalChar( escaped ) ) - { - int octalChars = 1; - if ( isOctalChar( charAt( text, end, i + 2 ) ) ) - { - ++octalChars; - if ( isOctalChar( charAt( text, end, i + 3 ) ) ) - { - ++octalChars; - } - } - int value = '?'; - try - { - value = Integer.parseInt( text.substring( i + 1, i + 1 + octalChars ), 8 ); - } - catch ( NumberFormatException e ) - { - if ( getLog().isDebugEnabled() ) - { - getLog().debug( - "Not a number: " - + text.substring( i + 1, i + 1 + octalChars ) ); - } - } - - i += octalChars; - buffer.append( (char) value ); - } - else - { - buffer.append( BACKSLASH ); - } - } - } - else - { - buffer.append( BACKSLASH ); - } - break; - - case LEFT_CURLY_BRACKET: /*}*/ - if ( !anchor && !link ) - { - if ( i + 1 < end && text.charAt( i + 1 ) == LEFT_CURLY_BRACKET /*}*/) - { - ++i; - link = true; - flushTraversed( buffer, sink ); - - String linkAnchor = null; - - if ( i + 1 < end && text.charAt( i + 1 ) == LEFT_CURLY_BRACKET /*}*/) - { - ++i; - StringBuffer buf = new StringBuffer(); - i = skipTraversedLinkAnchor( text, i + 1, end, buf ); - linkAnchor = buf.toString(); - } - - if ( linkAnchor == null ) - { - linkAnchor = getTraversedLink( text, i + 1, end ); - } - - sink.link( linkAnchor ); - } - else - { - anchor = true; - flushTraversed( buffer, sink ); - sink.anchor( getTraversedAnchor( text, i + 1, end ) ); - } - } - else - { - buffer.append( c ); - } - break; - - case /*{*/RIGHT_CURLY_BRACKET: - if ( link && i + 1 < end && text.charAt( i + 1 ) == /*{*/RIGHT_CURLY_BRACKET ) - { - ++i; - link = false; - flushTraversed( buffer, sink ); - sink.link_(); - } - else if ( anchor ) - { - anchor = false; - flushTraversed( buffer, sink ); - sink.anchor_(); - } - else + } + + blockFileName = source.getName(); + blockLineNumber = source.getLineNumber(); + block = null; + switch ( line.charAt( i ) ) + { + case STAR: + if ( indent == 0 ) + { + if ( charAt( line, length, i + 1 ) == MINUS && charAt( line, length, i + 2 ) == MINUS ) { - buffer.append( c ); + block = new Table( indent, line ); } - break; - - case LESS_THAN: - if ( !italic && !bold && !monospaced ) + else if ( charAt( line, length, i + 1 ) == STAR ) { - if ( i + 1 < end && text.charAt( i + 1 ) == LESS_THAN ) + if ( charAt( line, length, i + 2 ) == STAR ) { - if ( i + 2 < end && text.charAt( i + 2 ) == LESS_THAN ) + if ( charAt( line, length, i + 3 ) == STAR ) { - i += 2; - monospaced = true; - flushTraversed( buffer, sink ); - sink.monospaced(); + block = new Section5( indent, line ); } else { - ++i; - bold = true; - flushTraversed( buffer, sink ); - sink.bold(); + block = new Section4( indent, line ); } } else { - italic = true; - flushTraversed( buffer, sink ); - sink.italic(); + block = new Section3( indent, line ); } } else { - buffer.append( c ); - } - break; - - case GREATER_THAN: - if ( monospaced && i + 2 < end && text.charAt( i + 1 ) == GREATER_THAN - && text.charAt( i + 2 ) == GREATER_THAN ) - { - i += 2; - monospaced = false; - flushTraversed( buffer, sink ); - sink.monospaced_(); - } - else if ( bold && i + 1 < end && text.charAt( i + 1 ) == GREATER_THAN ) - { - ++i; - bold = false; - flushTraversed( buffer, sink ); - sink.bold_(); + block = new Section2( indent, line ); } - else if ( italic ) + } + else + { + block = new ListItem( indent, line ); + } + break; + case LEFT_SQUARE_BRACKET: + if ( charAt( line, length, i + 1 ) == RIGHT_SQUARE_BRACKET ) + { + block = new ListBreak( indent, line ); + } + else + { + if ( indent == 0 ) { - italic = false; - flushTraversed( buffer, sink ); - sink.italic_(); + block = new Figure( indent, line ); } else { - buffer.append( c ); - } - break; + if ( charAt( line, length, i + 1 ) == LEFT_SQUARE_BRACKET ) + { + int numbering; - default: - if ( Character.isWhitespace( c ) ) - { - buffer.append( SPACE ); + switch ( charAt( line, length, i + 2 ) ) + { + case NUMBERING_LOWER_ALPHA_CHAR: + numbering = Sink.NUMBERING_LOWER_ALPHA; + break; + case NUMBERING_UPPER_ALPHA_CHAR: + numbering = Sink.NUMBERING_UPPER_ALPHA; + break; + case NUMBERING_LOWER_ROMAN_CHAR: + numbering = Sink.NUMBERING_LOWER_ROMAN; + break; + case NUMBERING_UPPER_ROMAN_CHAR: + numbering = Sink.NUMBERING_UPPER_ROMAN; + break; + case NUMBERING: + default: + // The first item establishes the numbering + // scheme for the whole list. + numbering = Sink.NUMBERING_DECIMAL; + } - // Skip to the last char of a sequence of white spaces. - while ( i + 1 < end && Character.isWhitespace( text.charAt( i + 1 ) ) ) + block = new NumberedListItem( indent, line, numbering ); + } + else { - ++i; + block = new DefinitionListItem( indent, line ); } } + } + break; + case MINUS: + if ( charAt( line, length, i + 1 ) == MINUS && charAt( line, length, i + 2 ) == MINUS ) + { + if ( indent == 0 ) + { + block = new Verbatim( indent, line ); + } else { - buffer.append( c ); + if ( firstBlock ) + { + block = new Title( indent, line ); + } } - } + } + break; + case PLUS: + if ( indent == 0 && charAt( line, length, i + 1 ) == MINUS && charAt( line, length, i + 2 ) == MINUS ) + { + block = new Verbatim( indent, line ); + } + break; + case EQUAL: + if ( indent == 0 && charAt( line, length, i + 1 ) == EQUAL && charAt( line, length, i + 2 ) == EQUAL ) + { + block = new HorizontalRule( indent, line ); + } + break; + case PAGE_BREAK: + if ( indent == 0 ) + { + block = new PageBreak( indent, line ); + } + break; + case PERCENT: + if ( indent == 0 && charAt( line, length, i + 1 ) == LEFT_CURLY_BRACKET ) + { + block = new MacroBlock( indent, line ); + } + break; + case COMMENT: + if ( indent == 0 && charAt( line, length, i + 1 ) == COMMENT ) + { + block = new Comment( line.substring( 2 ).trim() ); + } + break; + default: + break; } - if ( monospaced ) - { - throw new AptParseException( "missing '" + MONOSPACED_END_MARKUP + "'" ); - } - if ( bold ) - { - throw new AptParseException( "missing '" + BOLD_END_MARKUP + "'" ); - } - if ( italic ) - { - throw new AptParseException( "missing '" + ITALIC_END_MARKUP + "'" ); - } - if ( link ) + if ( block == null ) { - throw new AptParseException( "missing '" + LINK_END_MARKUP + "'" ); + if ( indent == 0 ) + { + block = new Section1( indent, line ); + } + else + { + block = new Paragraph( indent, line ); + } } - if ( anchor ) + } + + /** + * Checks that the current block is of the expected type. + * + * @param type the expected type. + * @throws AptParseException if something goes wrong. + */ + private void expectedBlock( int type ) + throws AptParseException + { + int blockType = block.getType(); + + if ( blockType != type ) { - throw new AptParseException( "missing '" + ANCHOR_END_MARKUP + "'" ); + throw new AptParseException( "expected " + TYPE_NAMES[type] + ", found " + TYPE_NAMES[blockType] ); } + } - flushTraversed( buffer, sink ); + // ----------------------------------------------------------------------- + + /** + * Determine if c is an octal character. + * + * @param c the character. + * @return boolean + */ + private static boolean isOctalChar( char c ) + { + return ( c >= '0' && c <= '7' ); + } + + /** + * Determine if c is an hex character. + * + * @param c the character. + * @return boolean + */ + private static boolean isHexChar( char c ) + { + return ( ( c >= '0' && c <= '9' ) || ( c >= 'a' && c <= 'f' ) || ( c >= 'A' && c <= 'F' ) ); } /** @@ -1526,16 +1564,19 @@ Sink linkSink = new SinkAdapter() { + /** [EMAIL PROTECTED] */ public void lineBreak() { buffer.append( SPACE ); } + /** [EMAIL PROTECTED] */ public void nonBreakingSpace() { buffer.append( SPACE ); } + /** [EMAIL PROTECTED] */ public void text( String text ) { buffer.append( text ); @@ -2828,39 +2869,5 @@ return result; } - } - - // ----------------------------------------------------------------------- - - /** - * Replace part of a string. - * - * @param string the string - * @param oldSub the substring to replace - * @param newSub the replacement string - * @return String - */ - private static String replaceAll( String string, String oldSub, String newSub ) - { - StringBuffer replaced = new StringBuffer(); - int oldSubLength = oldSub.length(); - int begin, end; - - begin = 0; - while ( ( end = string.indexOf( oldSub, begin ) ) >= 0 ) - { - if ( end > begin ) - { - replaced.append( string.substring( begin, end ) ); - } - replaced.append( newSub ); - begin = end + oldSubLength; - } - if ( begin < string.length() ) - { - replaced.append( string.substring( begin ) ); - } - - return replaced.toString(); } }