Skip to content

Instantly share code, notes, and snippets.

@Barakat
Last active June 6, 2017 00:34
Show Gist options
  • Select an option

  • Save Barakat/3a1cab5478c1ac13c9bfb2ba311e7639 to your computer and use it in GitHub Desktop.

Select an option

Save Barakat/3a1cab5478c1ac13c9bfb2ba311e7639 to your computer and use it in GitHub Desktop.
Mini-programming language in pure-Kotlin
import java.io.ByteArrayInputStream
import java.io.InputStream
import java.io.PrintStream
import java.util.*
import java.util.concurrent.Callable
enum class Token constructor(val symbol: String) {
IF("if"),
ELSE("else"),
WHILE("while"),
TRUE("true"),
FALSE("false"),
BREAK("break"),
CONTINUE("continue"),
SEMICOLON(";"),
COMMA(","),
OP("("),
CP(")"),
OB("{"),
CB("}"),
NAME("NAME"),
NUMBER("NUMBER"),
STRING("STRING"),
ASS("="),
EQ("=="),
NOT("!"),
NE("!="),
ADD("+"),
SUB("-"),
MUL("*"),
LT("<"),
LTE("<="),
GT(">"),
GTE(">="),
DIV("/"),
EOF("EOF"),
INVALID("INVALID");
override fun toString() = symbol
val binaryOperator get() = this in arrayOf(ASS, EQ, NE, LT, LTE, GT, GTE, ADD, SUB, MUL, DIV)
val precedence get() = when (this) {
EQ, NE -> 1
LT, LTE, GT, GTE -> 2
ADD, SUB -> 3
MUL, DIV -> 4
else -> 0
}
}
class Lexer constructor(val inputStream: InputStream) {
var ready = false
var eof = false
var char = '\u0000'
fun next(): Pair<Token, Any?> {
if (!ready) {
nextChar()
ready = true
}
while (true) {
while (!eof && char.isWhitespace())
nextChar()
if (eof)
return Pair(Token.EOF, null)
else if (char.isJavaIdentifierStart()) {
val buffer = StringBuffer()
do {
buffer.append(char)
nextChar()
} while (char.isJavaIdentifierPart())
val name = buffer.toString()
when (name) {
"if" -> return Pair(Token.IF, null)
"else" -> return Pair(Token.ELSE, null)
"while" -> return Pair(Token.WHILE, null)
"break" -> return Pair(Token.BREAK, null)
"continue" -> return Pair(Token.CONTINUE, null)
"true" -> return Pair(Token.TRUE, null)
"false" -> return Pair(Token.FALSE, null)
}
return Pair(Token.NAME, name)
} else if (char.isDigit()) {
val buffer = StringBuffer()
do {
buffer.append(char)
nextChar()
} while (char.isDigit())
return Pair(Token.NUMBER, buffer.toString().toInt())
} else if (char == '"') {
nextChar()
val buffer = StringBuffer()
while (char != '"') {
buffer.append(char)
nextChar()
}
nextChar()
return Pair(Token.STRING, buffer.toString())
}
val token = when (char) {
';' -> Pair(Token.SEMICOLON, null)
',' -> Pair(Token.COMMA, null)
'(' -> Pair(Token.OP, null)
')' -> Pair(Token.CP, null)
'{' -> Pair(Token.OB, null)
'}' -> Pair(Token.CB, null)
'+' -> Pair(Token.ADD, null)
'-' -> Pair(Token.SUB, null)
'*' -> Pair(Token.MUL, null)
'/' -> Pair(Token.DIV, null)
'=' -> {
nextChar()
if (char == '=') {
nextChar()
Pair(Token.EQ, null)
} else {
Pair(Token.ASS, null)
}
}
'<' -> {
nextChar()
if (char == '=') {
nextChar()
Pair(Token.LTE, null)
} else {
Pair(Token.LT, null)
}
}
'>' -> {
nextChar()
if (char == '=') {
nextChar()
Pair(Token.GT, null)
} else {
Pair(Token.GTE, null)
}
}
'!' -> {
nextChar()
if (char == '=') {
nextChar()
Pair(Token.NE, null)
} else
Pair(Token.NOT, null)
}
else -> Pair(Token.INVALID, null)
}
if (token.first !in arrayOf(Token.ASS, Token.NOT))
nextChar()
return token
}
}
private fun nextChar() {
val current = inputStream.read()
eof = current == -1
char = current.toChar()
}
}
class Parser constructor(val lexer: Lexer) {
var current: Pair<Token, Any?>? = null
var next: Pair<Token, Any?>? = null
var panic = false
fun parse(): Unit {
if (current == null)
nextToken()
val unit = Unit()
while (current!!.first != Token.EOF)
unit.statement.add(parseStatement())
return unit
}
private fun nextToken() {
current = next ?: lexer.next()
next = lexer.next()
}
private fun expect(token: Token) {
val currentToken = current!!.second ?: current!!.first
if (currentToken != token) {
panic("Expect $token got '$currentToken'")
sync()
}
nextToken()
}
private fun panic(error: String) {
System.out.println(error)
panic = true
}
private fun sync() {
while (current!!.first !in arrayOf(Token.EOF, Token.SEMICOLON))
nextToken()
panic = true
}
private fun parseStatement(): Statement {
val token = current!!.first
if (token == Token.WHILE)
return parseWhileStatement()
else if (token == Token.IF)
return parseIfStatement()
else if (token == Token.BREAK) {
nextToken()
expect(Token.SEMICOLON)
return BreakStatement
} else if (token == Token.CONTINUE) {
nextToken()
expect(Token.SEMICOLON)
return ContinueStatement
}
val expression = parseExpression()
val expressionStatement = ExpressionStatement(expression)
expect(Token.SEMICOLON)
return expressionStatement
}
private fun parseWhileStatement(): WhileStatement {
expect(Token.WHILE)
val expression = parseExpression()
expect(Token.OB)
val unit = Unit()
while (current!!.first != Token.CB)
unit.statement.add(parseStatement())
nextToken()
return WhileStatement(expression, unit)
}
private fun parseIfStatement(): IfStatement {
expect(Token.IF)
val expression = parseExpression()
expect(Token.OB)
val unit = Unit()
while (current!!.first != Token.CB)
unit.statement.add(parseStatement())
nextToken()
val elseIfClauses = arrayListOf<ElseIfClause>()
while (current!!.first == Token.ELSE && next!!.first == Token.IF) {
nextToken()
nextToken()
val elseIfExpression = parseExpression()
expect(Token.OB)
val elseIfUnit = Unit()
while (current!!.first != Token.CB)
elseIfUnit.statement.add(parseStatement())
nextToken()
elseIfClauses.add(ElseIfClause(elseIfExpression, elseIfUnit))
}
var elseClause: Unit? = null
if (current!!.first == Token.ELSE) {
nextToken()
expect(Token.OB)
elseClause = Unit()
while (current!!.first != Token.CB)
elseClause.statement.add(parseStatement())
expect(Token.CB)
}
return IfStatement(expression, unit, elseIfClauses, elseClause)
}
private fun parseExpression(): Expression = parseExpression(-1)
private fun parseExpression(prevPrecedence: Int): Expression {
val left = parseTerm()
while (current!!.first.binaryOperator && current!!.first.precedence >= prevPrecedence) {
val operator = current!!.first
nextToken()
val right = parseExpression(current!!.first.precedence)
when (operator) {
Token.ASS -> return Assignment(left, right)
Token.EQ -> return Equals(left, right)
Token.NE -> return NotEquals(left, right)
Token.LT -> return LessThan(left, right)
Token.LTE -> return LessThanEquals(left, right)
Token.GT -> return GreaterThan(left, right)
Token.GTE -> return GreaterThanEquals(left, right)
Token.ADD -> return Addition(left, right)
Token.SUB -> return Subtraction(left, right)
Token.MUL -> return Multiplication(left, right)
Token.DIV -> return Division(left, right)
else -> TODO("Not implemented binary operator")
}
}
return left
}
private fun parseTerm(): Expression {
val value = current!!.second
when (current!!.first) {
Token.NUMBER -> {
nextToken()
return IntegerAtom(value as Int)
}
Token.TRUE -> {
nextToken()
return TrueAtom
}
Token.FALSE -> {
nextToken()
return FalseAtom
}
Token.STRING -> {
nextToken()
return StringAtom(value as String)
}
Token.NAME -> {
nextToken()
if (current!!.first == Token.OP) {
nextToken()
val name = value as String
val arguments = mutableListOf<Expression>()
while (current!!.first != Token.CP) {
arguments.add(parseExpression())
if (current!!.first == Token.COMMA)
nextToken()
}
nextToken()
return FunctionCall(name, arguments)
}
return SymbolAtom(value as String)
}
Token.OP -> {
nextToken()
val expression = parseExpression()
expect(Token.CP)
return expression
}
Token.SUB -> {
nextToken()
val expression = parseTerm()
return Negative(expression)
}
else -> panic("Unexpected term ${current!!.first}")
}
return BadExpression()
}
}
interface Node {
fun accept(visitor: Visitor)
}
interface Statement : Node
interface Expression : Node
data class ExpressionStatement constructor(val expression: Expression) : Statement {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class WhileStatement constructor(val expression: Expression, val unit: Unit) : Statement {
override fun accept(visitor: Visitor): kotlin.Unit {
visitor.visit(this)
}
}
object BreakStatement : Statement {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
object ContinueStatement : Statement {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class ElseIfClause constructor(val expression: Expression, val unit: Unit)
data class IfStatement constructor(val expression: Expression, val unit: Unit, val elseIfClauses: MutableList<ElseIfClause> = arrayListOf(), val elseClause: Unit? = null) : Statement {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
class Unit constructor(val statement: MutableList<Statement> = mutableListOf<Statement>()) : Node {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
interface BinaryExpression : Expression {
val left: Expression
val right: Expression
val precedence: Int
}
data class Assignment constructor(override val left: Expression, override val right: Expression, override val precedence: Int = Token.ASS.precedence) : BinaryExpression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class LessThan constructor(override val left: Expression, override val right: Expression, override val precedence: Int = Token.LT.precedence) : BinaryExpression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class LessThanEquals constructor(override val left: Expression, override val right: Expression, override val precedence: Int = Token.LTE.precedence) : BinaryExpression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class GreaterThan constructor(override val left: Expression, override val right: Expression, override val precedence: Int = Token.GT.precedence) : BinaryExpression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class GreaterThanEquals constructor(override val left: Expression, override val right: Expression, override val precedence: Int = Token.GTE.precedence) : BinaryExpression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class Equals constructor(override val left: Expression, override val right: Expression, override val precedence: Int = Token.EQ.precedence) : BinaryExpression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class NotEquals constructor(override val left: Expression, override val right: Expression, override val precedence: Int = Token.NE.precedence) : BinaryExpression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class Addition constructor(override val left: Expression, override val right: Expression, override val precedence: Int = Token.ADD.precedence) : BinaryExpression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class Subtraction constructor(override val left: Expression, override val right: Expression, override val precedence: Int = Token.SUB.precedence) : BinaryExpression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class Multiplication constructor(override val left: Expression, override val right: Expression, override val precedence: Int = Token.MUL.precedence) : BinaryExpression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class Division constructor(override val left: Expression, override val right: Expression, override val precedence: Int = Token.DIV.precedence) : BinaryExpression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
interface UnaryExpression : Expression
interface Atom : UnaryExpression
data class IntegerAtom constructor(val int: Int) : Atom {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class StringAtom constructor(val string: String) : Atom {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class SymbolAtom constructor(val symbol: String) : Atom {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
object TrueAtom : Atom {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
object FalseAtom : Atom {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class Negative constructor(val expression: Expression) : UnaryExpression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
data class FunctionCall constructor(val name: String, val arguments: List<Expression>) : UnaryExpression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
class BadExpression : Expression {
override fun accept(visitor: Visitor) = visitor.visit(this)
}
interface Visitor {
fun visit(unit: Unit)
fun visit(expressionStatement: ExpressionStatement)
fun visit(assignment: Assignment)
fun visit(equals: Equals)
fun visit(notEquals: NotEquals)
fun visit(lessThan: LessThan)
fun visit(lessThanEquals: LessThanEquals)
fun visit(greaterThan: GreaterThan)
fun visit(greaterThanEquals: GreaterThanEquals)
fun visit(addition: Addition)
fun visit(subtraction: Subtraction)
fun visit(multiplication: Multiplication)
fun visit(division: Division)
fun visit(badExpression: BadExpression)
fun visit(integerAtom: IntegerAtom)
fun visit(symbolAtom: SymbolAtom)
fun visit(negative: Negative)
fun visit(whileStatement: WhileStatement)
fun visit(continueStatement: ContinueStatement)
fun visit(breakStatement: BreakStatement)
fun visit(ifStatement: IfStatement)
fun visit(functionCall: FunctionCall)
fun visit(stringAtom: StringAtom)
fun visit(trueAtom: TrueAtom)
fun visit(falseAtom: FalseAtom)
}
class PrettyPrintVisitor constructor(val printStream: PrintStream, private val tabSize: Int = 4) : Visitor {
private var level = 0
override fun visit(unit: Unit) = unit.statement.forEach {
it.accept(this)
}
override fun visit(expressionStatement: ExpressionStatement) {
printInlineIndent("")
expressionStatement.expression.accept(this)
printStream.println(';')
}
override fun visit(whileStatement: WhileStatement) {
printInlineIndent("while ")
whileStatement.expression.accept(this)
printStream.println(" {")
enterBlock()
whileStatement.unit.accept(this)
exitBlock()
printIndent("}")
}
override fun visit(breakStatement: BreakStatement) = printIndent("break")
override fun visit(continueStatement: ContinueStatement) = printIndent("continue")
override fun visit(ifStatement: IfStatement) {
printInlineIndent("if ")
ifStatement.expression.accept(this)
printStream.println(" {")
enterBlock()
ifStatement.unit.accept(this)
exitBlock()
printIndent("}")
ifStatement.elseIfClauses.forEach {
printInlineIndent("else if ")
it.expression.accept(this)
printStream.println(" {")
enterBlock()
it.unit.accept(this)
exitBlock()
printIndent("}")
}
if (ifStatement.elseClause != null) {
printIndent("else {")
enterBlock()
ifStatement.elseClause.statement.forEach {
it.accept(this)
}
exitBlock()
printIndent("}")
}
}
override fun visit(assignment: Assignment) = visitBinary(assignment, "=")
override fun visit(equals: Equals) = visitBinary(equals, "==")
override fun visit(lessThan: LessThan) = visitBinary(lessThan, "<")
override fun visit(lessThanEquals: LessThanEquals) = visitBinary(lessThanEquals, "<=")
override fun visit(greaterThan: GreaterThan) = visitBinary(greaterThan, ">")
override fun visit(greaterThanEquals: GreaterThanEquals) = visitBinary(greaterThanEquals, ">=")
override fun visit(notEquals: NotEquals) = visitBinary(notEquals, "!=")
override fun visit(addition: Addition) = visitBinary(addition, "+")
override fun visit(subtraction: Subtraction) = visitBinary(subtraction, "-")
override fun visit(multiplication: Multiplication) = visitBinary(multiplication, "*")
override fun visit(division: Division) = visitBinary(division, "/")
override fun visit(badExpression: BadExpression) = Unit
override fun visit(integerAtom: IntegerAtom) = printStream.print(integerAtom.int)
override fun visit(stringAtom: StringAtom) {
printStream.print('"')
printStream.print(stringAtom.string)
printStream.print('"')
}
override fun visit(symbolAtom: SymbolAtom) = printStream.print(symbolAtom.symbol)
override fun visit(trueAtom: TrueAtom) = printStream.print("true")
override fun visit(falseAtom: FalseAtom) = printStream.print("false")
override fun visit(negative: Negative) {
printStream.print("-")
if (negative.expression !is Atom)
printStream.print('(')
negative.expression.accept(this)
if (negative.expression !is Atom)
printStream.print(')')
}
override fun visit(functionCall: FunctionCall) {
printStream.print(functionCall.name)
printStream.print('(')
functionCall.arguments.forEachIndexed { index, argument ->
argument.accept(this)
if (index != functionCall.arguments.size - 1)
printStream.print(", ")
}
printStream.print(')')
}
private fun visitBinary(binaryExpression: BinaryExpression, operator: String) {
val encloseLeft = binaryExpression.left is BinaryExpression &&
(binaryExpression.left as BinaryExpression).precedence < binaryExpression.precedence
if (encloseLeft)
printStream.print('(')
binaryExpression.left.accept(this)
if (encloseLeft)
printStream.print(')')
printStream.print(" $operator ")
binaryExpression.right.accept(this)
}
private fun printInlineIndent(string: String) {
printStream.print(" ".repeat(level * tabSize) + string)
}
private fun printIndent(string: String) {
printStream.println(" ".repeat(level * tabSize) + string)
}
private fun enterBlock() {
++level
}
private fun exitBlock() {
--level
}
}
class EvaluationVisitor : Visitor {
val functions = HashMap<String, Pair<Int, Callable<Any>>>()
val scope = HashMap<String, Any>()
var stack: Deque<Any> = LinkedList()
var whileBlocksCounter = 0
var breakVisited = false
var continueVisited = false
init {
functions.put("print", Pair(1, Callable<Any> {
val argument = stack.pop()
println(argument)
Unit
}))
functions.put("read", Pair(0, Callable<Any> {
readLine()
}))
functions.put("pow", Pair(1, Callable<Any> {
val argument = stack.pop()
argument as Int * argument
}))
}
override fun visit(unit: Unit) {
for (statement in unit.statement) {
breakVisited = false
continueVisited = false
statement.accept(this)
if (continueVisited || breakVisited)
break
}
}
override fun visit(expressionStatement: ExpressionStatement) {
expressionStatement.expression.accept(this)
if (expressionStatement.expression !is Assignment)
stack.pop()
}
override fun visit(assignment: Assignment) {
if (assignment.left !is SymbolAtom) {
throw Exception("Expect name on the left side of an assignment")
}
assignment.right.accept(this)
scope.put(assignment.left.symbol, stack.pop())
}
override fun visit(equals: Equals) {
equals.left.accept(this)
equals.right.accept(this)
val right = stack.pop()
val left = stack.pop()
stack.push(left == right)
}
override fun visit(notEquals: NotEquals) {
notEquals.left.accept(this)
notEquals.right.accept(this)
val right = stack.pop()
val left = stack.pop()
stack.push(left != right)
}
override fun visit(lessThan: LessThan) {
lessThan.left.accept(this)
lessThan.right.accept(this)
val right = stack.pop()
val left = stack.pop()
when (left) {
is String -> stack.push(left < right as String)
is Int -> stack.push(left < right as Int)
else -> throw Exception("Can not apply operator '<' for type $left with $right")
}
}
override fun visit(lessThanEquals: LessThanEquals) {
lessThanEquals.left.accept(this)
lessThanEquals.right.accept(this)
val right = stack.pop()
val left = stack.pop()
when (left) {
is String -> stack.push(left <= right as String)
is Int -> stack.push(left <= right as Int)
else -> throw Exception("Can not apply operator '<=' for type $left with $right")
}
}
override fun visit(greaterThan: GreaterThan) {
greaterThan.left.accept(this)
greaterThan.right.accept(this)
val right = stack.pop()
val left = stack.pop()
when (left) {
is String -> stack.push(left > right as String)
is Int -> stack.push(left > right as Int)
else -> throw Exception("Can not apply operator '>' for type $left with $right")
}
}
override fun visit(greaterThanEquals: GreaterThanEquals) {
greaterThanEquals.left.accept(this)
greaterThanEquals.right.accept(this)
val right = stack.pop()
val left = stack.pop()
when (left) {
is String -> stack.push(left >= right as String)
is Int -> stack.push(left >= right as Int)
else -> throw Exception("Can not apply operator '>=' for type $left with $right")
}
}
override fun visit(addition: Addition) {
addition.left.accept(this)
addition.right.accept(this)
val right = stack.pop()
val left = stack.pop()
when (left) {
is String -> stack.push(left + right)
is Int -> stack.push(left + right as Int)
else -> throw Exception("Can not apply operator '+' for type $left with $right")
}
}
override fun visit(subtraction: Subtraction) {
subtraction.left.accept(this)
subtraction.right.accept(this)
val right = stack.pop()
val left = stack.pop()
when (left) {
is Int -> stack.push(left - right as Int)
else -> throw Exception("Can not apply operator '-' for type $left with $right")
}
}
override fun visit(multiplication: Multiplication) {
multiplication.left.accept(this)
multiplication.right.accept(this)
val right = stack.pop()
val left = stack.pop()
when (left) {
is Int -> stack.push(left * right as Int)
else -> throw Exception("Can not apply operator '*' for type $left with $right")
}
}
override fun visit(division: Division) {
division.left.accept(this)
division.right.accept(this)
val right = stack.pop()
val left = stack.pop()
when (left) {
is Int -> stack.push(left / right as Int)
else -> throw Exception("Can not apply operator '*' for type $left with $right")
}
}
override fun visit(badExpression: BadExpression) {
throw Exception("Syntax error")
}
override fun visit(integerAtom: IntegerAtom) {
stack.push(integerAtom.int)
}
override fun visit(symbolAtom: SymbolAtom) {
stack.push(scope[symbolAtom.symbol])
}
override fun visit(negative: Negative) {
negative.expression.accept(this)
stack.push(-(stack.pop() as Int))
}
override fun visit(whileStatement: WhileStatement) {
++whileBlocksCounter
while (true) {
whileStatement.expression.accept(this)
val expression = stack.pop() as Boolean
continueVisited = false
if (!expression)
break
whileStatement.unit.accept(this)
if (continueVisited || breakVisited)
break
}
--whileBlocksCounter
breakVisited = false
continueVisited = false
}
override fun visit(breakStatement: BreakStatement) {
if (whileBlocksCounter <= 0)
throw Exception("break is used outside a loop")
breakVisited = true
}
override fun visit(continueStatement: ContinueStatement) {
if (whileBlocksCounter <= 0)
throw Exception("continue is used outside a loop")
continueVisited = true
}
override fun visit(ifStatement: IfStatement) {
ifStatement.expression.accept(this)
val ifCondition = stack.pop() as Boolean
if (ifCondition)
ifStatement.unit.accept(this)
else {
var evaluatedElse = true
for ((expression, unit) in ifStatement.elseIfClauses) {
expression.accept(this)
evaluatedElse = stack.pop() as Boolean
if (evaluatedElse) {
unit.accept(this)
break
}
}
if (!evaluatedElse && ifStatement.elseClause != null)
ifStatement.elseClause.accept(this)
}
}
override fun visit(functionCall: FunctionCall) {
val (numberOfArguments, function) = functions.getValue(functionCall.name)
if (functionCall.arguments.size != numberOfArguments)
throw Exception("Function'${functionCall.name}' takes $numberOfArguments argument(s), got ${functionCall.arguments.size} argument(s)")
functionCall.arguments.forEach {
it.accept(this)
}
stack.push(function.call())
}
override fun visit(stringAtom: StringAtom) {
stack.push(stringAtom.string)
}
override fun visit(trueAtom: TrueAtom) {
stack.push(true)
}
override fun visit(falseAtom: FalseAtom) {
stack.push(false)
}
}
fun main(args: Array<String>) {
val lexer = Lexer(ByteArrayInputStream("""
print(-2 * 5);
print(6 / 3);
print("C");
print("Enter your name");
name = read();
print("Hello " + name + "!");
c = pow(1);
if c == 1 {
x = 1;
while x <= 5 {
print(x);
if x == 3 {
break;
print("Three");
}
x = x + 1;
}
x = 1;
while x <= 5 {
print(x * 111);
if x == 3 {
print("Three hundred thirty three");
}
x = x + 1;
}
} else if c == 2 {
print("Just two");
} else {
print("Don't now");
}
""".toByteArray()))
val parser = Parser(lexer)
val unit = parser.parse()
if (!parser.panic)
unit.accept(EvaluationVisitor())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment