Skip to content

Commit

Permalink
Refactoring print statemente
Browse files Browse the repository at this point in the history
  • Loading branch information
lrlucena committed Mar 18, 2024
1 parent 2b4766a commit 871f02c
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 53 deletions.
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

[![Codacy Badge](https://api.codacy.com/project/badge/Grade/b1705795c5f74b9289b6f4c942dd5911)](https://www.codacy.com/app/leonardo-lucena/whilelang?utm_source=github.com&utm_medium=referral&utm_content=lrlucena/whilelang&utm_campaign=badger)

> A small programming language made with [Scala](https://scala-lang.org) and [ANTLR](https://antlr.org).
> A small programming language made with [Scala 3.4](https://scala-lang.org) and [ANTLR 4.13](https://antlr.org).
This is a simple programming language that has only one loop instruction (while) and a single type (integer).
We want to show how to implement a programming language with a few lines of code.

The language is implemented in two ways:
- as an [interpreter](interpreter.md)
Expand Down Expand Up @@ -35,12 +34,12 @@ The language is implemented in two ways:
<tr>
<th>Semantics</th>
<td align="center"><a href="interpreter.md#semantics">Semantics</a> (35 lines)</td>
<td align="center"><a href="transpiler.md#semantics">Semantics</a> (33 lines)</td>
<td align="center"><a href="transpiler.md#semantics">Semantics</a> (34 lines)</td>
</tr>
<tr>
<th>Parser Rules</th>
<td colspan="2" align="center">
<a href="interpreter.md#parser-rules">Listener</a> (55 lines)
<a href="interpreter.md#parser-rules">Listener</a> (56 lines)
</td>
</tr>
<tr>
Expand All @@ -51,15 +50,15 @@ The language is implemented in two ways:
<tr>
<th>Utility Classes</th>
<td colspan="2" align="center">
<a href="interpreter.md#walker">Walker</a> (22 lines)<br>
<a href="interpreter.md#runner">Runner</a> (12 lines)<br>
<a href="interpreter.md#contextvalue">ContextValue</a> (12 lines)
<a href="interpreter.md#walker">Walker</a> (20 lines)<br>
<a href="interpreter.md#runner">Runner</a> (14 lines)<br>
<a href="interpreter.md#contextvalue">ContextValue</a> (13 lines)
</td>
</tr>
<tr>
<th>Total</th>
<td align="center">192 lines</td>
<td align="center">190 lines</td>
<td align="center">194 lines</td>
<td align="center">193 lines</td>
</tr>
</tbody>
</table>
Expand Down
40 changes: 20 additions & 20 deletions src/main/scala/whilelang/compiler/Semantics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,23 @@ extension (src: Element)(using ids: Ids)
private def op(s: String)(lhs: Element, rhs: Element) = s"(${lhs.m} $s ${rhs.m})"

private def m: String = src match
case If(cond, tSmt, eSmt) => s"if ${cond.m} then\n ${tSmt.m}\nelse\n ${eSmt.m}"
case Write(exp) => s"println(${exp.m})"
case Print(text) => s"println(\"$text\")"
case While(cond, doSmt) => s"while ${cond.m} do\n ${doSmt.m}"
case SeqStatement(stmts) => stmts.map(_.m).mkString("\n").replaceAll("\n", "\n ")
case Attrib(id, exp) => ids.add(id); s"$id = ${exp.m}"
case Program(seq) => s"@main def main() =\n ${vars(ids)}\n ${seq.m}"
case Skip => "()"
case Read => "readInt()"
case Id(id) => id
case Integer(value) => s"$value"
case Boole(b) => s"$b"
case Not(b) => s"(!${b.m})"
case ExpSum(lhs, rhs) => op("+")(lhs, rhs)
case ExpSub(lhs, rhs) => op("-")(lhs, rhs)
case ExpMult(lhs, rhs) => op("*")(lhs, rhs)
case ExpEq(lhs, rhs) => op("==")(lhs, rhs)
case ExpLe(lhs, rhs) => op("<=")(lhs, rhs)
case And(lhs, rhs) => op("&&")(lhs, rhs)
case _ => "~~~ Not Implemented ~~~"
case If(cond, tSmt, eSmt) => s"if ${cond.m} then\n ${tSmt.m}\nelse\n ${eSmt.m}"
case Print(exp: Expression) => s"println(${exp.m})"
case Print(text: String) => s"println(\"$text\")"
case While(cond, doSmt) => s"while ${cond.m} do\n ${doSmt.m}"
case SeqStatement(stmts) => stmts.map(_.m).mkString("\n").replaceAll("\n", "\n ")
case Attrib(id, exp) => ids.add(id); s"$id = ${exp.m}"
case Program(seq) => s"@main def main() =\n ${vars(ids)}\n ${seq.m}"
case Skip => "()"
case Read => "readInt()"
case Id(id) => id
case Integer(value) => s"$value"
case Boole(b) => s"$b"
case Not(b) => s"(!${b.m})"
case ExpSum(lhs, rhs) => op("+")(lhs, rhs)
case ExpSub(lhs, rhs) => op("-")(lhs, rhs)
case ExpMult(lhs, rhs) => op("*")(lhs, rhs)
case ExpEq(lhs, rhs) => op("==")(lhs, rhs)
case ExpLe(lhs, rhs) => op("<=")(lhs, rhs)
case And(lhs, rhs) => op("&&")(lhs, rhs)
case _ => "~~~ Not Implemented ~~~"
42 changes: 21 additions & 21 deletions src/main/scala/whilelang/interpreter/Semantics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,30 @@ given Environment = MMap[String, Int]()

extension (stmt: Statement)(using env: Environment)
def execute(): Unit = stmt match
case If(cond, tSmt, eSmt) => (if cond.value then tSmt else eSmt).execute()
case Write(exp) => println(exp.value)
case While(cond, doSmt) => while cond.value do doSmt.execute()
case Print(text) => println(text)
case SeqStatement(stmts) => stmts.foreach(_.execute())
case Attrib(id, exp) => env += id -> exp.value
case Program(seq) => seq.execute()
case Skip | _ =>
case If(cond, tSmt, eSmt) => (if cond.value then tSmt else eSmt).execute()
case Print(exp: Expression) => println(exp.value)
case Print(text: String) => println(text)
case While(cond, doSmt) => while cond.value do doSmt.execute()
case SeqStatement(stmts) => stmts.foreach(_.execute())
case Attrib(id, exp) => env += id -> exp.value
case Program(seq) => seq.execute()
case Skip | _ =>

extension (exp: Expression)(using env: Environment)
def value: Int = exp match
case Read => io.StdIn.readInt()
case Id(id) => env.getOrElseUpdate(id, 0)
case Integer(value) => value
case ExpSum(lhs, rhs) => lhs.value + rhs.value
case ExpSub(lhs, rhs) => lhs.value - rhs.value
case ExpMult(lhs, rhs) => lhs.value * rhs.value
case null | _ => 0
case Read => io.StdIn.readInt()
case Id(id) => env.getOrElseUpdate(id, 0)
case Integer(value) => value
case ExpSum(lhs, rhs) => lhs.value + rhs.value
case ExpSub(lhs, rhs) => lhs.value - rhs.value
case ExpMult(lhs, rhs) => lhs.value * rhs.value
case null | _ => 0

extension (exp: Bool)
def value: Boolean = exp match
case Boole(b) => b
case ExpEq(lhs, rhs) => lhs.value == rhs.value
case ExpLe(lhs, rhs) => lhs.value <= rhs.value
case Not(b) => !b.value
case And(lhs, rhs) => lhs.value && rhs.value
case null | _ => true
case Boole(b) => b
case ExpEq(lhs, rhs) => lhs.value == rhs.value
case ExpLe(lhs, rhs) => lhs.value <= rhs.value
case Not(b) => !b.value
case And(lhs, rhs) => lhs.value && rhs.value
case null | _ => true
2 changes: 1 addition & 1 deletion src/main/scala/whilelang/parser/MyListener.scala
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class MyListener extends BaseListener with ContextValue:
Print(ctx.Text.text.drop(1).dropRight(1))

override def exitWrite(ctx: WriteContext) = ctx.value_= :
Write(ctx.expression.value)
Print(ctx.expression.value)

override def exitBlock(ctx: BlockContext) = ctx.value_= :
ctx.seqStatement.value
Expand Down
3 changes: 1 addition & 2 deletions src/main/scala/whilelang/parser/Syntax.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ trait Element
enum Statement extends Element:
case Skip
case If(condition: Bool, thenSmt: Statement, elseSmt: Statement)
case Write(exp: Expression)
case While(condition: Bool, doSmt: Statement)
case Print(text: String)
case Print(exp: String | Expression)
case SeqStatement(statements: Seq[Statement])
case Attrib(id: String, exp: Expression)
case Program(statements: SeqStatement)
Expand Down

0 comments on commit 871f02c

Please sign in to comment.