diff --git a/Main.pseudo b/Main.pseudo index 8701229..c0f759b 100644 --- a/Main.pseudo +++ b/Main.pseudo @@ -1,17 +1,8 @@ -Gcd(a,b) - // still to fix - if(a=0) - then return b - r <- b mod a - return Gcd(r, a) - rozNWD(j,k) - //foo - if (j<0 or j>k) + if (j<0 or j>=k) then return None - //bar if (j = 0) - then return (k, 0, 1) //info dla G + then return (k, 0, 1) r <- k mod j (d, xp, yp) <- rozNWD(r, j) x <- yp - k /f j * xp diff --git a/src/main/scala/org/PseudoLang/Main.scala b/src/main/scala/org/PseudoLang/Main.scala index 7713a29..2cbcced 100644 --- a/src/main/scala/org/PseudoLang/Main.scala +++ b/src/main/scala/org/PseudoLang/Main.scala @@ -16,6 +16,16 @@ object Main extends App { val name = "Generated" FileManager.saveCodeToFile("", name, transpiled, "py") + def runParserWD(): Unit = { + println("========================= INPUT ============================") + println(code) + println("========================== AST =============================") + println(Debug.pretty(parsed.toString)) + println("========================== CODE ============================") + println(parsed.show()) + println("============================================================") + } + def runWithDebugging(): Unit = { println("======================= PSEUDO LANG ========================") println("========================= INPUT ============================") @@ -41,4 +51,6 @@ object Main extends App { } runWithoutDebugging() +// runWithDebugging() +// runParserWD() } diff --git a/src/main/scala/org/PseudoLang/Transpiler.scala b/src/main/scala/org/PseudoLang/Transpiler.scala index 2d9f86a..19e661e 100644 --- a/src/main/scala/org/PseudoLang/Transpiler.scala +++ b/src/main/scala/org/PseudoLang/Transpiler.scala @@ -16,7 +16,7 @@ import scala.sys.process.stdout * through AST */ object Transpiler { - def run(ast: AST): String = transpile(ast).build() + def run(ast: AST): String = transpile(ast).build() def transpile(ast: AST): Repr.Builder = traverse(0, ast.elems) /** @@ -72,10 +72,7 @@ object Transpiler { a: AST.Array, rest: List[AST.Elem] ): Repr.Builder = { - R + a.name + traverseParens(a.elems) + traverse( - indent, - rest - ) + R + a.name + traverseParens(a.elems) + traverse(indent, rest) } private def transpileRepeatUntil( @@ -87,7 +84,7 @@ object Transpiler { case b: AST.Block => R + traverseBlock(b) case oth => R + oth } - R + "while True:" + bRepr + AST + R + AST.Newline() + indent + "while True:" + bRepr + AST .Newline() + l.block .asInstanceOf[AST.Block] .indent + "if not " + traverseParens(l.condition) + AST @@ -103,7 +100,8 @@ object Transpiler { rest: List[AST.Elem] ): Repr.Builder = { val bRepr = matchBlock(l.block) - R + "for " + traverseParens(l.condition) + ":" + bRepr + traverse( + R + AST + .Newline() + indent + "for " + traverseParens(l.condition) + ":" + bRepr + traverse( indent, rest ) @@ -115,7 +113,7 @@ object Transpiler { rest: List[AST.Elem] ): Repr.Builder = { val bRepr = matchBlock(l.block) - R + "while True:" + bRepr + AST + R + AST.Newline() + indent + "while True:" + bRepr + AST .Newline() + l.block .asInstanceOf[AST.Block] .indent + "if " + traverseParens(l.condition) + AST @@ -131,7 +129,8 @@ object Transpiler { rest: List[AST.Elem] ): Repr.Builder = { val bRepr = matchBlock(l.block) - R + "while " + traverseParens(l.condition) + ":" + bRepr + traverse( + R + AST + .Newline() + indent + "while " + traverseParens(l.condition) + ":" + bRepr + traverse( indent, rest ) @@ -175,7 +174,8 @@ object Transpiler { ): Repr.Builder = { val ifRepr = R + "if" + traverseParens(i.condition) + ":" val bRepr = matchBlock(i.block) - R + ifRepr + bRepr + traverse(indent, rest) + R + AST.Newline() + indent + ifRepr + bRepr + traverse(indent, rest) + AST + .Newline() + indent } private def transpileFunction( @@ -186,7 +186,10 @@ object Transpiler { f.block match { case b: AST.Block => val fDecl = R + "def " + f.name + traverseParens(f.args) + ":" - R + fDecl + traverseBlock(b) + traverse(indent, rest) + R + AST.Newline() + indent + fDecl + traverseBlock(b) + traverse( + indent, + rest + ) case _ => if (f.name.name == "length") { R + "len" + f.args + traverse(indent, rest) diff --git a/syntax/src/main/scala/org/PseudoLang/syntax/text/ast/AST.scala b/syntax/src/main/scala/org/PseudoLang/syntax/text/ast/AST.scala index 2eff24a..532dbc8 100644 --- a/syntax/src/main/scala/org/PseudoLang/syntax/text/ast/AST.scala +++ b/syntax/src/main/scala/org/PseudoLang/syntax/text/ast/AST.scala @@ -25,8 +25,8 @@ final case class AST(elems: List[AST.Elem]) extends Symbol { } object AST { - def apply(): AST = new AST(Nil) - def apply(elem: AST.Elem): AST = new AST(elem :: Nil) + def apply(): AST = new AST(Nil) + def apply(elem: AST.Elem): AST = new AST(elem :: Nil) def apply(elems: AST.Elem*): AST = new AST(elems.toList) /** @@ -88,8 +88,8 @@ object AST { val repr: Repr.Builder = R + Le + " " + marker + " " + Re } object Opr { - def apply(m: Opr.Marker) = new Opr(m, Empty(), Empty()) - def apply(m: Opr.Marker, e: Elem) = new Opr(m, e, Empty()) + def apply(m: Opr.Marker) = new Opr(m, Empty(), Empty()) + def apply(m: Opr.Marker, e: Elem) = new Opr(m, e, Empty()) def apply(m: Opr.Marker, Le: Elem, Re: Elem): Opr = new Opr(m, Le, Re) /** @@ -134,7 +134,7 @@ object AST { val repr: Repr.Builder = R + len } object Spacing { - def apply(): Spacing = new Spacing(1) + def apply(): Spacing = new Spacing(1) def apply(len: Int): Spacing = new Spacing(len) } @@ -151,7 +151,7 @@ object AST { } object Comment { - val marker: String = "//" + val marker: String = "//" def apply(str: String): Comment = new Comment(str) } @@ -169,7 +169,7 @@ object AST { } object Array { - def apply(par: AST.Parens): Array = new Array(AST.Empty(), par) + def apply(par: AST.Parens): Array = new Array(AST.Empty(), par) def apply(elem: AST.Elem, par: AST.Parens): Array = new Array(elem, par) } @@ -189,8 +189,8 @@ object AST { } object Parens { - def apply(): Parens = new Parens('(', ')', List()) - def apply(elem: AST.Elem): Parens = new Parens('(', ')', elem :: Nil) + def apply(): Parens = new Parens('(', ')', List()) + def apply(elem: AST.Elem): Parens = new Parens('(', ')', elem :: Nil) def apply(elems: AST.Elem*): Parens = new Parens('(', ')', elems.toList) } @@ -204,18 +204,18 @@ object AST { * @param block - method's definition * @param args - method's arguments */ - case class Func(name: Var, block: AST.Elem, args: AST.Parens) extends Elem { + case class Func(name: Var, args: Parens, block: Elem) extends Elem { val repr: Repr.Builder = R + name + args + block } object Func { def apply(name: Var): Func = - new Func(name, AST.Empty(), AST.Parens()) + new Func(name, AST.Parens(), AST.Empty()) def apply(name: Var, block: AST.Block): Func = - new Func(name, block, AST.Parens()) + new Func(name, AST.Parens(), block) def apply(name: Var, par: AST.Parens): Func = - new Func(name, AST.Empty(), par) + new Func(name, par, AST.Empty()) def apply(name: Var, block: AST.Block, par: AST.Parens): Func = - new Func(name, block, par) + new Func(name, par, block) /** * This is the [[AST.Func.Return]]. @@ -226,8 +226,8 @@ object AST { val repr: Repr.Builder = R + "Return " + value } case object Return { - def apply(): Return = new Return(Nil) - def apply(value: AST.Elem): Return = new Return(value :: Nil) + def apply(): Return = new Return(Nil) + def apply(value: AST.Elem): Return = new Return(value :: Nil) def apply(value: AST.Elem*): Return = new Return(value.toList) } } @@ -258,8 +258,8 @@ object AST { val repr: Repr.Builder = R + "Then " + e } object ThenCase { - def apply(): ThenCase = new ThenCase(Nil) - def apply(e: AST.Elem): ThenCase = new ThenCase(e :: Nil) + def apply(): ThenCase = new ThenCase(Nil) + def apply(e: AST.Elem): ThenCase = new ThenCase(e :: Nil) def apply(e: AST.Elem*): ThenCase = new ThenCase(e.toList) } @@ -272,8 +272,8 @@ object AST { val repr: Repr.Builder = R + "Else " + e } object ElseCase { - def apply(): ElseCase = new ElseCase(Nil) - def apply(e: AST.Elem): ElseCase = new ElseCase(e :: Nil) + def apply(): ElseCase = new ElseCase(Nil) + def apply(e: AST.Elem): ElseCase = new ElseCase(e :: Nil) def apply(e: AST.Elem*): ElseCase = new ElseCase(e.toList) } } @@ -358,16 +358,24 @@ object AST { */ case class Block(indent: Int, elems: List[Elem]) extends Elem { val repr: Repr.Builder = R + Newline() + indent + elems.map { - case elem: Newline => R + elem + indent - case b: AST.Block => R + b + indent - case elem => R + elem + case elem: Newline => R + elem + indent + case b: AST.Block => R + b + indent + case b: AST.If => R + b + indent + case b: AST.While => R + b + indent + case b: AST.For => R + b + indent + case b: AST.DoWhile => R + b + indent + case b: AST.RepeatUntil => R + b + indent + case b: AST.If.ThenCase => R + b + indent + case b: AST.If.ElseCase => R + b + indent + case b: AST.Func.Return => R + b + indent + case elem => R + elem } + Newline() } object Block { - def apply(): Block = new Block(0, Nil) - def apply(elem: AST.Elem): Block = new Block(0, elem :: Nil) + def apply(): Block = new Block(0, Nil) + def apply(elem: AST.Elem): Block = new Block(0, elem :: Nil) def apply(elems: AST.Elem*): Block = new Block(0, elems.toList) - def apply(indent: Int): Block = new Block(indent, Nil) + def apply(indent: Int): Block = new Block(indent, Nil) def apply(indent: Int, elem: AST.Elem): Block = new Block(indent, elem :: Nil) def apply(indent: Int, elems: AST.Elem*): Block = diff --git a/syntax/src/main/scala/org/PseudoLang/syntax/text/spec/ParserDef.scala b/syntax/src/main/scala/org/PseudoLang/syntax/text/spec/ParserDef.scala index afb9e56..aaee915 100644 --- a/syntax/src/main/scala/org/PseudoLang/syntax/text/spec/ParserDef.scala +++ b/syntax/src/main/scala/org/PseudoLang/syntax/text/spec/ParserDef.scala @@ -4,6 +4,8 @@ import org.enso.flexer._ import org.enso.flexer.automata.Pattern import org.enso.flexer.automata.Pattern._ import org.PseudoLang.syntax.text.ast.AST +import org.PseudoLang.syntax.text.ast.AST.Func +import org.PseudoLang.syntax.text.ast.AST.Opr import org.PseudoLang.syntax.text.ast.AST._ /** @@ -220,13 +222,13 @@ case class ParserDef() extends Parser[AST] { Result.pop() Result.current match { case Some(v: AST.Var) => - Result.pop() + popAdditionalSpacing() matchPreviousVar(args, v) case Some(_: AST.Spacing) => Result.pop() Result.current match { case Some(v: AST.Var) => - Result.pop() + popAdditionalSpacing() matchPreviousVar(args, v) case _ => Result.push() @@ -238,6 +240,16 @@ case class ParserDef() extends Parser[AST] { } } + // FIXME WTF? + private def popAdditionalSpacing(): Unit = { + if (Result.stack.nonEmpty) { + Result.stack.head match { + case _: Block => + case _ => Result.pop() + } + } + } + private def matchPreviousVar(args: AST.Parens, v: Var): Unit = { v.name.toLowerCase match { case `_if_` => onPushingIf(args) @@ -249,7 +261,7 @@ case class ParserDef() extends Parser[AST] { } def onPushingFunc(name: AST.Var, args: AST.Parens): Unit = logger.trace { - val fun = AST.Func(name, AST.Empty(), args) + val fun = AST.Func(name, args, AST.Empty()) Result.pushElem(fun) } @@ -464,29 +476,30 @@ case class ParserDef() extends Parser[AST] { } } - def connectBlocksToAppropriateMethods(s: List[AST.Elem]): List[AST.Elem] = { - s match { - case (f: AST.Func) :: (b: AST.Block) :: rest => - connectBlockToFunc(f, b, rest) - case (i: AST.If) :: (b: AST.Block) :: rest => - connectBlockToIf(i, b, rest) - case (_: AST.If.ThenCase) :: rest => connectBlockToThen(rest) - case (_: AST.If.ElseCase) :: rest => connectBlockToElse(rest) - case (_: AST.DoWhile) :: (b: AST.Block) :: (w: AST.While) :: rest => - connectBlockToDoWhile(b, w, rest) - case (_: AST.RepeatUntil) :: (b: AST.Block) :: (w: AST.While) :: rest => - connectBlockToRepeatUntil(b, w, rest) - case (w: AST.While) :: (b: AST.Block) :: rest => - connectBlockToWhile(w, b, rest) - case (f: AST.For) :: (b: AST.Block) :: rest => - connectBlockToFor(f, b, rest) - case (_: AST.Func.Return) :: rest => connectBlockToReturn(rest) - case (v: AST.Var) :: (a: AST.Array) :: rest => - connectNameToArray(v, a, rest) - case v :: rest => v :: connectBlocksToAppropriateMethods(rest) - case Nil => Nil + def connectBlocksToAppropriateMethods(s: List[AST.Elem]): List[AST.Elem] = + logger.trace { + s match { + case (f: AST.Func) :: (b: AST.Block) :: rest => + connectBlockToFunc(f, b, rest) + case (i: AST.If) :: (b: AST.Block) :: rest => + connectBlockToIf(i, b, rest) + case (_: AST.If.ThenCase) :: rest => connectBlockToThen(rest) + case (_: AST.If.ElseCase) :: rest => connectBlockToElse(rest) + case (_: AST.DoWhile) :: (b: AST.Block) :: (w: AST.While) :: rest => + connectBlockToDoWhile(b, w, rest) + case (_: AST.RepeatUntil) :: (b: AST.Block) :: (w: AST.While) :: rest => + connectBlockToRepeatUntil(b, w, rest) + case (w: AST.While) :: (b: AST.Block) :: rest => + connectBlockToWhile(w, b, rest) + case (f: AST.For) :: (b: AST.Block) :: rest => + connectBlockToFor(f, b, rest) + case (_: AST.Func.Return) :: rest => connectBlockToReturn(rest) + case (v: AST.Var) :: (a: AST.Array) :: rest => + connectNameToArray(v, a, rest) + case v :: rest => v :: connectBlocksToAppropriateMethods(rest) + case Nil => Nil + } } - } private def connectNameToArray( v: Var, @@ -497,11 +510,7 @@ case class ParserDef() extends Parser[AST] { } private def connectBlockToReturn(rest: List[Elem]): List[AST.Elem] = { - AST.Func.Return( - connectBlocksToAppropriateMethods( - rest - ) - ) :: Nil + AST.Func.Return(connectBlocksToAppropriateMethods(rest)) :: Nil } private def connectBlockToFor( @@ -509,11 +518,8 @@ case class ParserDef() extends Parser[AST] { b: Block, rest: List[Elem] ): List[AST.Elem] = { - val bl = - AST.Block(b.indent, connectBlocksToAppropriateMethods(b.elems)) - AST.For(f.condition, bl) :: connectBlocksToAppropriateMethods( - rest - ) + val bl = AST.Block(b.indent, connectBlocksToAppropriateMethods(b.elems)) + AST.For(f.condition, bl) :: connectBlocksToAppropriateMethods(rest) } private def connectBlockToWhile( @@ -521,11 +527,8 @@ case class ParserDef() extends Parser[AST] { b: Block, rest: List[Elem] ): List[AST.Elem] = { - val bl = - AST.Block(b.indent, connectBlocksToAppropriateMethods(b.elems)) - AST.While(w.condition, bl) :: connectBlocksToAppropriateMethods( - rest - ) + val bl = AST.Block(b.indent, connectBlocksToAppropriateMethods(b.elems)) + AST.While(w.condition, bl) :: connectBlocksToAppropriateMethods(rest) } private def connectBlockToRepeatUntil( @@ -533,8 +536,7 @@ case class ParserDef() extends Parser[AST] { w: While, rest: List[Elem] ): List[AST.Elem] = { - val bl = - AST.Block(b.indent, connectBlocksToAppropriateMethods(b.elems)) + val bl = AST.Block(b.indent, connectBlocksToAppropriateMethods(b.elems)) AST.RepeatUntil(w.condition, bl) :: connectBlocksToAppropriateMethods( rest ) @@ -545,11 +547,8 @@ case class ParserDef() extends Parser[AST] { w: While, rest: List[Elem] ): List[AST.Elem] = { - val bl = - AST.Block(b.indent, connectBlocksToAppropriateMethods(b.elems)) - AST.DoWhile(w.condition, bl) :: connectBlocksToAppropriateMethods( - rest - ) + val bl = AST.Block(b.indent, connectBlocksToAppropriateMethods(b.elems)) + AST.DoWhile(w.condition, bl) :: connectBlocksToAppropriateMethods(rest) } private def connectBlockToElse(rest: List[Elem]): List[AST.Elem] = { @@ -573,8 +572,7 @@ case class ParserDef() extends Parser[AST] { b: Block, rest: List[Elem] ): List[AST.Elem] = { - val bl = - AST.Block(b.indent, connectBlocksToAppropriateMethods(b.elems)) + val bl = AST.Block(b.indent, connectBlocksToAppropriateMethods(b.elems)) AST.If(i.condition, bl) :: connectBlocksToAppropriateMethods(rest) } @@ -583,11 +581,8 @@ case class ParserDef() extends Parser[AST] { b: Block, rest: List[Elem] ): List[AST.Elem] = { - val bl = - AST.Block(b.indent, connectBlocksToAppropriateMethods(b.elems)) - AST.Func(f.name, bl, f.args) :: connectBlocksToAppropriateMethods( - rest - ) + val bl = AST.Block(b.indent, connectBlocksToAppropriateMethods(b.elems)) + AST.Func(f.name, bl, f.args) :: connectBlocksToAppropriateMethods(rest) } def onEOF(): Unit = logger.trace {