| options { |
| LOOKAHEAD = 1; |
| STATIC = false; |
| UNICODE_INPUT = true; |
| MULTI = true; |
| BUILD_NODE_FILES = false; |
| NODE_PREFIX = ""; |
| NODE_DEFAULT_VOID = true; |
| NODE_USES_PARSER = false; |
| NODE_PACKAGE = "org.tautua.markdownpapers.ast"; |
| DEBUG_PARSER = false; |
| DEBUG_TOKEN_MANAGER = false; |
| DEBUG_LOOKAHEAD = false; |
| } |
| |
| PARSER_BEGIN(Parser) |
| package org.tautua.markdownpapers.parser; |
| |
| import org.tautua.markdownpapers.ast.*; |
| import org.tautua.markdownpapers.util.*; |
| |
| public class Parser { |
| private static final String EMPTY_STRING = ""; |
| private static final String QUOTE = '"' + ""; |
| |
| private Stack<Node> stack = new DequeStack<Node>(); |
| private Stack<Node> markupStack = new DequeStack<Node>(); |
| private int currentQuoteLevel = 0; |
| private int parentheses; |
| private int brackets; |
| |
| public Document parse() throws ParseException { |
| jj_input_stream.setTabSize(4); |
| Document(); |
| return (Document)getRootNode(); |
| } |
| |
| public Node getRootNode() { |
| return jjtree.rootNode(); |
| } |
| |
| String val(Token t) { |
| String i = t.image; |
| if (t.kind == CODE_SPAN && i.startsWith("``")) { |
| i = i.substring(2, i.length() - 2); |
| } else if (t.kind == CODE_SPAN) { |
| i = i.substring(1, i.length() - 1); |
| } else if(t.kind == ESCAPED_CHAR) { |
| i = String.valueOf(i.charAt(1)); |
| } |
| return i; |
| } |
| |
| String toWhitespace(Token prev, Token tab) { |
| int x = (4 - ((prev == null ? 1 : prev.endColumn + 1) % 4)) + 1; |
| switch(x) { |
| case 1: |
| return " "; |
| case 2: |
| return " "; |
| case 3: |
| return " "; |
| default: |
| return " "; |
| } |
| } |
| |
| boolean ParagraphLookahead() { |
| if (getToken(1).kind != EOL) { |
| return false; |
| } |
| |
| int i = 2; |
| int quoteLevel = 0; |
| Token t; |
| |
| do { |
| t = getToken(i++); |
| if (t.kind == GT) { |
| quoteLevel++; |
| } else if (t.kind == EOL) { |
| quoteLevel = 0; |
| } |
| } while(t.any(EOL, SPACE, TAB, GT)); |
| |
| if (t.any(PLUS, MINUS, STAR, NUMBERING, EOF)) { |
| return false; |
| } |
| |
| return currentQuoteLevel == quoteLevel && stack.size() > 0 && stack.peek() instanceof Item |
| && ((Item)stack.peek()).getIndentation() < t.beginColumn; |
| } |
| |
| boolean LineLookahead() { |
| if (getToken(1).kind != EOL) { |
| return false; |
| } |
| |
| int i = 2; |
| int quoteLevel = 0; |
| Token t; |
| |
| do { |
| t = getToken(i++); |
| if(t.kind == GT) { |
| quoteLevel++; |
| } |
| } while (t.any(SPACE, TAB, GT)); |
| |
| if (t.any(EOL, EOF)) { |
| return false; |
| } |
| |
| if (t.any(PLUS, MINUS, STAR, NUMBERING) && stack.peek() instanceof Item) { |
| return false; |
| } |
| |
| return currentQuoteLevel >= quoteLevel; |
| } |
| |
| boolean CodeLineLookahead() { |
| if (getToken(1).kind != EOL) { |
| return false; |
| } |
| |
| int i = 2; |
| int quoteLevel = 0; |
| int _indent = 0; |
| Token t; |
| |
| do { |
| t = getToken(i++); |
| if(t.kind == GT) { |
| quoteLevel++; |
| _indent = 0; |
| } else if(t.kind == SPACE) { |
| _indent++; |
| } else if(t.kind == TAB) { |
| _indent += 4; |
| } |
| } while (t.any(SPACE, TAB, GT) && _indent < 4); |
| |
| if (t.any(EOL, EOF)) { |
| return true; |
| } |
| |
| return currentQuoteLevel >= quoteLevel && _indent >= 4; |
| } |
| |
| boolean QuotedElementLookahead() { |
| if (getToken(1).none(EOL)) { |
| return false; |
| } |
| |
| int i = 2; |
| int quoteLevel = 0; |
| Token t; |
| |
| do { |
| t = getToken(i++); |
| if (t.any(GT)) { |
| quoteLevel++; |
| } |
| } while (t.any(SPACE, TAB, GT)); |
| |
| if (t.any(EOL, EOF)) { |
| return true; |
| } |
| |
| return currentQuoteLevel <= quoteLevel; |
| } |
| |
| boolean LooseLookahead() { |
| if (getToken(1).none(EOL)) { |
| return false; |
| } |
| |
| int i = 2; |
| boolean newline = false; |
| Token t; |
| |
| do { |
| t = getToken(i++); |
| if (t.any(EOL)) { |
| newline = true; |
| } |
| } while(t.any(SPACE, TAB, GT, EOL)); |
| |
| Item item = (Item)stack.peek(); |
| |
| return newline && t.any(PLUS, MINUS, STAR, NUMBERING) && (getToken(i).kind == SPACE || getToken(i).kind == TAB) |
| && item.getIndentation() == t.beginColumn; |
| } |
| |
| boolean TextLookahead() { |
| if (stack.size() > 0 && stack.peek() instanceof Header) { |
| int i = 1; |
| Token t; |
| do { |
| t = getToken(i++); |
| } while(t.any(SHARP)); |
| |
| return t.none(EOL,EOF); |
| } |
| |
| return getToken(1).none(EOL, EOF); |
| } |
| |
| boolean ListLookahead() { |
| if (getToken(1).none(EOL)) { |
| return false; |
| } |
| |
| int i = 2; |
| int quoteLevel = 0; |
| Token t; |
| |
| do { |
| t = getToken(i++); |
| if (t.any(GT)) { |
| quoteLevel++; |
| } |
| } while (t.any(EOL, SPACE, TAB, GT)); |
| |
| Item item = (Item)stack.peek(); |
| |
| return t.any(PLUS, MINUS, STAR, NUMBERING) && item.getIndentation() < t.beginColumn |
| && quoteLevel <= currentQuoteLevel; |
| } |
| |
| boolean ItemLookahead() { |
| if (getToken(1).none(EOL)) { |
| return false; |
| } |
| |
| int i = 2; |
| int quoteLevel = 0; |
| Token t; |
| |
| do { |
| t = getToken(i++); |
| if (t.any(GT)) { |
| quoteLevel++; |
| } |
| } while (t.any(EOL, SPACE, TAB, GT)); |
| |
| List list = (List)stack.peek(); |
| |
| return t.any(PLUS, MINUS, STAR, NUMBERING) && (getToken(i).kind == SPACE || getToken(i).kind == TAB) |
| && list.getIndentation() == t.beginColumn && !RulerLookahead(i); |
| } |
| |
| boolean RulerLookahead(int i) { |
| Token t; |
| int whitespace = 0; |
| do { |
| t = getToken(i++); |
| if(t.kind == SPACE) { |
| whitespace++; |
| } else { |
| whitespace = 0; |
| } |
| |
| if(whitespace > 2) { |
| return false; |
| } |
| } while(t.any(STAR, MINUS, SPACE)); |
| |
| return t.any(EOL, EOF); |
| } |
| |
| boolean QuoteInsideTitleLookahead(int quoteKind) { |
| if (getToken(1).kind == quoteKind) { |
| Token t; |
| int i = 2; |
| do { |
| t = getToken(i++); |
| } while (t.none(quoteKind, RPAREN, EOL, EOF)); |
| |
| return t.kind == quoteKind; |
| } |
| |
| return getToken(1).none(EOL, EOF); |
| } |
| |
| boolean NotClosingTag() { |
| return !(getToken(1).kind == LT && getToken(2).kind == SLASH |
| && getToken(3).kind == CHAR_SEQUENCE && getToken(4).kind == GT); |
| } |
| } |
| PARSER_END(Parser) |
| |
| /* WHITESPACE */ |
| TOKEN : { |
| < SPACE : " " > |
| | < TAB : "\t" > |
| | < EOL : "\r" | "\n" | "\r\n" > |
| } |
| |
| /* PUNCTUATION */ |
| TOKEN : { |
| < AMPERSAND : "&" > |
| | < BACKSLASH : "\\" > |
| | < BACKTICK : "`" > |
| | < BANG : "!" > |
| | < COLON : ":" > |
| | < DOUBLE_QUOTE : "\"" > |
| | < EQ : "=" > |
| | < GT : ">" > |
| | < LBRACKET : "[" > |
| | < LPAREN : "(" > |
| | < LT : "<" > |
| | < MINUS : "-" > |
| | < PLUS : "+" > |
| | < RBRACKET : "]" > |
| | < RPAREN : ")" > |
| | < SHARP : "#" > |
| | < SINGLE_QUOTE : "'" > |
| | < SLASH : "/" > |
| | < STAR : "*" > |
| | < UNDERSCORE : "_" > |
| } |
| |
| TOKEN : { |
| < COMMENT_OPEN : "<!--" > |
| | < COMMENT_CLOSE : "-->" > |
| } |
| |
| TOKEN : { |
| < CODE_SPAN : "`" ( ~["`", "\r", "\n"] )+ "`" | "`" "`" ( ~["'", "\r", "\n"] )+ "`" "`" > |
| | < NUMBERING : ( ["0"-"9"] )+ "." > |
| } |
| |
| TOKEN : { |
| < CHAR_ENTITY_REF : "&" ( ["a"-"z", "A"-"Z"] )+ ";" > |
| | < NUMERIC_CHAR_REF : "&" ( ( ["0"-"9"] ){1,4} | "x" ( ["0"-"9", "a"-"f", "A"-"F"] ){1,4} ) ";" > |
| | < ESCAPED_CHAR : "\\" ["{", "}", "[", "]", "(", ")", "\\", "`", "_", ">", "#", ".", "!", "+", "-", "*"] > |
| | < CHAR_SEQUENCE : ( ~["=", "#", "&", "*", "\"", "'", "`", ":", "<", ">", "(", ")", "[", "]", " " |
| , "\\", "/", "\t", "\r", "\n", "!", "_", "-", "+"] )+ > |
| } |
| |
| void Document() #Document : {} { |
| ( |
| <EOL> |
| | Element() ( LOOKAHEAD(2) <EOL> Element() )* |
| )* |
| <EOF> |
| } |
| |
| void Element() : {} { |
| LOOKAHEAD( ResourceDefinition() ) ResourceDefinition() |
| | BlockElement() |
| } |
| |
| void BlockElement() : {} { |
| LOOKAHEAD( EmptyLine() ) Whitespace() |
| | LOOKAHEAD( CodeLinePrefix() ) Code() |
| | |
| ( |
| ( InsignificantWhitespace() )? |
| ( |
| LOOKAHEAD( QuotePrefix() ) Quote() |
| | LOOKAHEAD( Ruler() ( <EOL> | <EOF> ) ) Ruler() |
| | LOOKAHEAD( Header() ( <EOL> | <EOF> ) ) Header() |
| | LOOKAHEAD( Comment() ) Comment() |
| | LOOKAHEAD( TagOpen() ) HtmlBlock() |
| | LOOKAHEAD(2) List() |
| | Paragraph() |
| ) |
| ) |
| } |
| |
| public void HtmlBlock() : {} { |
| Tag() ( Whitespace() )? |
| } |
| |
| void Whitespace() : {} { |
| ( <SPACE> | <TAB> )+ |
| } |
| |
| void InsignificantWhitespace() : {} { |
| <SPACE> ( <SPACE> ( <SPACE> )? )? |
| } |
| |
| void EmptyLine() : {} { |
| ( Whitespace() )? ( <EOL> | <EOF> ) |
| } |
| |
| void Header() #Header : { |
| int level = 1; |
| stack.push(jjtThis); |
| } { |
| ( |
| level = HeaderPrefix() Line() ( "#" )* |
| | Line() <EOL> level = HeaderSuffix() |
| ) ( Whitespace() )? |
| { |
| jjtThis.setLevel(level); |
| stack.pop(); |
| } |
| } |
| |
| int HeaderPrefix() : { |
| int level = 1; |
| } { |
| "#" ( "#" { level++; } ( "#" { level++; } ( "#" { level++; } ( "#" { level++; } ( "#" { level++; } )? )? )? )? )? |
| { |
| return level; |
| } |
| } |
| |
| int HeaderSuffix() : { |
| int level = 1; |
| }{ |
| ( |
| ( < EQ > )+ { level = 1; } |
| | ( < MINUS > )+ { level = 2; } |
| ) |
| { |
| return level; |
| } |
| } |
| |
| void Ruler() #Ruler : {} { |
| ( |
| "-" ( LOOKAHEAD(3) " " (" ")? )? "-" ( LOOKAHEAD(3) ( " " (" ")? )? "-" )+ |
| | "*" ( LOOKAHEAD(3) " " (" ")? )? "*" ( LOOKAHEAD(3) ( " " (" ")? )? "*" )+ |
| | "_" ( LOOKAHEAD(3) " " (" ")? )? "_" ( LOOKAHEAD(3) ( " " (" ")? )? "_" )+ |
| ) |
| ( Whitespace() )? |
| } |
| |
| void Quote() #Quote : { |
| stack.push(jjtThis); |
| currentQuoteLevel++; |
| } { |
| QuotePrefix() BlockElement() |
| ( LOOKAHEAD( {QuotedElementLookahead()} ) <EOL> |
| ( |
| LOOKAHEAD( ( Whitespace() )? <EOL> | <EOF> ) Whitespace() #Line |
| | LOOKAHEAD( QuotePrefix() ) QuotePrefix() ( BlockElement() )? |
| |
| )? |
| )* |
| { |
| currentQuoteLevel--; |
| stack.pop(); |
| } |
| } |
| |
| void QuotePrefix() : {} { |
| <GT> ( <SPACE> )? |
| } |
| |
| void Code() #Code : {} { |
| CodeLine() |
| ( LOOKAHEAD( {CodeLineLookahead()} ) <EOL> |
| ( LOOKAHEAD( QuotePrefix() ) QuotePrefix() )* |
| ( |
| LOOKAHEAD( ( Whitespace() )? <EOL> | <EOF> ) ( Whitespace() )? #Line |
| | CodeLine() |
| ) |
| )* |
| } |
| |
| void CodeLine() #Line : {} { |
| CodeLinePrefix() CodeText() |
| } |
| |
| void CodeLinePrefix() : {} { |
| <SPACE> <SPACE> <SPACE> <SPACE> | <TAB> |
| } |
| |
| void CodeText() #CodeText : { |
| Token t; |
| Token prev = null; |
| } { |
| ( |
| ( |
| ( |
| t = <CHAR_SEQUENCE> |
| | t = <SPACE> |
| | t = <AMPERSAND> |
| | t = <BACKTICK> |
| | t = <BACKSLASH> |
| | t = <BANG> |
| | t = <CHAR_ENTITY_REF> |
| | t = <CODE_SPAN> |
| | t = <COMMENT_OPEN> |
| | t = <COMMENT_CLOSE> |
| | t = <COLON> |
| | t = <DOUBLE_QUOTE> |
| | t = <EQ> |
| | t = <ESCAPED_CHAR> |
| | t = <GT> |
| | t = <NUMBERING> |
| | t = <NUMERIC_CHAR_REF> |
| | t = <LBRACKET> |
| | t = <LPAREN> |
| | t = <LT> |
| | t = <MINUS> |
| | t = <PLUS> |
| | t = <RBRACKET> |
| | t = <RPAREN> |
| | t = <SHARP> |
| | t = <SINGLE_QUOTE> |
| | t = <SLASH> |
| | t = <STAR> |
| | t = <UNDERSCORE> |
| ) { jjtThis.append(t.image); } |
| | t = <TAB> { jjtThis.append(toWhitespace(prev, t)); } |
| ) { prev = t; } |
| )* |
| } |
| |
| |
| void ResourceDefinition() #ResourceDefinition : { |
| String n = null; |
| Resource resource; |
| } { |
| ( InsignificantWhitespace() )? |
| "[" n = refname() "]" { jjtThis.setId(n); } |
| ( <SPACE> )? ":" |
| ( Whitespace() )? |
| resource = Resource() { jjtThis.setResource(resource); } |
| ( Whitespace() )? |
| } |
| |
| void List() #List : { |
| stack.push(jjtThis); |
| } { |
| ( <SPACE> | <TAB> | <GT> )* |
| Item() |
| ( |
| LOOKAHEAD( {ItemLookahead()} ) <EOL> |
| ( <SPACE> | <TAB> | <GT> )* ( Item() )? |
| )* |
| |
| { |
| stack.pop(); |
| } |
| } |
| |
| void Item() #Item : { |
| stack.push(jjtThis); |
| Token t; |
| } { |
| t = ItemPrefix() |
| { |
| if(t.kind == NUMBERING) { |
| jjtThis.makeOrdered(); |
| } |
| jjtThis.setIndentation(t.beginColumn); |
| } |
| Paragraph() |
| ( |
| ( |
| LOOKAHEAD( {ParagraphLookahead()} ) <EOL> ( LOOKAHEAD( EmptyLine() ) ( Whitespace() )? <EOL> )* Paragraph() { jjtThis.makeLoose(); } |
| | LOOKAHEAD( {LooseLookahead()} ) <EOL> ( Whitespace() )? { jjtThis.makeLoose(); } |
| | LOOKAHEAD( {ListLookahead()} ) <EOL> ( LOOKAHEAD( EmptyLine() ) ( Whitespace() )? <EOL> )* List() |
| ) |
| )* |
| { |
| Item item = (Item)stack.pop(); |
| List list = (List)stack.peek(); |
| if (list.getIndentation() == 0) { |
| list.setIndentation(item.getIndentation()); |
| } |
| } |
| } |
| |
| Token ItemPrefix() : { |
| Token t; |
| } { |
| ( |
| ( |
| t = <PLUS> |
| | t = <MINUS> |
| | t = <STAR> |
| | t = <NUMBERING> |
| ) |
| ( <SPACE> | <TAB> ) |
| ) |
| { return t; } |
| } |
| |
| void Paragraph() #Paragraph : {} { |
| Line() |
| ( LOOKAHEAD( {LineLookahead()} ) <EOL> ( <SPACE> | <TAB> | <GT> )* Line() )* |
| } |
| |
| void Line() #Line : {} { |
| (LOOKAHEAD( {TextLookahead()} ) |
| ( |
| CharRef() |
| | CodeSpan() |
| | LOOKAHEAD( Link() ) Link() |
| | LOOKAHEAD( Image() ) Image() |
| | LOOKAHEAD( InlineURL() ) InlineURL() |
| | LOOKAHEAD( Emphasis() ) Emphasis() |
| | LOOKAHEAD( LineBreak() <EOL> ) LineBreak() |
| | LOOKAHEAD(4) Tag() |
| | Text() |
| ) |
| )+ |
| } |
| |
| void LineBreak() #LineBreak : {} { |
| <SPACE> <SPACE> |
| } |
| |
| void Text() #Text : { |
| Token t; |
| String v; |
| } { |
| v = Anything() { jjtThis.append(v); } |
| } |
| |
| void CharRef() #CharRef : { |
| Token t; |
| } { |
| ( t = <NUMERIC_CHAR_REF> | t = <CHAR_ENTITY_REF> ) { jjtThis.setValue(t.image); } |
| } |
| |
| void CodeSpan() #CodeSpan : { |
| Token t; |
| } { |
| t = <CODE_SPAN> { jjtThis.setText(val(t)); } |
| } |
| |
| void Emphasis() #Emphasis : { |
| StringBuilder buff = new StringBuilder(); |
| Token t; |
| int flag = 1; |
| } { |
| ( |
| <UNDERSCORE> ( <UNDERSCORE> { flag = 2; } ( <UNDERSCORE> { flag = 3; } )? )? |
| ( t = EmphasisText() | t = <STAR> ) { buff.append(t.image); } |
| ( |
| ( <SPACE> { buff.append(" "); } )? |
| ( t = EmphasisText() | t = <STAR> ) { buff.append(t.image); } |
| )* |
| <UNDERSCORE> ( <UNDERSCORE> ( <UNDERSCORE> )? )? |
| | |
| <STAR> ( <STAR> { flag = 2; } ( <STAR> { flag = 3; } )? )? |
| ( t = EmphasisText() | t = <UNDERSCORE> ) { buff.append(t.image); } |
| ( |
| ( <SPACE> { buff.append(" "); } )? |
| ( t = EmphasisText() | t = <UNDERSCORE> ) { buff.append(t.image); } |
| )* |
| <STAR> ( <STAR> ( <STAR> )? )? |
| ) { |
| jjtThis.setText(buff.toString()); |
| if (flag == 2) { |
| jjtThis.makeBold(); |
| } else if (flag == 3) { |
| jjtThis.makeItalicAndBold(); |
| } |
| } |
| } |
| |
| void Comment() #Comment : { |
| StringBuilder buff = new StringBuilder(); |
| String v; |
| Token t; |
| } { |
| <COMMENT_OPEN> |
| ( |
| ( |
| LOOKAHEAD( {getToken(1).none(EOL,COMMENT_CLOSE)} ) v = Anything() { buff.append(v); } |
| | t = <EOL> { buff.append(t.image); } |
| ) |
| )* |
| { jjtThis.setText(buff.toString()); } |
| <COMMENT_CLOSE> |
| } |
| |
| void InlineURL() #InlineUrl : { |
| Token t; |
| StringBuilder buff = new StringBuilder(); |
| } { |
| "<" |
| t = <CHAR_SEQUENCE> { buff.append(t.image); } |
| ":" { buff.append(":"); } |
| ( "/" { buff.append("/"); } )* |
| t = <CHAR_SEQUENCE> { buff.append(t.image); } |
| ( |
| ( |
| t = <CHAR_SEQUENCE> |
| | t = <AMPERSAND> |
| | t = <BACKSLASH> |
| | t = <COLON> |
| | t = <EQ> |
| | t = <LBRACKET> |
| | t = <LPAREN> |
| | t = <MINUS> |
| | t = <RBRACKET> |
| | t = <RPAREN> |
| | t = <SHARP> |
| | t = <SLASH> |
| | t = <UNDERSCORE> |
| ) { buff.append(t.image); } |
| )* |
| ">" |
| { jjtThis.setUrl(buff.toString()); } |
| } |
| |
| void Link() #Link : { |
| String text, reference = ""; |
| Resource resource = null; |
| } { |
| "[" |
| ( |
| LinkBody() |
| )+ |
| "]" |
| ( |
| LOOKAHEAD(3) |
| ( |
| ( <SPACE> { jjtThis.setWhitespaceAtMiddle(); } )? ( <EOL> )? |
| "[" |
| ( reference = refname() )? |
| { jjtThis.setReference(reference); } |
| "]" |
| | |
| "(" |
| ( Whitespace() )? |
| ( resource = Resource() ( Whitespace() )? )? |
| { jjtThis.setResource(resource); } |
| ")" |
| ) |
| )? |
| } |
| |
| void Image() #Image : { |
| String text, reference; |
| Resource resource = null; |
| } { |
| "!" "[" |
| text = refname() { jjtThis.setText(text); } |
| "]" |
| ( |
| ( <SPACE> )? |
| "[" |
| reference = refname() { jjtThis.setReference(reference); } |
| "]" |
| | |
| "(" |
| ( Whitespace() )? |
| (resource = Resource() ( Whitespace() )? )? |
| { jjtThis.setResource(resource); } |
| ")" |
| )? |
| } |
| |
| void Tag() #Tag : { |
| Token t; |
| TagAttribute attribute; |
| } { |
| "<" t = <CHAR_SEQUENCE> { jjtThis.setName(t.image); } |
| ( LOOKAHEAD(2) ( <SPACE> )+ attribute = TagAttribute() { jjtThis.addAttribute(attribute); } )* ( <SPACE> )* |
| ( |
| LOOKAHEAD(2) |
| "/" ">" |
| | |
| try { |
| ">" |
| ( LOOKAHEAD(2) ( TextNode() | Tag() ) )* |
| "<" "/" <CHAR_SEQUENCE> ( <SPACE> )* ">" |
| } catch (ParseException e) { |
| // failsafe |
| } |
| ) |
| } |
| |
| TagAttribute TagAttribute() : { |
| StringBuilder buff = new StringBuilder(); |
| Token name; |
| Token t; |
| } { |
| name = <CHAR_SEQUENCE> "=" |
| ( |
| "\"" |
| ( |
| ( |
| t = TagAttributeText() |
| | t = "'" |
| ) { buff.append(t.image); } |
| )* |
| "\"" |
| | |
| "'" |
| ( |
| ( |
| t = TagAttributeText() |
| | t = "\"" |
| ) { buff.append(t.image); } |
| )* |
| "'" |
| ) |
| { |
| return new TagAttribute(name.image, buff.toString()); |
| } |
| } |
| |
| void TagOpen() : {} { |
| "<" <CHAR_SEQUENCE> ( ( <SPACE> )+ TagAttribute() )* ( <SPACE> )* ( "/" )? ">" |
| } |
| |
| String refname() : { |
| Token t; |
| StringBuilder buff = new StringBuilder(); |
| } { |
| ( |
| ( |
| t = <CHAR_SEQUENCE> |
| | t = <SPACE> |
| | t = <AMPERSAND> |
| | t = <BACKSLASH> |
| | t = <COLON> |
| | t = <EQ> |
| | t = <GT> |
| | t = <LBRACKET> |
| | t = <LPAREN> |
| | t = <LT> |
| | t = <RPAREN> |
| | t = <SLASH> |
| | t = <TAB> |
| | t = <UNDERSCORE> |
| ) { buff.append(t.image); } |
| )+ |
| { return buff.toString(); } |
| } |
| |
| Resource Resource() : { |
| String url; |
| String hint = null; |
| } { |
| url = url() |
| ( |
| Whitespace() |
| ( hint = title() )? |
| )? |
| { return new Resource(url, hint); } |
| } |
| |
| String url() : { |
| String text; |
| } { |
| ( |
| "<" |
| text = urltext() |
| ">" |
| | |
| text = urltext() |
| ) |
| { return text; } |
| } |
| |
| String urltext() : { |
| Token t; |
| StringBuilder buff = new StringBuilder(); |
| } { |
| ( |
| ( |
| t = <CHAR_SEQUENCE> |
| | t = <AMPERSAND> |
| | t = <BACKSLASH> |
| | t = <COLON> |
| | t = <EQ> |
| | t = <LBRACKET> |
| | t = <LPAREN> { parentheses++; } |
| | t = <MINUS> |
| | t = <RBRACKET> |
| | LOOKAHEAD({parentheses > 0}) t = <RPAREN> { parentheses--; } |
| | t = <SHARP> |
| | t = <SLASH> |
| | t = <UNDERSCORE> |
| ) { buff.append(t.image); } |
| ) + |
| { parentheses = 0; return buff.toString(); } |
| } |
| |
| String title() : { |
| String text; |
| } { |
| ( |
| ( |
| "\"" |
| text = titletext(DOUBLE_QUOTE) |
| "\"" |
| ) |
| | |
| ( |
| "'" |
| text = titletext(SINGLE_QUOTE) |
| "'" |
| ) |
| ) |
| { return text; } |
| } |
| |
| String titletext(int quoteType) : { |
| StringBuilder buff = new StringBuilder(); |
| Token t; |
| } { |
| ( |
| LOOKAHEAD( {QuoteInsideTitleLookahead(quoteType)} ) |
| ( |
| t = <CHAR_SEQUENCE> |
| | t = <SPACE> |
| | t = <AMPERSAND> |
| | t = <BACKSLASH> |
| | t = <DOUBLE_QUOTE> |
| | t = <LPAREN> |
| | t = <RPAREN> |
| | t = <SINGLE_QUOTE> |
| | t = <SLASH> |
| | t = <TAB> |
| | t = <UNDERSCORE> |
| ) { buff.append(t.image); } |
| )* |
| { return buff.toString(); } |
| } |
| |
| String Anything() : { |
| Token t; |
| } { |
| ( |
| t = <CHAR_SEQUENCE> |
| | t = <SPACE> |
| | t = <AMPERSAND> |
| | t = <BACKSLASH> |
| | t = <BACKTICK> |
| | t = <BANG> |
| | t = <COLON> |
| | t = <COMMENT_CLOSE> |
| | t = <COMMENT_OPEN> |
| | t = <DOUBLE_QUOTE> |
| | t = <EQ> |
| | t = <ESCAPED_CHAR> |
| | t = <GT> |
| | t = <LBRACKET> |
| | t = <LPAREN> |
| | t = <LT> |
| | t = <MINUS> |
| | t = <NUMBERING> |
| | t = <PLUS> |
| | t = <RBRACKET> |
| | t = <RPAREN> |
| | t = <SHARP> |
| | t = <SINGLE_QUOTE> |
| | t = <SLASH> |
| | t = <STAR> |
| | t = <TAB> |
| | t = <UNDERSCORE> |
| ) { return val(t); } |
| } |
| |
| Token EmphasisText() : { |
| Token t; |
| } { |
| ( |
| t = <CHAR_SEQUENCE> |
| | t = <AMPERSAND> |
| | t = <BACKSLASH> |
| | t = <BACKTICK> |
| | t = <BANG> |
| | t = <COLON> |
| | t = <COMMENT_CLOSE> |
| | t = <COMMENT_OPEN> |
| | t = <DOUBLE_QUOTE> |
| | t = <EQ> |
| | t = <ESCAPED_CHAR> |
| | t = <GT> |
| | t = <LBRACKET> |
| | t = <LPAREN> |
| | t = <LT> |
| | t = <MINUS> |
| | t = <NUMBERING> |
| | t = <PLUS> |
| | t = <RBRACKET> |
| | t = <RPAREN> |
| | t = <SHARP> |
| | t = <SINGLE_QUOTE> |
| | t = <SLASH> |
| | t = <TAB> |
| ) { return t; } |
| } |
| |
| void LinkBody() : {} { |
| CharRef() |
| | CodeSpan() |
| | LOOKAHEAD( Emphasis() ) Emphasis() |
| | LOOKAHEAD( InlineURL() ) InlineURL() |
| | LOOKAHEAD( Link() ) Link() |
| | LOOKAHEAD( Image() ) Image() |
| | LinkText() |
| } |
| |
| void LinkText() #Text : { |
| Token t; |
| } { |
| ( |
| t = <CHAR_SEQUENCE> |
| | t = <SPACE> |
| | t = <AMPERSAND> |
| | t = <BACKSLASH> |
| | t = <BACKTICK> |
| | t = <BANG> |
| | t = <COLON> |
| | t = <COMMENT_CLOSE> |
| | t = <COMMENT_OPEN> |
| | t = <DOUBLE_QUOTE> |
| | t = <EOL> |
| | t = <EQ> |
| | t = <ESCAPED_CHAR> |
| | t = <GT> |
| | t = <LPAREN> |
| | t = <LT> |
| | t = <MINUS> |
| | t = <NUMBERING> |
| | t = <PLUS> |
| | t = <RPAREN> |
| | t = <SHARP> |
| | t = <SINGLE_QUOTE> |
| | t = <SLASH> |
| | t = <STAR> |
| | t = <TAB> |
| | t = <UNDERSCORE> |
| ) { jjtThis.append(t.image); } |
| } |
| |
| Token TagAttributeText() : { |
| Token t; |
| } { |
| ( |
| t = <CHAR_SEQUENCE> |
| | t = <SPACE> |
| | t = <AMPERSAND> |
| | t = <BACKSLASH> |
| | t = <BACKTICK> |
| | t = <BANG> |
| | t = <CODE_SPAN> |
| | t = <COLON> |
| | t = <EOL> |
| | t = <EQ> |
| | t = <ESCAPED_CHAR> |
| | t = <GT> |
| | t = <LPAREN> |
| | t = <MINUS> |
| | t = <NUMBERING> |
| | t = <PLUS> |
| | t = <RPAREN> |
| | t = <SHARP> |
| | t = <SLASH> |
| | t = <STAR> |
| | t = <TAB> |
| | t = <UNDERSCORE> |
| ) { return t; } |
| } |
| |
| void TextNode() #Text : { |
| Token t; |
| } { |
| ( |
| t = <CHAR_SEQUENCE> |
| | t = <SPACE> |
| | t = <AMPERSAND> |
| | t = <BACKSLASH> |
| | t = <BACKTICK> |
| | t = <BANG> |
| | t = <CODE_SPAN> |
| | t = <COLON> |
| | t = <COMMENT_CLOSE> |
| | t = <COMMENT_OPEN> |
| | t = <DOUBLE_QUOTE> |
| | t = <EQ> |
| | t = <EOL> |
| | t = <ESCAPED_CHAR> |
| | t = <GT> |
| | t = <LBRACKET> |
| | t = <LPAREN> |
| | t = <MINUS> |
| | t = <NUMBERING> |
| | t = <PLUS> |
| | t = <RBRACKET> |
| | t = <RPAREN> |
| | t = <SHARP> |
| | t = <SINGLE_QUOTE> |
| | t = <SLASH> |
| | t = <STAR> |
| | t = <TAB> |
| | t = <UNDERSCORE> |
| ) { jjtThis.append(t.image); } |
| } |