All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.galileo_2.12.0.1.2.source-code.Parser.scala Maven / Gradle / Ivy

The newest version!
package galileo.parser

import java.io.IOException
import scala.util.parsing.combinator.ImplicitConversions // really useful...
import scala.util.parsing.combinator.JavaTokenParsers

import galileo.environment.Environment
import galileo.expr._
import galileo.exprhandler.ExprHandler
import galileo.linalg._
import galileo.logic._
import galileo.manipulate._
import galileo.proof.Proof
import galileo.rand.Rand
import galileo.solve.Solve
import galileo.tensor._
import galileo.trigonometry._

class Parser extends builtinParser with exprParser { 
	// lexer can be used to reserve keywords
  def program = rep1sep(statement, ";") <~ opt(";")
  def statement:Parser[Expr] =  builtin | prove | assignment | expression // | selector // | expression // | selector
  def builtin:Parser[Expr] = comment | whos | who | clear | ls | cd | pwd | load | exit
  def prove:Parser[Expr] = "prove" ~ "(" ~> expression ~ ( "=" | ">" | "<" | "!=" ) ~ expression <~ ")" ^^ { case l~o~r => Proof( l, o, r ) }
  // Assignment and array assignment (AssignmentN)
  def assignment:Parser[Expr] = 
    ( "[" ~> ident <~ "," ) ~ (ident <~ "," ) ~ ( ident <~ "]" ) ~ ( "=" ~> expression ) ^^ { case a~b~c~e => Assignment3( a, b, c, e ) } |
    ( "[" ~> ident <~ "," ) ~ ( ident <~ "]" ) ~ ( "=" ~> expression ) ^^ { case a~b~e => Assignment2( a, b, e ) } |
    ident ~ ( "=" ~> expression ) ^^ { case name~e => Assignment1( name, e ) }
  
/*
override def selector:Parser[Expr] = 
    expression ~ ( "[" ~> expression <~ "]" ) ^^ { case selectee~index0 => Selector( selectee, index0 ) }
*/
  override def failure(msg: String) = "" ~> super.failure(msg)
  // VERY IMPORTANT
  // NEEDS parseAll rather than parse
  def parse(str:String):ParseResult[List[Expr]] = parseAll(program, str)
  // todo: Does this change env correctly?
  // e.g. toExpr( "a=1;a", env);
  // Does env contain 'a=1' now?
  def toExpr(env:Environment,str:String):Option[List[Expr]] = {
    parse( str ) match {
          case Success(expressions,_) => {
            val handler = new ExprHandler
            assert( expressions.size > 0 )
            var list:List[Expr] = List();
            for( expression <- expressions )
              list :+ handler.visit( env, expression)   

            Some( list )
          }
          case err: NoSuccess   => None
        }
  }
}

trait exprParser extends logicParser with functionParser with matrixParser with tensorParser {
  val expression:Parser[Expr] = chainl1( term, "+" ^^^ Sum2 | "-" ^^^ Sub | "||" ^^^ Or2 ) 
  def term:Parser[Expr] = chainl1( power, "*" ^^^ Product2 | "/" ^^^ Div | "&&" ^^^ And2 ) 
  def power:Parser[Expr] = chainl1( factor, "^" ^^^ Power ) 
  def factor:Parser[Expr] = selector | mats | tensor | function | deriv | boolOps |
    rowVector |
    floatingPointNumber ^^ NumD | 
    bool | 
    variableE |
    "(" ~> expression <~ ")" | unaryMinus | "" ~> failure( "factor expected")
  def unaryMinus:Parser[Expr] = "-" ~> term ^^ { e:Expr => Product( Number( -1 ), e ) }
  // for matrix selection, e.g. A[0] or A[0,1]
  def selector:Parser[Expr] = 
    ident ~ ( "[" ~> factor <~ "," ) ~ factor <~ "]" ^^ { case selectee~index0~index1 => Selector( Variable( selectee ), index0, index1 ) } |
    ident ~ ( "[" ~> factor <~ "]" ) ^^ { case selectee~index0 => Selector( Variable( selectee ), index0 ) } |
    mats ~ ( "[" ~> factor <~ "," ) ~ factor <~ "]" ^^ { case selectee~index0~index1 => Selector( selectee , index0, index1 ) } |
    mats ~ ( "[" ~> factor <~ "]" ) ^^ { case selectee~index0 => Selector( selectee, index0 ) } |
    tensor ~ ( "[" ~> factor <~ "," ) ~ factor <~ "]" ^^ { case selectee~index0~index1 => Selector( selectee, index0, index1 ) } |
    tensor ~ ( "[" ~> factor <~ "]" ) ^^ { case selectee~index0 => Selector( selectee, index0 ) } 
  // An expression that is not a matrix or vector
  val m_expression = chainl1( m_term, "+" ^^^ Sum2 | "-" ^^^ Sub | "||" ^^^ Or2 ) 
  def m_term:Parser[Expr] = chainl1( m_power, "*" ^^^ Product2 | "/" ^^^ Div | "&&" ^^^ And2 ) 
  def m_power:Parser[Expr] = chainl1( m_factor, "^" ^^^ Power ) 
  def m_factor:Parser[Expr] = function | deriv | boolOps |
    floatingPointNumber ^^ NumD | 
    bool | 
    variableE | //bool | //rowVector |
    "(" ~> m_expression <~ ")" | m_unaryMinus | "" ~> failure( "factor expected")
  def m_unaryMinus:Parser[Expr] = "-" ~> m_term ^^ { e:Expr => Product( Number( -1 ), e ) }

  def deriv:Parser[Expr] = ( "deriv" ~> "(" ~> expression ) ~ ( "," ~> variableV <~ ")" ) ^^ { case y~x => Derivative( y, x ) }

  val Sub = ( a:Expr, b:Expr ) => Sum( a, Product( Number( -1 ), b ) )
  val Div = ( a:Expr, b:Expr ) => Fraction( a, b ) 
  val Product2 = (a:Expr, b:Expr ) => Product( a, b )
  val Sum2 = (a:Expr, b:Expr ) => Sum( a, b )
  val Or2 = (a:Expr,b:Expr) => BoolOrSc( a, b ) // sc for short-circuit evalualation
  val And2 = (a:Expr,b:Expr) => BoolAndSc( a, b )
}

// Tensor related Parser functionality
trait tensorParser extends JavaTokenParsers with ImplicitConversions {
  val expression:Parser[Expr]
  def tensor = metric | christoffel | tensors
  def metric:Parser[Metric] = "metric.generate(" ~> metrictemplate <~ ")" ^^ { 
    case "minkowski" => Metric.minkowski()
    case "two-sphere" => Metric.twoSphere( Variable( "r" ) )
    case "three-sphere" => Metric.threeSphere( Variable( "r" ) )
    case "schwarzschild" => Metric.schwarzschild( Variable( "r") )
  } 
  def metrictemplate:Parser[String] = "two-sphere" | "three-sphere" | "schwarzschild"
  def christoffel = // these are not tensors - small technicality
    "christoffelfirst(" ~> expression <~ ")" ^^ ChristoffelFirstU |
    "christoffelsecond(" ~> expression <~ ")" ^^ ChristoffelSecondU

  def tensors = 
    "riemannfirst" ~> "(" ~> expression <~ ")" ^^ RiemannFirstU |
    "riemannsecond" ~> "(" ~> expression <~ ")" ^^ RiemannSecondU |
    "einsteintensor" ~> "(" ~> expression <~ ")" ^^ EinsteinTensorU |
    "einsteinscalar" ~> "(" ~> expression <~ ")" ^^ EinsteinScalarU |
    "riccitensor" ~> "(" ~> expression <~ ")" ^^ RicciTensorU |
    "ricciscalar" ~> "(" ~> expression <~ ")" ^^ RicciScalarU  |
    "weyltensor" ~> "(" ~> expression <~ ")" ^^ WeylTensorU
    /*|
    "schoutentensor" ~> "(" ~> expression <~ ")" ^^ SchoutenTensorU |
    "cottontensor" ~> "(" ~> expression <~ ")" ^^ CottonTensorU |
    "lanczostensor" ~> "(" ~> expression <~ ")" ^^ LanczosTensorU  
    */  
}

  //def tensor = "tensor" ~> "(" ~> expr ~ "," ~ expr ~ "," ~ expr <~ ")" ^^ { case l~_~u~_~d => TensorU( l, u, d ) } 

  //def tensor = christof // "hello" ^^^{ Number( 1 ) } //christof
 // def christof:Parser[Expr] = //"christof" ~> "(" ~> expression ~ ( "," ~> vector <~ ")" ) ^^ { case metric~coords => Christoffel( metric, coords, 1 ) } |
  //  "christof" ~> "(" ~> expression ~ ( "," ~> expression <~ ")" ) ^^ { case metric~coords => Christoffel( metric, coords, 1 ) }
  //def vector:Parser[List[Expr]] = "[" ~> rep1sep( expression, " " ) <~ "]" ^^ { case es => es.to[List] }

// Matrix related Parser functionality
trait matrixParser extends JavaTokenParsers with ImplicitConversions {
  val expression:Parser[Expr]
  // m_expression is an expression that is not a matrix or vector itself
  // m_expression can be elements of a matrix
  val m_expression:Parser[Expr]
  // content valid inside a matrix  
  //def matrixContent:Parser[Expr] = m_expression //unaryMinusMatrixTerm | matrixTerm | // | 
  def rand:Parser[Expr] = 
    "rand" ~ "(" ~> m_expression ~ "," ~ m_expression <~ ")" ^^ { case nr~_~nc => Rand( nr,nc ) } |
    "rand" ~ "(" ~> m_expression <~ ")" ^^ { case e => Rand( e ) }
  
  def mats:Parser[Expr] = matsolve | matlu | matinv | matnorm | matrix | matrixT
  def matsolve:Parser[Expr] = ( matrix | variableE ) ~ ( '\\' ~> ( matrix | variableE ) ) ^^ Solve
  def matlu:Parser[Expr] = "lu" ~> "(" ~> ( matrix | variableE )  <~ ")" ^^ MatLU
  def matinv:Parser[Expr] = "inv" ~> "(" ~> ( m_expression )  <~ ")" ^^ MatInv
  def matnorm:Parser[Expr] = 
    ( "norm" ~> "(" ~> expression <~ "," ) ~ ( posNumber <~ ")" ) ^^ { case m~p => MatNorm( m, p ) } |
    "norm" ~> "(" ~> expression <~ ")" ^^ { case m => MatNorm( m ) }

  def posNumber:Parser[Integer] = wholeNumber ^^ { s:String => { val r = s.toInt; require( r >= 0 ); r } } 
  def ones:Parser[Expr] = 
    ( "ones" ~> "(" ~> m_expression ) ~ ( "," ~> m_expression <~ ")" ) ^^ { case n~m => OnesMatrixU( n, m ) } |
    "ones" ~> "(" ~> m_expression <~ ")" ^^ { case e => OnesMatrixU( e, e ) } |
    "ones" ^^ { _ => Number( 1 ) }
  def zeros:Parser[Expr] = 
    ( "zeros" ~> "(" ~> m_expression ) ~ ( "," ~> m_expression <~ ")" ) ^^ { case n~m => OnesMatrixU( n, m, Number( 0 ) ) } |
    "zeros" ~> "(" ~> m_expression <~ ")" ^^ { case e => OnesMatrixU( e, e, Number( 0 ) ) } |
    "zeros" ^^ { _ => Number( 0 ) }

  def eye:Parser[Expr] = 
    ( "eye" ~> "(" ~> m_expression ) ~ ( "," ~> m_expression <~ ")" ) ^^ { case n~m => EyeMatrixU( n, m ) } |
    "eye" ~> "(" ~> m_expression <~ ")" ^^ { case e => EyeMatrixU( e, e ) } |
    "eye" ^^ { _ => Number( 1 ) }

  // TODO: true and false are not valid variable names!!!
  def variableV:Parser[Variable] = ident ^^ Variable
  def variableE:Parser[Expr] = ident ^^ Variable
  //def vectorT:Parser[Expr] = vector <~ ''' ^^ { case Vector( l ) => Matrix( l.map( e=> List(e) ) ) }//VecT //| matrix <~ ''' MatT
  def matrixT:Parser[Expr] = matrix <~ '\'' ^^ { case DenseMatrix( ll ) => DenseMatrix( ll.transpose ) }
  //def vector:Parser[Expr] = "[" ~> rep1sep( factor, ' ' ) <~ "]" ^^ { case l => Matrix( List( l ) }
  def row:Parser[Expr] = "[" ~> rep1sep( m_expression, " " ) <~ "]" ^^ { case l:List[Expr] => DenseMatrix( List( l ) ) }
  def matrixCore:Parser[Expr] = "[" ~> rep1sep( rep1sep( m_expression, ' ' ), ";" ) <~ "]" ^^ Mat
  def rowVector:Parser[Expr] = 
    m_expression ~ ":" ~ m_expression ~ ":" ~ m_expression ^^ { case a~_~b~_~c => RowVector( a, c, b ) } |
    m_expression ~ ":" ~ m_expression                      ^^ { case a~_~b     => RowVector( a, b, Number( 1 ) ) }


  def linspace:Parser[Expr] =
    "linspace" ~ "(" ~> floatingPointNumber ~ "," ~ floatingPointNumber ~ "," ~ wholeNumber <~ ")" ^^ { case a~_~b~_~c => LinSpace( a.toDouble, b.toDouble, c.toInt ) } |
    "linspace" ~ "(" ~> floatingPointNumber ~ "," ~ floatingPointNumber <~ ")" ^^ { case a~_~b => LinSpace( a.toDouble, b.toDouble) }
    def logspace:Parser[Expr] =
    "logspace" ~ "(" ~> floatingPointNumber ~ "," ~ floatingPointNumber ~ "," ~ wholeNumber <~ ")" ^^ { case a~_~b~_~c => LogSpace( a.toDouble, b.toDouble, c.toInt ) } |
    "logspace" ~ "(" ~> floatingPointNumber ~ "," ~ floatingPointNumber <~ ")" ^^ { case a~_~b => LogSpace( a.toDouble, b.toDouble ) }

  def matrix:Parser[Expr] = 
    eye | 
    ones | zeros | rand | linspace | logspace | transpose |
    matrixCore <~ '\'' ^^ { case DenseMatrix( ll ) => DenseMatrix( ll.transpose ) } | 
    matrixCore 
  def transpose:Parser[Expr] = "transpose" ~> "(" ~> m_expression <~ ")" ^^ { case e => Transpose( e ) }
  
  val NumD = ( a:String ) => Number( a.toDouble )
  //val Der = ( a:Expr, b:Variable ) => Derivative( a, b ) //a.derive( b ) //Derivative( a, b ) //a.derive( b )
  
  val Mat = (ll:List[List[Expr]]) => { require( ll.forall( str => str.size == ll(0).size ), "Not all rows have the same size" ); DenseMatrix( ll ) }
}

// functions
trait functionParser extends JavaTokenParsers {
  val expression:Parser[Expr]
  def function:Parser[ Expr ] = 
    //"kron" ~> "(" ~> expression ~ ( "," ~> expression <~ ")" ) ^^ TensorProduct |
    "sin" ~> "(" ~> expression <~ ")" ^^ SinF1 |
    "cos" ~> "(" ~> expression <~ ")" ^^ CosF1 |
    "tan" ~> "(" ~> expression <~ ")" ^^ TanF1 |
    "asin" ~> "(" ~> expression <~ ")" ^^ AsinF1 |
    "acos" ~> "(" ~> expression <~ ")" ^^ AcosF1 |
    "atan" ~> "(" ~> expression <~ ")" ^^ AtanF1 |
    "log" ~> "(" ~> expression <~ ")" ^^ LogF1 |
    "exp" ~> "(" ~> expression <~ ")" ^^ ExpF1 |
    "sqrt" ~> "(" ~> expression <~ ")" ^^ { e:Expr => Sqrt( e ) } |
    "info" ~> "(" ~> expression <~ ")" ^^ Info |
    "eval" ~> "(" ~> expression <~ ")" ^^ Eval |
    "complexity" ~> "(" ~> expression <~ ")" ^^ Complexity |
    "simplify" ~> "(" ~> expression <~ ")" ^^ Simplify |
    "simplify" ~> "(" ~> expression <~ "," ~ "min" ~ ")" ^^ SimplifyMin | // Minimize expression complexity
    "expand" ~> "(" ~> expression <~ ")" ^^ Expand |
    "factor" ~> "(" ~> expression <~ ")" ^^ Factor
}

// logicalParser
trait logicParser extends JavaTokenParsers with ImplicitConversions {
  val expression:Parser[Expr]
  // logical operations
  def bool = "true" ^^ { _ => Bool( true ) } | "false" ^^ { _ => Bool( false ) } 
  def boolOps:Parser[Expr] = boolAnd | boolOr | boolXor | boolNot
  def boolNot:Parser[Expr] = "not" ~> "(" ~> expression <~ ")" ^^ { case e => BoolNot( e ) }
  def boolAnd:Parser[Expr] = ( "and" ~> "(" ~> expression ) ~ ( "," ~> expression <~ ")"  ) ^^ { case e~f => BoolAnd( e, f ) } 
  def boolOr:Parser[Expr] = ( "or" ~> "(" ~> expression ) ~ ( "," ~> expression <~ ")"  ) ^^ { case e~f => BoolOr( e, f ) } 
  def boolXor:Parser[Expr] = ( "xor" ~> "(" ~> expression ) ~ ( "," ~> expression <~ ")" ) ^^ { case e~f => BoolXor( e, f ) }
}

trait builtinParser extends JavaTokenParsers { 
  //system commands, used by builtin
  def comment:Parser[Expr] = "//" ~ rep(not("\n") ~ ".".r) ^^^ { new NilExpr }
  //"//" ~ rep(not("\n") ~ ".".r) ^^^ Unit
  def clear:Parser[Expr] = "clear" ^^ { case _ => new Clear() }
  def exit:Parser[Expr] = "exit" ^^ { case _ => new Exit() }
  def ls:Parser[Expr] = "ls" ^^ { case _ => SystemCommand( "ls" ) }
  def cd:Parser[Expr] = "cd" ~> path ^^ { p => SystemCommand( "cd " + p ) }
  def pwd:Parser[Expr] = "pwd" ^^ { case _ => SystemCommand( "pwd ") }
  def load:Parser[Expr] = "load" ~ "(" ~> path <~ ")" ^^ { case filename => Load( filename ) } 
  def who:Parser[Expr] = "who" ^^ { case(_:String) => new Who() }
  def whos:Parser[Expr] = "whos" ^^ { case(_:String) => new Whos() }
  def path:Parser[String] = "[^)]+".r // ^^ { _.toString }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy