2 * Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
3 * Use is subject to license terms.
5 package com
.intellij
.lang
.pratt
;
7 import com
.intellij
.codeInsight
.daemon
.JavaErrorMessages
;
8 import com
.intellij
.lang
.PsiBuilder
;
9 import com
.intellij
.lang
.impl
.PsiBuilderImpl
;
10 import com
.intellij
.lexer
.Lexer
;
11 import com
.intellij
.openapi
.util
.Trinity
;
12 import com
.intellij
.psi
.tree
.IElementType
;
13 import org
.jetbrains
.annotations
.NotNull
;
14 import org
.jetbrains
.annotations
.Nullable
;
16 import java
.util
.LinkedList
;
21 public class PrattBuilderImpl
extends PrattBuilder
implements PrattBuilderFacade
{
22 private final PrattBuilder myParentBuilder
;
23 private final PsiBuilder myBuilder
;
24 private final LinkedList
<IElementType
> myLeftSiblings
= new LinkedList
<IElementType
>();
25 private boolean myParsingStarted
;
26 private String myExpectedMessage
;
27 private int myPriority
= Integer
.MIN_VALUE
;
28 private MutableMarker myStartMarker
;
30 private PrattBuilderImpl(final PsiBuilder builder
, final PrattBuilder parent
) {
32 myParentBuilder
= parent
;
35 public static PrattBuilderImpl
createBuilder(final PsiBuilder builder
) {
36 return new PrattBuilderImpl(builder
, null);
39 public PrattBuilderFacade
expecting(final String expectedMessage
) {
40 myExpectedMessage
= expectedMessage
;
44 public PrattBuilderFacade
withLowestPriority(final int priority
) {
45 myPriority
= priority
;
49 public Lexer
getLexer() {
50 return ((PsiBuilderImpl
) myBuilder
).getLexer();
53 public MutableMarker
mark() {
54 return new MutableMarker(myLeftSiblings
, myBuilder
.mark(), myLeftSiblings
.size());
58 public IElementType
parse() {
60 return myLeftSiblings
.size() != 1 ?
null : myLeftSiblings
.getLast();
63 protected PrattBuilderFacade
createChildBuilder() {
64 assert myParsingStarted
;
65 return new PrattBuilderImpl(myBuilder
, this) {
66 protected void doParse() {
68 PrattBuilderImpl
.this.myLeftSiblings
.addAll(getResultTypes());
73 protected void doParse() {
75 error(myExpectedMessage
!= null ? myExpectedMessage
: JavaErrorMessages
.message("unexpected.eof"));
79 TokenParser parser
= findParser();
81 error(myExpectedMessage
!= null ? myExpectedMessage
: JavaErrorMessages
.message("unexpected.token"));
85 myStartMarker
= mark();
87 int startOffset
= myBuilder
.getCurrentOffset();
89 if (!parser
.parseToken(this)) break;
91 assert startOffset
< myBuilder
.getCurrentOffset() : "Endless loop on " + getTokenType();
93 parser
= findParser();
94 if (parser
== null) break;
100 private TokenParser
findParser() {
101 final IElementType tokenType
= getTokenType();
102 for (final Trinity
<Integer
, PathPattern
, TokenParser
> trinity
: PrattRegistry
.getParsers(tokenType
)) {
103 if (trinity
.first
> myPriority
&& trinity
.second
.accepts(this)) {
104 return trinity
.third
;
110 public boolean assertToken(final PrattTokenType type
, @NotNull final String errorMessage
) {
111 return _checkToken(type
, errorMessage
);
114 public boolean checkToken(final PrattTokenType type
) {
115 return _checkToken(type
, null);
118 private boolean _checkToken(final PrattTokenType type
, @Nullable String errorMessage
) {
123 if (errorMessage
!= null) {
129 public void advance() {
130 myLeftSiblings
.addLast(getTokenType());
131 myBuilder
.advanceLexer();
134 public void error(final String errorText
) {
135 final PsiBuilder
.Marker marker
= myBuilder
.mark();
136 myBuilder
.error(errorText
);
141 public IElementType
getTokenType() {
142 return myBuilder
.getTokenType();
146 public String
getTokenText() {
147 return myBuilder
.getTokenText();
150 public void reduce(@NotNull final IElementType type
) {
151 myStartMarker
.finish(type
);
152 myStartMarker
= myStartMarker
.precede();
156 public LinkedList
<IElementType
> getResultTypes() {
158 return myLeftSiblings
;
161 private void checkParsed() {
162 if (!myParsingStarted
) {
163 myParsingStarted
= true;
168 public PrattBuilder
getParent() {
169 return myParentBuilder
;
172 public int getPriority() {