Top Description Fields Constructors Methods
org.python.antlr

public Class PythonTokenSource

extends Object
implements TokenSource
Class Inheritance
All Implemented Interfaces
org.antlr.runtime.TokenSource
Imports
org.python.core.Py, org.antlr.runtime.*, java.util.*

Python does not explicitly provide begin and end nesting signals. Rather, the indentation level indicates when you begin and end. This is an interesting lexical problem because multiple DEDENT tokens should be sent to the parser sometimes without a corresponding input symbol! Consider the following example:
a=1
 if a>1:
     print a
 b=3
Here the "b" token on the left edge signals that a DEDENT is needed after the "print a \n" and before the "b". The sequence should be
 ... 1 COLON NEWLINE INDENT PRINT a NEWLINE DEDENT b ASSIGN 3 ...
For more examples, see the big comment at the bottom of this file. This TokenStream normally just passes tokens through to the parser. Upon NEWLINE token from the lexer, however, an INDENT or DEDENT token may need to be sent to the parser. The NEWLINE is the trigger for this class to do it's job. NEWLINE is saved and then the first token of the next line is examined. If non-leading-whitespace token, then check against stack for indent vs dedent. If LEADING_WS, then the column of the next non-whitespace token will dictate indent vs dedent. The column of the next real token is number of spaces in the LEADING_WS token + 1 (to move past the whitespace). The lexer grammar must set the text of the LEADING_WS token to be the proper number of spaces (and do tab conversion etc...). A stack of column numbers is tracked and used to detect changes in indent level from one token to the next. A queue of tokens is built up to hold multiple DEDENT tokens that are generated. Before asking the lexer for another token via nextToken(), the queue is flushed first one token at a time. Terence Parr and Loring Craymer February 2004

Field Summary

Modifier and TypeField and Description
pack-priv String
public static final int
pack-priv int[]
indentStack

The stack of indent levels (column numbers)

pack-priv boolean
pack-priv int
public static final int
pack-priv int
sp

stack pointer

pack-priv CommonTokenStream
stream

We pull real tokens from this lexer

pack-priv Vector<Token>
tokens

The queue of tokens

Constructor Summary

AccessConstructor and Description
public
public
public
PythonTokenSource(CommonTokenStream stream, String filename, boolean single)

Method Summary

Modifier and TypeMethod and Description
private void
private List<Token>
protected int
findPreviousIndent(int i, Token t)

Return the index on stack of previous indent level == i else -1

private void
public String
getSourceName()

Implements org.antlr.runtime.TokenSource.getSourceName.

Where are you getting tokens from?

private void
private void
private void
protected void
public Token
nextToken()

Implements org.antlr.runtime.TokenSource.nextToken.

From http://www.python.org/doc/2.2.3/ref/indentation.html "Before the first line of the file is read, a single zero is pushed on the stack; this will never be popped off again.

protected int
peek()

protected int
pop()

protected void
push(int i)

public String
Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

filenameback to summary
pack-priv String filename
FIRST_CHAR_POSITIONback to summary
public static final int FIRST_CHAR_POSITION
indentStackback to summary
pack-priv int[] indentStack

The stack of indent levels (column numbers)

inSingleback to summary
pack-priv boolean inSingle
lastTokenAddedIndexback to summary
pack-priv int lastTokenAddedIndex
MAX_INDENTSback to summary
public static final int MAX_INDENTS
spback to summary
pack-priv int sp

stack pointer

streamback to summary
pack-priv CommonTokenStream stream

We pull real tokens from this lexer

tokensback to summary
pack-priv Vector<Token> tokens

The queue of tokens

Constructor Detail

PythonTokenSourceback to summary
public PythonTokenSource(PythonLexer lexer)
PythonTokenSourceback to summary
public PythonTokenSource(CommonTokenStream stream, String filename)
PythonTokenSourceback to summary
public PythonTokenSource(CommonTokenStream stream, String filename, boolean single)

Method Detail

enqueueback to summary
private void enqueue(Token t)
enqueueHiddensback to summary
private List<Token> enqueueHiddens(Token t)
findPreviousIndentback to summary
protected int findPreviousIndent(int i, Token t)

Return the index on stack of previous indent level == i else -1

generateNewlineback to summary
private void generateNewline(Token t)
getSourceNameback to summary
public String getSourceName()

Implements org.antlr.runtime.TokenSource.getSourceName.

Doc from org.antlr.runtime.TokenSource.getSourceName.

Where are you getting tokens from? normally the implication will simply ask lexers input stream.

Annotations
@Override
handleDedentsback to summary
private void handleDedents(int cpos, CommonToken t)
handleEOFback to summary
private void handleEOF(CommonToken eof, CommonToken prev)
handleIndentsback to summary
private void handleIndents(int cpos, CommonToken t)
insertImaginaryIndentDedentTokensback to summary
protected void insertImaginaryIndentDedentTokens()
nextTokenback to summary
public Token nextToken()

Implements org.antlr.runtime.TokenSource.nextToken.

From http://www.python.org/doc/2.2.3/ref/indentation.html "Before the first line of the file is read, a single zero is pushed on the stack; this will never be popped off again. The numbers pushed on the stack will always be strictly increasing from bottom to top. At the beginning of each logical line, the line's indentation level is compared to the top of the stack. If it is equal, nothing happens. If it is larger, it is pushed on the stack, and one INDENT token is generated. If it is smaller, it must be one of the numbers occurring on the stack; all numbers on the stack that are larger are popped off, and for each number popped off a DEDENT token is generated. At the end of the file, a DEDENT token is generated for each number remaining on the stack that is larger than zero." I use char position in line 0..n-1 instead. The DEDENTS possibly needed at EOF are gracefully handled by forcing EOF to have char pos 0 even though with UNIX it's hard to get EOF at a non left edge.

Annotations
@Override
peekback to summary
protected int peek()
popback to summary
protected int pop()
pushback to summary
protected void push(int i)
stackStringback to summary
public String stackString()