/* * 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); } } }