org.sweble.wikitext.lazy.parser.Section.rats Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of swc-parser-lazy Show documentation
Show all versions of swc-parser-lazy Show documentation
A parser for MediaWiki's Wikitext.
/**
* Copyright 2011 The Open Source Research Group,
* University of Erlangen-Nürnberg
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*!
*
* Section Heading
* ---------------
*
* Grammar:
* - '='+ Title '='+ Space* EolOrEof
*
* The title can contain:
* - ExternalLink
* - InternalLink
* - MagicWord
* - ParserEntity
* - PlainExternalLink
* - Signature
* - Ticks
* - XmlElement
* - XmlReference
*
* The title cannot contain:
* - Newline
* - Tables
* - Headings
* - Horizontal lines
* - Block level elements
*
* The title can not contain (syntactically):
* - Newlines
*
* AST node:
* Name : Heading
* Extends : ContentNode
* Constructor : "content, level"
* NodeType : org.sweble.wikitext.lazy.AstNodeTypes.NT_HEADING
*
* Properties:
* level : int
*
* Section
* -------
*
* AST node:
* Name : Section
* Extends : InnerNode.InnerNode2
* Constructor : "level, title, body"
* NodeType : org.sweble.wikitext.lazy.AstNodeTypes.NT_SECTION
*
* Properties:
* level : int
*
* Children:
* title : NodeList
* body : NodeList
*
*/
module org.sweble.wikitext.lazy.parser.Section;
import org.sweble.wikitext.lazy.utils.Warnings;
import org.sweble.wikitext.lazy.parser.Content;
import org.sweble.wikitext.lazy.parser.Whitespace;
// -- Heading ------------------------------------------------------------------
header
{
import java.util.Stack;
}
body
{
private Heading createHeading(
int spanFrom,
Result spanTo,
AstNode rt0,
int oCount,
NodeList title,
int cCount,
AstNode rt1)
{
int oOdd = 0;
int cOdd = 0;
if (oCount > 6)
{
oOdd = oCount - 6;
oCount = 6;
}
if (cCount > 6)
{
cOdd = cCount - 6;
cCount = 6;
}
int level;
if (cCount > oCount)
{
level = oCount;
cOdd += cCount - oCount;
cCount -= cCount - oCount;
}
else
{
level = cCount;
oOdd += oCount - cCount;
oCount -= oCount - cCount;
}
Heading heading = new Heading(title, level);
Text oOddText = null;
if (oOdd > 0)
{
if (isWarningLevelEnabled(WS_NORMAL))
fileOddSyntaxWarning(
heading,
makeSpan(spanFrom, spanTo),
WS_NORMAL,
"Odd number of opening equals");
oOddText = new Text(StringUtils.strrep('=', oOdd));
}
Text cOddText = null;
if (cOdd > 0)
{
if (isWarningLevelEnabled(WS_NORMAL))
fileOddSyntaxWarning(
heading,
makeSpan(spanFrom, spanTo),
WS_NORMAL,
"Odd number of closing equals");
cOddText = new Text(StringUtils.strrep('=', cOdd));
}
heading.setContent(new NodeList(oOddText, title, cOddText));
if (isGatherRtData())
{
String equals = StringUtils.strrep('=', level);
addRtData(heading,
joinRt(rt0, equals),
joinRt(equals, rt1));
}
return heading;
}
private void fixSectionMetadata(Heading heading, Section section)
{
RtData rtd = (RtData) heading.getAttribute("RTD");
if (rtd != null)
{
Object[][] newRts = new Object[3][];
newRts[0] = rtd.getRts()[0];
newRts[1] = rtd.getRts()[1];
newRts[2] = null;
section.setAttribute("RTD", new RtData(newRts));
}
Object warnings = heading.getAttribute("warnings");
if (warnings != null)
section.setAttribute("warnings", warnings);
}
private AstNode makeSections(Section first, Pair tail)
{
Stack stack = new Stack();
stack.push(first);
NodeList result = new NodeList(first);
Pair i = tail;
while (!i.isEmpty())
{
Section s = i.head();
while (!stack.isEmpty() && s.getLevel() <= stack.peek().getLevel())
stack.pop();
if (stack.isEmpty())
{
result.add(s);
}
else
{
// TODO: Dangerous! We must clone the section instead!
stack.peek().setBody(new NodeList(stack.peek().getBody(), s));
}
stack.push(s);
i = i.tail();
}
return result;
}
}
// -- Sections --[ State Aware Memoization ]------------------------------------
noinline transient AstNode Sections =
^{
StateAwareResult r = (StateAwareResult) pSectionsMemoized(yyBase);
final LazyParserContext context = getContext();
Result yyResult = r.getResult(context);
if (yyResult == null)
yyResult = r.setResult(context, pSectionsTransient(yyBase));
if (returnTrue(r))
return yyResult;
}
;
noinline memoized AstNode SectionsMemoized =
^{
Result yyResult = new StateAwareResult("Sections", getContext(), pSectionsTransient(yyBase));
if (returnTrue(yyResult))
return yyResult;
}
;
// -- Sections -----------------------------------------------------------------
noinline transient AstNode SectionsTransient =
&{ accept(ParserAtoms.SECTIONS) } first:Section tail:Section*
{
yyValue = makeSections(first, tail);
}
;
inline void InlineContentStopperHeading =
&{ inScope(ParserScopes.SECTION_HEADING) } EqualsStr pExtSpaceStar slEolOrEof
;
inline void BlockStopperNextSection =
&{ inScope(ParserScopes.SECTION_BODY) } Heading
;
// -- Section ------------------------------------------------------------------
private noinline transient Section Section =
h:Heading Eof
{
yyValue = new Section(h.getLevel(), h.getContent(), new NodeList());
fixSectionMetadata(h, yyValue);
}
/ h:Heading body:SectionContentStar
{
yyValue = new Section(h.getLevel(), h.getContent(), body);
fixSectionMetadata(h, yyValue);
}
;
// -- Heading --[ State Aware Memoization ]-------------------------------------
noinline transient Heading Heading =
^{
StateAwareResult r = (StateAwareResult) pHeadingMemoized(yyBase);
final LazyParserContext context = getContext();
Result yyResult = r.getResult(context);
if (yyResult == null)
yyResult = r.setResult(context, pHeadingTransient(yyBase));
if (returnTrue(r))
return yyResult;
}
;
noinline memoized Heading HeadingMemoized =
^{
Result yyResult = new StateAwareResult("Heading", getContext(), pHeadingTransient(yyBase));
if (returnTrue(yyResult))
return yyResult;
}
;
// -- Heading ------------------------------------------------------------------
noinline transient Heading HeadingTransient =
rt0:pTpStar open:EqualsStr heading:HeadingContentStar close:EqualsStr rt1:pExtSpaceStar &slEolOrEof
{
// TODO: add warning productions
yyValue = createHeading(yyStart, yyResult, rt0, open.length(), heading, close.length(), rt1);
}
;
private transient String EqualsStr = "="+ ;
// -- Content ------------------------------------------------------------------
private inline stateful NodeList HeadingContentStar =
{
enter(ParserScopes.SECTION_HEADING);
}
InlineContentPlus
;
private inline stateful NodeList SectionContentStar =
{
enter(ParserScopes.SECTION_BODY);
}
BlockContent
;
// -- End of file --------------------------------------------------------------