blob: 1df9fc1eca0d650bf20c70f23f4a42572f2b7a94 [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* 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.
*/
package com.jetbrains.rest.parsing;
import com.intellij.lang.ASTNode;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiParser;
import com.intellij.psi.tree.IElementType;
import com.jetbrains.rest.RestElementTypes;
import com.jetbrains.rest.RestTokenTypes;
import org.jetbrains.annotations.NotNull;
/**
* User : catherine
*/
public class RestParser implements PsiParser {
@NotNull
public ASTNode parse(IElementType root, PsiBuilder builder) {
final PsiBuilder.Marker rootMarker = builder.mark();
while (!builder.eof()) {
IElementType type = builder.getTokenType();
if (type == RestTokenTypes.EXPLISIT_MARKUP_START) {
builder.advanceLexer();
parseMarkup(builder);
}
else if (type == RestTokenTypes.REFERENCE_NAME || type == RestTokenTypes.SUBSTITUTION) {
PsiBuilder.Marker marker = builder.mark();
builder.advanceLexer();
marker.done(RestTokenTypes.REFERENCE_NAME);
}
else if (type == RestTokenTypes.TITLE) {
PsiBuilder.Marker marker = builder.mark();
builder.advanceLexer();
marker.done(RestTokenTypes.TITLE);
}
else if (type == RestTokenTypes.FIELD) {
parseFieldList(builder);
}
else if (type == RestTokenTypes.INLINE_LINE) {
PsiBuilder.Marker marker = builder.mark();
builder.advanceLexer();
marker.done(RestElementTypes.INLINE_BLOCK);
}
else if (type == RestTokenTypes.ANONYMOUS_HYPERLINK) {
PsiBuilder.Marker marker = builder.mark();
builder.advanceLexer();
marker.done(RestElementTypes.REFERENCE_TARGET);
}
else if (type == RestTokenTypes.LINE) {
parseLineText(builder, type);
}
else
builder.advanceLexer();
}
rootMarker.done(root);
return builder.getTreeBuilt();
}
private static boolean parseLineText(PsiBuilder builder, IElementType type) {
PsiBuilder.Marker marker = builder.mark();
boolean gotLine = false;
while (type == RestTokenTypes.LINE || type == RestTokenTypes.WHITESPACE) {
builder.advanceLexer();
type = builder.getTokenType();
gotLine = true;
}
if (gotLine)
marker.done(RestElementTypes.LINE_TEXT);
else
marker.drop();
return gotLine;
}
private static void parseFieldList(PsiBuilder builder) {
PsiBuilder.Marker listMarker = builder.mark();
PsiBuilder.Marker marker = builder.mark();
builder.advanceLexer();
marker.done(RestTokenTypes.FIELD);
if (parseLineText(builder, builder.getTokenType()))
listMarker.done(RestElementTypes.FIELD_LIST);
else
listMarker.drop();
}
private static void parseMarkup(PsiBuilder builder) {
PsiBuilder.Marker marker = builder.mark();
IElementType type = builder.getTokenType();
if (type == RestTokenTypes.SUBSTITUTION) {
builder.advanceLexer();
marker.done(RestElementTypes.REFERENCE_TARGET);
builder.advanceLexer();
marker = builder.mark();
type = builder.getTokenType();
}
if (type == RestTokenTypes.DIRECTIVE) {
gotoNextWhiteSpaces(builder);
if (builder.getTokenType() != RestTokenTypes.WHITESPACE) {
builder.advanceLexer();
marker.done(RestElementTypes.DIRECTIVE_BLOCK);
return;
}
skipBlankLines(builder);
if (builder.getTokenType() != RestTokenTypes.WHITESPACE || "\n".equals(builder.getTokenText())) {
marker.done(RestElementTypes.DIRECTIVE_BLOCK);
return;
}
String white = builder.getTokenText();
parseDirective(builder, white, marker);
}
else if (type == RestTokenTypes.FOOTNOTE || type == RestTokenTypes.CITATION ||
type == RestTokenTypes.HYPERLINK || type == RestTokenTypes.ANONYMOUS_HYPERLINK) {
builder.advanceLexer();
marker.done(RestElementTypes.REFERENCE_TARGET);
}
else {
builder.advanceLexer();
marker.drop();
}
}
private static void gotoNextWhiteSpaces(PsiBuilder builder) {
while(!"\n".equals(builder.getTokenText()) && !(builder.getTokenType() == RestTokenTypes.TITLE) && !builder.eof() && (builder.getTokenType() != null)) {
builder.advanceLexer();
}
}
private static void skipBlankLines(PsiBuilder builder) {
while("\n".equals(builder.getTokenText()) && !builder.eof() && (builder.getTokenType() != null)) {
builder.advanceLexer();
}
}
private static void parseDirective(PsiBuilder builder, String white, PsiBuilder.Marker marker) {
gotoNextWhiteSpaces(builder);
if (builder.getTokenType() != RestTokenTypes.WHITESPACE) {
builder.advanceLexer();
marker.done(RestElementTypes.DIRECTIVE_BLOCK);
return;
}
skipBlankLines(builder);
if (white.equals(builder.getTokenText())) {
builder.advanceLexer();
parseDirective(builder, white, marker);
}
else {
marker.done(RestElementTypes.DIRECTIVE_BLOCK);
}
}
}