blob: 68b8dc2e5059110c8b994940ece2fc9b08df30b9 [file] [log] [blame]
/*
* Copyright 2007 Sascha Weinreuter
*
* 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 org.intellij.plugins.relaxNG.compact.parser;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.containers.ContainerUtil;
import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import java.util.Map;
import static org.intellij.plugins.relaxNG.compact.RncTokenTypes.*;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 09.08.2007
*/
public class PatternParsing extends DeclarationParsing {
@SuppressWarnings({"unchecked"})
protected static final Map<IElementType, IElementType> TOKEN_MAP =
ContainerUtil.newIdentityTroveMap();
static {
TOKEN_MAP.put(COMMA, RncElementTypes.SEQUENCE);
TOKEN_MAP.put(PIPE, RncElementTypes.CHOICE);
TOKEN_MAP.put(AND, RncElementTypes.INTERLEAVE);
TOKEN_MAP.put(STAR, RncElementTypes.ZERO_OR_MORE);
TOKEN_MAP.put(PLUS, RncElementTypes.ONE_OR_MORE);
TOKEN_MAP.put(QUEST, RncElementTypes.OPTIONAL);
}
private final NameClassParsing myNameClassParsing;
public PatternParsing(PsiBuilder builder) {
super(builder);
myNameClassParsing = new NameClassParsing(builder);
}
public void parse() {
parseTopLevel();
}
@Override
protected boolean parsePattern() {
PsiBuilder.Marker marker = myBuilder.mark();
if (!parseQuantifiedPattern()) {
marker.drop();
return false;
}
while (BINARY_OPS.contains(currentToken())) {
IElementType t;
if (BINARY_OPS.contains(t = currentToken())) {
do {
advance();
if (!parseQuantifiedPattern()) {
error("Pattern expected");
}
} while (currentToken() == t);
marker.done(TOKEN_MAP.get(t));
marker = marker.precede();
}
}
marker.drop();
return true;
}
private boolean parseQuantifiedPattern() {
final PsiBuilder.Marker marker = myBuilder.mark();
if (!parseSinglePattern()) {
marker.drop();
return false;
}
final IElementType t = currentToken();
if (matches(QUANTIFIER_OPS)) {
marker.done(TOKEN_MAP.get(t));
} else {
marker.drop();
}
return true;
}
private boolean parseSinglePattern() {
final PsiBuilder.Marker marker = myBuilder.mark();
if (matches(ATTR_OR_ELEMENT)) {
if (!myNameClassParsing.parseNameClass()) {
error("Name class expected");
marker.drop();
return false;
}
parseBracedPattern();
marker.done(RncElementTypes.PATTERN);
} else if (matches(KEYWORD_LIST)) {
parseBracedPattern();
marker.done(RncElementTypes.LIST_PATTERN);
} else if (matches(KEYWORD_MIXED)) {
parseBracedPattern();
marker.done(RncElementTypes.MIXED_PATTERN);
} else if (matches(KEYWORD_EXTERNAL)) {
parseAnyUriLiteral();
parseInherit();
marker.done(RncElementTypes.EXTERNAL_REF);
} else if (matches(KEYWORD_NOT_ALLOWED)) {
marker.done(RncElementTypes.NOT_ALLOWED_PATTERN);
} else if (matches(KEYWORD_TEXT)) {
marker.done(RncElementTypes.TEXT_PATTERN);
} else if (matches(KEYWORD_EMPTY)) {
marker.done(RncElementTypes.EMPTY_PATTERN);
} else if (matches(KEYWORD_PARENT)) {
match(IDENTIFIERS, "Identifier expected");
marker.done(RncElementTypes.PARENT_REF);
} else if (matches(KEYWORD_GRAMMAR)) {
parseBracedGrammarContents();
marker.done(RncElementTypes.GRAMMAR_PATTERN);
} else if (matches(LPAREN)) {
if (!parsePattern()) {
error("Pattern expected");
}
match(RPAREN, "')' expected");
marker.done(RncElementTypes.GROUP_PATTERN);
} else if (matches(IDENTIFIERS)) {
marker.done(RncElementTypes.REF_PATTERN);
} else if (matches(LA_DATATYPE)) {
parseDatatype();
marker.done(RncElementTypes.DATATYPE_PATTERN);
} else if (currentToken() == PREFIXED_NAME) {
makeName();
parseDatatype();
marker.done(RncElementTypes.DATATYPE_PATTERN);
} else if (matches(LITERAL)) {
marker.done(RncElementTypes.DATATYPE_PATTERN);
} else {
marker.drop();
return false;
}
return true;
}
private void parseDatatype() {
if (currentToken() == LITERAL) {
advance();
} else if (matches(LBRACE)) {
parseParams();
if (matches(MINUS)) {
if (!parsePattern()) {
error("Pattern expected");
}
}
match(RBRACE, "'}' expected");
}
}
private void parseBracedPattern() {
match(LBRACE, "'{' expected");
if (!parsePattern()) {
error("Pattern expected");
}
match(RBRACE, "'}' expected");
}
private void parseParams() {
final IElementType t = currentToken();
if (t != RBRACE) {
do {
final PsiBuilder.Marker marker = myBuilder.mark();
match(IDENTIFIER_OR_KEYWORD, "Identifier expected");
match(EQ, "'=' expected");
match(LITERAL, "Literal expected");
marker.done(RncElementTypes.PARAM);
} while (IDENTIFIER_OR_KEYWORD.contains(currentToken()));
}
}
}