| 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 == EMPHASIS_BOLD || (t.kind == CODE_SPAN && i.startsWith("``"))) { |
| i = i.substring(2, i.length() - 2); |
| } else if (t.any(CODE_SPAN, EMPHASIS_ITALIC)) { |
| i = i.substring(1, i.length() - 1); |
| } else if (t.any(EMPHASIS_ITALIC_BOLD)) { |
| i = i.substring(3, i.length() - 3); |
| } 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, EOL)); |
| |
| Item item = (Item)stack.peek(); |
| |
| return newline && t.any(PLUS, MINUS, STAR, NUMBERING) && 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; |
| } |
| |
| 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) && list.getIndentation() == t.beginColumn; |
| } |
| |
| 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); |
| } |
| } |
| 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 : "*" > |
| } |
| |
| TOKEN : { |
| < MINUS_RULER : "-" ( (" "){0,2} )? "-" ( ( (" "){0,2} )? "-" )+ > |
| | < STAR_RULER : "*" ( (" "){0,2} )? "*" ( ( (" "){0,2} )? "*" )+ > |
| | < UNDERSCORE_RULER : "_" ( (" "){0,2} )? "_" ( ( (" "){0,2} )? "_" )+ > |
| } |
| |
| TOKEN : { |
| < COMMENT_OPEN : "<!--" > |
| | < COMMENT_CLOSE : "-->" > |
| } |
| |
| TOKEN : { |
| < CODE_SPAN : "`" ( ~["`", "\r", "\n"] )+ "`" | "`" "`" ( ~["'", "\r", "\n"] )+ "`" "`" > |
| | < EMPHASIS_ITALIC : "*" <EMP_A> ( ( ~["*", "\r", "\n"] )* <EMP_A> )? "*" |
| | "_" <EMP_U> ( ( ~["_", "\r", "\n"] )* <EMP_U> )? "_"> |
| | < EMPHASIS_BOLD : "**" <EMP_A> ( ( ~["*", "\r", "\n"] )* <EMP_A> )? "**" |
| | "__" <EMP_U> ( ( ~["_", "\r", "\n"] )* <EMP_U> )? "__"> |
| | < EMPHASIS_ITALIC_BOLD : "***" <EMP_A> ( ( ~["*", "\r", "\n"] )* <EMP_A> )? "***" |
| | "___" <EMP_U> ( ( ~["_", "\r", "\n"] )* <EMP_U> )? "___"> |
| | < NUMBERING : ( ["0"-"9"] )+ "." > |
| | < #EMP_A : ~["*", " ", "\t", "\r", "\n"] > |
| | < #EMP_U : ~["_", " ", "\t", "\r", "\n"] > |
| } |
| |
| 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() ) DocumentElement() | BlockElement() |
| } |
| |
| void DocumentElement() : {} { |
| ResourceDefinition() |
| } |
| |
| void BlockElement() : {} { |
| LOOKAHEAD( Header() ( <EOL> | <EOF> ) ) Header() |
| | LOOKAHEAD( EmptyLine() ) Whitespace() |
| | LOOKAHEAD( Ruler() ( <EOL> | <EOF> ) ) Ruler() |
| | LOOKAHEAD( CodeLine() ) Code() |
| | LOOKAHEAD( QuotePrefix() ) Quote() |
| | LOOKAHEAD( ( InsignificantWhitespace() )? ( <PLUS> | <MINUS> | <STAR> | <NUMBERING> ) ( <SPACE> | <TAB> ) ) List() |
| | LOOKAHEAD( Comment() ) Comment() |
| | Paragraph() |
| } |
| |
| 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_RULER > { level = 2; } |
| | < MINUS > { level = 2; } |
| ) |
| { |
| return level; |
| } |
| } |
| |
| void Ruler() #Ruler : {} { |
| ( InsignificantWhitespace() )? ( <UNDERSCORE_RULER> | <MINUS_RULER> | <STAR_RULER> ) ( 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() : {} { |
| ( InsignificantWhitespace() )? <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 = <AMPERSAND> |
| | t = <BACKTICK> |
| | t = <BACKSLASH> |
| | t = <BANG> |
| | t = <CHAR_ENTITY_REF> |
| | t = <CHAR_SEQUENCE> |
| | t = <CODE_SPAN> |
| | t = <COMMENT_OPEN> |
| | t = <COMMENT_CLOSE> |
| | t = <COLON> |
| | t = <DOUBLE_QUOTE> |
| | t = <EMPHASIS_ITALIC> |
| | t = <EMPHASIS_BOLD> |
| | t = <EMPHASIS_ITALIC_BOLD> |
| | t = <EQ> |
| | t = <ESCAPED_CHAR> |
| | t = <GT> |
| | t = <NUMBERING> |
| | t = <NUMERIC_CHAR_REF> |
| | t = <LBRACKET> |
| | t = <LPAREN> |
| | t = <LT> |
| | t = <MINUS> |
| | t = <MINUS_RULER> |
| | t = <PLUS> |
| | t = <RBRACKET> |
| | t = <RPAREN> |
| | t = <SHARP> |
| | t = <SINGLE_QUOTE> |
| | t = <SLASH> |
| | t = <SPACE> |
| | t = <STAR> |
| | t = <STAR_RULER> |
| | t = <UNDERSCORE_RULER> |
| ) { jjtThis.append(t.image); } |
| | t = <TAB> { jjtThis.append(toWhitespace(prev, t)); } |
| ) { prev = t; } |
| )* |
| } |
| |
| |
| void ResourceDefinition() #ResourceDefinition : { |
| String n = null; |
| Resource resource; |
| } { |
| ( <SPACE> ( <SPACE> ( <SPACE> )? )? )? |
| "[" n = refname() "]" { jjtThis.setId(n); } |
| ( <SPACE> )? ":" |
| ( Whitespace() )? |
| resource = Resource() { jjtThis.setResource(resource); } |
| } |
| |
| 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 = <PLUS> |
| | t = <MINUS> |
| | t = <STAR> |
| | t = <NUMBERING> { jjtThis.makeOrdered(); } |
| ) |
| ( <SPACE> | <TAB> ) |
| ) { jjtThis.setIndentation(t.beginColumn); } |
| Paragraph() |
| ( |
| LOOKAHEAD( {ParagraphLookahead()} ) <EOL> ( LOOKAHEAD( EmptyLine() ) ( Whitespace() )? <EOL> )* Paragraph() { jjtThis.makeLoose(); } |
| | LOOKAHEAD( {ListLookahead()} ) <EOL> ( LOOKAHEAD( EmptyLine() ) ( Whitespace() )? <EOL> )* List() |
| | LOOKAHEAD( {LooseLookahead()} ) <EOL> ( Whitespace() )? { jjtThis.makeLoose(); } |
| )* |
| { |
| Item item = (Item)stack.pop(); |
| List list = (List)stack.peek(); |
| if (list.getIndentation() == 0) { |
| list.setIndentation(item.getIndentation()); |
| } |
| } |
| } |
| |
| void Paragraph() #Paragraph : {} { |
| Line() |
| ( LOOKAHEAD( {LineLookahead()} ) <EOL> ( <SPACE> | <TAB> | <GT> )* Line() )* |
| } |
| |
| void Line() #Line : {} { |
| (LOOKAHEAD( {TextLookahead()} ) |
| ( |
| CharRef() |
| | CodeSpan() |
| | Emphasis() |
| | LOOKAHEAD( InlineURL() ) InlineURL() |
| | LOOKAHEAD( Tag() ) Tag() |
| | LOOKAHEAD( Image() ) Image() |
| | LOOKAHEAD( Link() ) Link() |
| | Text() |
| ) |
| )+ |
| } |
| |
| 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 : { |
| Token t; |
| } { |
| t = <EMPHASIS_ITALIC> { jjtThis.makeItalic(val(t)); } |
| | t = <EMPHASIS_BOLD> { jjtThis.makeBold(val(t)); } |
| | t = <EMPHASIS_ITALIC_BOLD> { jjtThis.makeItalicAndBold(val(t)); } |
| } |
| |
| 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> { buff.append(t.image); } |
| | "/" { buff.append("/"); } |
| | "&" { buff.append("&"); } |
| | "=" { buff.append("="); } |
| )* |
| ">" |
| { jjtThis.setUrl(buff.toString()); } |
| } |
| |
| void Link() #Link : { |
| String text, reference = ""; |
| Resource resource = null; |
| } { |
| "[" |
| ( |
| CharRef() |
| | CodeSpan() |
| | Emphasis() |
| | LOOKAHEAD( InlineURL() ) InlineURL() |
| | LOOKAHEAD( Image() ) Image() |
| | LOOKAHEAD( Link() ) Link() |
| | LOOKAHEAD( {getToken(1).none(RBRACKET, EOL, EOF)} ) Text() |
| | <EOL> #Text { ((Text)jjtree.peekNode()).append("\n"); } |
| )+ |
| "]" |
| ( |
| LOOKAHEAD(3) |
| ( |
| ( <SPACE> { jjtThis.setWhitespaceAtMiddle(); } )? ( <EOL> )? |
| "[" |
| ( reference = refname() )? |
| { jjtThis.setReference(reference); } |
| "]" |
| | |
| "(" |
| ( 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); } |
| "]" |
| | |
| "(" |
| (resource = Resource() { jjtThis.setResource(resource); })? |
| ( Whitespace() )? |
| ")" |
| )? |
| } |
| |
| void Tag() : { |
| Token t; |
| TagAttribute attribute; |
| java.util.List<TagAttribute> attributes = new java.util.ArrayList<TagAttribute>(); |
| } { |
| ( |
| LOOKAHEAD(2) |
| "<" "/" t = <CHAR_SEQUENCE> <GT> #ClosingTag |
| { |
| ClosingTag closing = ((ClosingTag)jjtree.peekNode()); |
| closing.setName(t.image); |
| if (markupStack.size() > 0) { |
| OpeningTag opening = (OpeningTag)markupStack.peek(); |
| if (opening.getName().equals(closing.getName())) { |
| opening.setClosingTag(closing); |
| markupStack.pop(); |
| } else { |
| markupStack.clear(); |
| } |
| } |
| } |
| | |
| "<" t = <CHAR_SEQUENCE> |
| ( |
| LOOKAHEAD( ( <SPACE> )+ <CHAR_SEQUENCE> ) |
| ( <SPACE> )+ attribute = TagAttribute() { attributes.add(attribute); } |
| )* ( <SPACE> )* |
| ( |
| "/" ">" #EmptyTag { EmptyTag emptytag = (EmptyTag)jjtree.peekNode(); emptytag.setName(t.image); emptytag.setAttributes(attributes); } |
| | ">" #OpeningTag { OpeningTag opening = (OpeningTag)jjtree.peekNode(); opening.setName(t.image); opening.setAttributes(attributes); markupStack.push(opening); }) |
| ) |
| } |
| |
| TagAttribute TagAttribute() : { |
| StringBuilder buff = new StringBuilder(); |
| Token attrName; |
| Token t; |
| } { |
| attrName = <CHAR_SEQUENCE> "=" |
| ( |
| "\"" |
| ( |
| ( |
| t = <CODE_SPAN> |
| | t = <ESCAPED_CHAR> |
| | t = <SPACE> |
| | t = <TAB> |
| | t = <CHAR_SEQUENCE> |
| | t = "&" |
| | t = "(" |
| | t = ")" |
| | t = "<" |
| | t = ">" |
| | t = "/" |
| | t = "\\" |
| | t = "'" |
| | t = "`" |
| |
| ) { buff.append(t.image); } |
| )* |
| "\"" |
| | |
| "'" |
| ( |
| ( |
| t = <CODE_SPAN> |
| | t = <ESCAPED_CHAR> |
| | t = <SPACE> |
| | t = <TAB> |
| | t = <CHAR_SEQUENCE> |
| | t = "&" |
| | t = "(" |
| | t = ")" |
| | t = "<" |
| | t = ">" |
| | t = "/" |
| | t = "\\" |
| | t = "\"" |
| | t = "`" |
| |
| ) { buff.append(t.image); } |
| )* |
| "'" |
| ) |
| { |
| return new TagAttribute(attrName.image, buff.toString()); |
| } |
| } |
| |
| String refname() : { |
| Token t; |
| StringBuilder buff = new StringBuilder(); |
| } { |
| ( |
| ( |
| t = <AMPERSAND> |
| | t = <BACKSLASH> |
| | t = <COLON> |
| | t = <EQ> |
| | t = <GT> |
| | t = <LBRACKET> |
| | t = <LPAREN> |
| | t = <LT> |
| | t = <RPAREN> |
| | t = <SLASH> |
| | t = <SPACE> |
| | t = <TAB> |
| | t = <CHAR_SEQUENCE> |
| ) { 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 = "&" |
| | t = "(" { parentheses++; } |
| | LOOKAHEAD({parentheses > 0}) t = ")" { parentheses--; } |
| | t = "[" |
| | t = "]" |
| | t = ":" |
| | t = "/" |
| | t = "\\" |
| | t = "#" |
| | t = "=" |
| ) { 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 = <TAB> |
| | t = "&" |
| | t = "(" |
| | t = ")" |
| | t = "/" |
| | t = "\\" |
| | t = "'" |
| | t = "\"" |
| ) { buff.append(t.image); } |
| )* |
| { return buff.toString(); } |
| } |
| |
| String Anything() : { |
| Token t; |
| } { |
| ( |
| t = <AMPERSAND> |
| | t = <BACKSLASH> |
| | t = <BACKTICK> |
| | t = <BANG> |
| | t = <CHAR_SEQUENCE> |
| | t = <COMMENT_CLOSE> |
| | t = <COMMENT_OPEN> |
| | t = <COLON> |
| | t = <DOUBLE_QUOTE> |
| | t = <EQ> |
| | t = <ESCAPED_CHAR> { t.image = val(t); } |
| | t = <GT> |
| | t = <LBRACKET> |
| | t = <LPAREN> |
| | t = <LT> |
| | t = <MINUS> |
| | t = <MINUS_RULER> |
| | t = <NUMBERING> |
| | t = <PLUS> |
| | t = <RBRACKET> |
| | t = <RPAREN> |
| | t = <SHARP> |
| | t = <SINGLE_QUOTE> |
| | t = <SLASH> |
| | t = <SPACE> |
| | t = <STAR> |
| | t = <STAR_RULER> |
| | t = <TAB> |
| | t = <UNDERSCORE_RULER> |
| ) { return t.image; } |
| } |