Package sicel.compiler.parser.internal

Source Code of sicel.compiler.parser.internal.ParserImpl

package sicel.compiler.parser.internal;

import java.io.File;
import java.io.IOException;

import sicel.compiler.parser.ASTNode;
import sicel.compiler.parser.Parser;
import sicel.compiler.parser.Token;
import sicel.compiler.parser.exceptions.SyntaxError;
import sicel.compiler.parser.exceptions.UnexpectedTokenError;
import sicel.compiler.parser.internal.ast.*;
import sicel.compiler.parser.internal.tokens.*;

public class ParserImpl extends AbstractParser implements Parser
{
 
  public static void main( String[] args ) throws IOException
  {
    Parser parser = new ParserImpl();
    parser.setLexer( new LexerImpl() );
    ASTNode rootNode;
    try
    {
      rootNode = parser.parse( new File( "input.txt" ) );
    }
    catch ( SyntaxError e )
    {
      e.printStackTrace();
      return;
    }
   
    rootNode.printTree();
  }
 
  @Override
  public final ASTNode parse( File file )
  {
    lexer.initialize( file );
    ASTNode n = new Program();
    while( true )
    {   
      while( consumeIf( T_EOL.class ) );
      if( lexer.peek() == null )
      {
        // no more tokens. EOF
        break;
      }
      if( ! binding() )
      {
        Token t = lexer.take();
        throw new UnexpectedTokenError( t, "binding" );
      }
      n.putChild( consumedNode );
    }
    return n;
  }
 
  private final boolean binding()
  {
    if( ! consumeIf( T_BINDING.class ) ) return false;
    T_BINDING t = (T_BINDING)consumedToken;
    ASTNode n = new Binding( t.text );
    expression();
    n.putChild( consumedNode );
    if( lexer.peek() != null )
    {
      expect( T_EOL.class );
      if( consumeIf( T_BRACE_OPEN.class) )
      {
        while( consumeIf( T_EOL.class ) );
        while( binding() )
        {
          n.putChild( consumedNode );
          while( consumeIf( T_EOL.class ) );
        }
        expect( T_BRACE_CLOSE.class );
      }
    }
    consumedNode = n;
    return true;
  }
 
 
  private final boolean binOp( ASTNode lhn )
  {
    if( lookAhead( 0, T_OPERATOR.class ) )
    {
      T_OPERATOR op_token = (T_OPERATOR)lexer.take();
      Operator op = new Operator( op_token.text );
      op.putChild( lhn ); //left-hand node
     
      if( ! unit() )
      {
        Token t = lexer.take();
        throw new UnexpectedTokenError( t );
      }
     
      op.putChild( consumedNode ); //right-hand node
     
      if( ! binOp( op ) )
      {
        consumedNode = op;
      }
     
      return true;
    }
   
    if( lookAhead( 0, T_INFIX_WORD.class ) )
    {
      T_INFIX_WORD op_token = (T_INFIX_WORD)lexer.take();
      FunctionCall op = new FunctionCall( op_token.text );
      op.putChild( lhn ); //left-hand node
     
      if( ! unit() )
      {
        Token t = lexer.take();
        throw new UnexpectedTokenError( t );
      }
     
      op.putChild( consumedNode ); //right-hand node
     
      if( ! binOp( op ) )
      {
        consumedNode = op;
      }
     
      return true;
    }
   
    return false;
  }
 
  private final boolean unit()
  {
    if( ! ( literalList() || lambda() || functionCall() || parenGroup() || atom() ) )
    {
      return false;
    }
    dotCall( consumedNode );
    return true;
  }
 
  private final boolean dotCall( ASTNode lhs )
  {
    if( ! consumeIf( T_DOT.class ) ) return false;
    if( ! functionCall() )
    {
      Token t = lexer.take();
      throw new UnexpectedTokenError( t, "function call" );
    }
    consumedNode.putChild( 0, lhs );
    dotCall( consumedNode );
    return true;
  }
 
  private final boolean expression()
  {
    if( ! unit() ) return false;
    binOp( consumedNode );
    return true;
  }
 
  private final boolean lambda()
  {
    if( ! lookAhead( 1, T_ARROW.class ) ) return false;
    T_WORD word = (T_WORD)expect( T_WORD.class );
    ASTNode lambda = new Lambda( word.text );
    lexer.take(); // arrow
    if( ! expression() )
    {
      Token t = lexer.take();
      throw new UnexpectedTokenError( t, "expression" );
    }
    lambda.putChild( consumedNode );
    consumedNode = lambda;
    return true;
  }
 
  private final boolean functionCall()
  {
    if( ! consumeIf( T_WORD.class ) ) return false;
    T_WORD word = (T_WORD)consumedToken;
    ASTNode fc = new FunctionCall( word.text );
   
    if( consumeIf( T_PAREN_OPEN.class ) )
    {
      if( expression() )
      {
        fc.putChild( consumedNode );
        while( consumeIf( T_COMMA.class ) )
        {
          if( ! expression() )
          {
            Token t = lexer.take();
            throw new SyntaxError( "Expected expression", "", t.getLine(), t.getColumn() );
          }
          fc.putChild( consumedNode );
        }
      }
      if( ! consumeIf( T_PAREN_CLOSE.class ) )
      {
        Token t = lexer.take();
        throw new UnexpectedTokenError( t, T_PAREN_CLOSE.class );
      }
    }
    consumedNode = fc;
    return true;
  }
 
  private final boolean atom()
  {
    ifconsumeIf( T_INT_LITERAL.class ) )
    {
      consumedNode = new IntLiteral( ( (T_INT_LITERAL)consumedToken ).value );
      return true;
    }
    ifconsumeIf( T_DOUBLE_LITERAL.class ) )
    {
      consumedNode = new DoubleLiteral( ( (T_DOUBLE_LITERAL)consumedToken ).value );
      return true;
    }
    if( consumeIf( T_STRING_LITERAL.class ) )
    {
      consumedNode = new StringLiteral( ( (T_STRING_LITERAL)consumedToken ).value );
      return true;
    }
    return false;
  }
 
  private final boolean literalList()
  {
    if( ! consumeIf( T_SQUARE_OPEN.class ) ) return false;

    ASTNode n = new LiteralList();
    if( expression() )
    {
      n.putChild( consumedNode );
      while( consumeIf( T_COMMA.class ) )
      {
        if( ! expression() )
        {
          Token t = lexer.take();
          throw new UnexpectedTokenError( t, "expression" );
        }
        n.putChild( consumedNode );
      }
    }
    consumedNode = n;
    expect( T_SQUARE_CLOSE.class );
    return true;
  }
 
  private final boolean parenGroup()
  {
    if( ! consumeIf( T_PAREN_OPEN.class ) ) return false;
    expression();
    expect( T_PAREN_CLOSE.class );
    return true;
  }
}
TOP

Related Classes of sicel.compiler.parser.internal.ParserImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.