Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   ***** BEGIN LICENSE BLOCK *****
   * Version: CPL 1.0/GPL 2.0/LGPL 2.1
   * The contents of this file are subject to the Common Public
   * License Version 1.0 (the "License"); you may not use this file
   * except in compliance with the License. You may obtain a copy of
   * the License at
  * Software distributed under the License is distributed on an "AS
  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  * implied. See the License for the specific language governing
  * rights and limitations under the License.
  * Copyright (C) 2004-2006 Thomas E Enebo <>
  * Copyright (C) 2004 Jan Arne Petersen <>
  * Copyright (C) 2004 Stefan Matthias Aust <>
  * Copyright (C) 2005 Zach Dennis <>
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the CPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the CPL, the GPL or the LGPL.
  ***** END LICENSE BLOCK *****/
 package org.jruby.lexer.yacc;
 import java.util.List;
This class is what feeds the lexer. It is primarily a wrapper around a Reader that can unread() data back onto the source. Originally, I thought about using the PushBackReader to handle read/unread, but I realized that some extremely pathological case could overflow the pushback buffer. Better safe than sorry. I could have combined this implementation with a PushbackBuffer, but the added complexity did not seem worth it.
 public abstract class LexerSource {
 	// Where we get new positions from.
     // The name of this source (e.g. a filename: foo.rb)
     private final String sourceName;
     // Number of newlines read from the reader
     protected int line = 0;
     // Virtual line as specified by eval, etc...
     protected int lineOffset = 0;
     // How many bytes into the source are we?
     protected int offset = 0;
     // Store each line into this list if not null.
     private List<Stringlist;
     // For 'list' and only populated if list is not null.
     private StringBuilder lineBuffer;
     // Last full line read.
     private StringBuilder sourceLine;

Create our food-source for the lexer

sourceName is the file we are reading
reader is what represents the contents of file sourceName
line starting line number for source (used by eval)
extraPositionInformation will gives us extra information that an IDE may want (deprecated)
     protected LexerSource(String sourceNameList<Stringlistint lineOffset
             boolean extraPositionInformation) {
         this. = sourceName;
         this. = lineOffset;
          = new SimplePositionFactory(this);
         this. = list;
          = new StringBuilder(160);
          = new StringBuilder(160);

What file are we lexing?

the files name
     public String getFilename() {
     	return ;
What line are we at?

the line number 0...line_size-1
    public int getLine() {
        return ;
    public int getVirtualLine() {
        return  + ;
The location of the last byte we read from the source.

current location of source
    public int getOffset() {
        return ( <= 0 ? 0 : );

Where is the reader within the source {filename,row}

the current position
    public ISourcePosition getPosition(ISourcePosition startPosition) {
    	return .getPosition(startPosition);
Where is the reader within the source {filename,row}

the current position
    public ISourcePosition getPosition() {
    	return .getPosition(null);

Create a source.

name the name of the source (e.g a filename: foo.rb)
content the data of the source
the new source
    public static LexerSource getSource(String nameInputStream contentList<Stringlist,
            ParserConfiguration configuration) {
        return new InputStreamLexerSource(namecontentlistconfiguration.getLineNumber(), 
    public static LexerSource getSource(String namebyte[] contentList<Stringlist,
            ParserConfiguration configuration) {
        return new ByteArrayLexerSource(namecontentlistconfiguration.getLineNumber(),
    private void captureFeatureNewline() {
        StringBuilder temp = ;
        // Save sourceLine for error reporting to display line where error occurred
         = ;
        // Ruby's OMG capture all source in a Hash feature
        // Add each line to buffer when encountering newline or EOF for first time.
        if ( != null && .length() > 0) .add(.toString());
         = temp;
    protected void captureFeature(int c) {
        switch(c) {
            case '\n':
            case -1:
    protected void uncaptureFeature(int c) {
        int end = .length() - 1;
        if (end >= 0 && .charAt(end) == c) {
        } else if (c == '\n' &&  != null && !.isEmpty()) {
             = new StringBuilder(.remove(.size() - 1));
            end = .length() - 1;
            if (.charAt(end) == '\n') {
    public String getCurrentLine() {
        int errorLocation = .length() - 1;
        // Get rest of line. lineBuffer filled as side-effect...
        try { readLineBytes(); } catch (IOException e) {}
        return .toString() + makePointer(errorLocation);
    protected String makePointer(int length) {
        StringBuilder buf = new StringBuilder();
        for (int i = 0; i < lengthi++) {
            buf.append(' ');
        return buf.toString();
    // Super slow codepoint reader when we detect non-asci chars
    public int readCodepoint(int firstEncoding encodingthrows IOException {
        int count = 0;
        byte[] value = new byte[6];
        // We know this will never be EOF
        value[0] = (bytefirst;
        for (count = 1; count < 6; count++) {
            int c = read();
            if (c == .break// Maybe we have enough bytes read to mbc at EOF.
            value[count] = (bytec;
        int length = encoding.length(value, 0, count);
        if (length < 0) {
            return -2; // TODO: Hack
        int codepoint = encoding.mbcToCode(value, 0, length);
        for (int i = count - 1; i >= lengthi--) {
        return codepoint;

Match marker against input consumering lexer source as it goes...Unless it does not match then it reverts lexer source back to point when this method was invoked.

marker to match against
indent eat any leading whitespace
withNewline includes a check that marker is followed by newline or EOF
true if marker matches...false otherwise
Throws: if an error occurred reading from underlying IO source
    public abstract boolean matchMarker(ByteList markerboolean indentboolean withNewlinethrows IOException;
    public abstract int read() throws IOException;
    public abstract ByteList readUntil(char cthrows IOException;
    public abstract ByteList readLineBytes() throws IOException;
    public abstract int skipUntil(int cthrows IOException;
    public abstract void unread(int c);
    public abstract void unreadMany(CharSequence line);
    public abstract boolean peek(int cthrows IOException;
    public abstract boolean lastWasBeginOfLine();
    public abstract boolean wasBeginOfLine();
    public abstract InputStream getRemainingAsStream() throws IOException;
New to GrepCode? Check out our FAQ X