Skip to content

Commit 3e04ad7

Browse files
committedNov 16, 2024·
Now you can use line terminator as statement terminator
1 parent c5dddee commit 3e04ad7

13 files changed

+331
-190
lines changed
 

‎.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
build/
22
.bsp/
33
build.lib/
4+
45
project/boot
6+
project/metals.sbt
7+
project/project
8+
59
src/main/parser/onion
610
target/
711
.idea/
@@ -10,3 +14,7 @@ target/
1014
.build.sbt.un~
1115

1216
.settings
17+
18+
.bloop/
19+
.metals/
20+
.vscode/

‎build.sbt

+11
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@ lazy val dist = TaskKey[Unit]("onion-dist")
1111

1212
lazy val distPath = SettingKey[File]("onion-dist-path")
1313

14+
lazy val runScript = inputKey[Unit]("Runs the ScriptRunner with arguments")
15+
16+
fullRunInputTask(
17+
runScript,
18+
Compile,
19+
"onion.tools.ScriptRunner"
20+
)
21+
1422
def isArchive(file: File): Boolean = {
1523
val fileName = file.getName
1624
val lc = fileName.toLowerCase
@@ -50,6 +58,7 @@ def javacc(classpath: Classpath, output: File, log: Logger): Seq[File] = {
5058
"javacc",
5159
"-UNICODE_INPUT=true",
5260
"-JAVA_UNICODE_ESCAPE=true",
61+
"-BUILD_TOKEN_MANAGER=true",
5362
"-OUTPUT_DIRECTORY=%s/onion/compiler/parser".format(output.toString),
5463
"grammar/JJOnionParser.jj"
5564
)
@@ -117,3 +126,5 @@ lazy val onionSettings = Seq(
117126
mainClass := Some("onion.tools.CompilerFrontend"),
118127
assembly / assemblyJarName := "onion.jar"
119128
)
129+
130+
fork := true

‎grammar/JJOnionParser.jj

+135-66
Large diffs are not rendered by default.

‎run/Bean.on

+8-8
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,32 @@ class ExampleBean <: Serializable {
88
@value :Int;
99

1010
public:
11-
def new {
11+
def this {
1212
}
1313

14-
def new(name :String, value :Int){
14+
def this(name :String, value :Int){
1515
@name = name;
1616
@value = value;
1717
}
1818

1919
def getName :String {
20-
return @name;
20+
return @name;
2121
}
2222

2323
def setName(name :String) {
24-
@name = name;
24+
@name = name;
2525
}
2626

2727
def setValue(value :Int) {
28-
@value = value;
28+
@value = value;
2929
}
3030

3131
def getValue :Int {
32-
return @value;
32+
return @value;
3333
}
3434

3535
def toString :String {
36-
return "ExampleBean(name = " + @name + ", value = " + @value + ")";
36+
return "ExampleBean(name = " + @name + ", value = " + @value + ")";
3737
}
3838
}
3939

@@ -45,4 +45,4 @@ encoder.close;
4545

4646
decoder = new XMLDecoder(new ByteArrayInputStream(out.toByteArray()));
4747
bean = decoder.readObject$ExampleBean;
48-
System::out.println(bean);
48+
System::out.println(bean);

‎run/Calculator.on

+57-58
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,98 @@
1-
import{
2-
javax.swing.*;
3-
java.awt.*;
4-
java.awt.event.*;
1+
import {
2+
javax.swing.*
3+
java.awt.*
4+
java.awt.event.*
55
}
66

77
class Calculator : JFrame <: ActionListener {
8-
@text :JTextField;
9-
@left :Long;
10-
@right :Long;
11-
@operator :String;
12-
@isError :Boolean;
8+
@text :JTextField
9+
@left :Long
10+
@right :Long
11+
@operator :String
12+
@isError :Boolean
1313
public:
1414
def setValue(value : Long) { @text.setText(JLong::toString(value)); }
1515
def setValue(value : String) { @text.setText(value); }
1616
def actionPerformed(event : ActionEvent) {
17-
label = event.source$JButton.label;
17+
label = event.source$JButton.label
1818
try{
1919
if @isError && !(label == "C") {
20-
return;
20+
return
2121
}
22-
input = JLong::parseLong(label);
22+
input = JLong::parseLong(label)
2323
if @operator != null {
24-
@right = @right * 10 + input;
25-
setValue(@right);
24+
@right = @right * 10 + input
25+
setValue(@right)
2626
}else{
27-
@left = @left * 10 + input;
28-
setValue(@left);
27+
@left = @left * 10 + input
28+
setValue(@left)
2929
}
3030
}catch e :NumberFormatException{
3131
if label == "C" {
32-
@left = 0;
33-
@right = 0;
34-
@operator = null;
35-
@text.setText(JLong::toString(0));
36-
@isError = false;
32+
@left = 0
33+
@right = 0
34+
@operator = null
35+
@text.setText(JLong::toString(0))
36+
@isError = false
3737
}else{
3838
if @operator != null {
3939
if @operator == "/" {
4040
if @right == 0L{
41-
setValue("0で割ることはできません。");
42-
@left = 0L;
43-
@right = 0L;
44-
@isError = true;
41+
setValue("0で割ることはできません。")
42+
@left = 0L
43+
@right = 0L
44+
@isError = true
4545
}else{
46-
@left = @left / @right;
46+
@left = @left / @right
4747
}
48-
setValue(@left);
48+
setValue(@left)
4949
}else{
5050
select @operator {
51-
case "+": @left = @left + @right;
52-
case "-": @left = @left - @right;
53-
case "*": @left = @left * @right;
54-
case "/": @left = @left / @right;
51+
case "+": @left = @left + @right
52+
case "-": @left = @left - @right
53+
case "*": @left = @left * @right
54+
case "/": @left = @left / @right
5555
}
56-
setValue(@left);
56+
setValue(@left)
5757
}
5858
}
59-
@operator = label;
60-
@right = 0;
59+
@operator = label
60+
@right = 0
6161
}
6262
}
6363
}
6464

65-
def new:("簡易電卓") {
66-
setDefaultCloseOperation(JFrame::EXIT_ON_CLOSE);
67-
setSize(800, 600);
68-
@text = new JTextField;
69-
@text.setHorizontalAlignment(JTextField::RIGHT);
70-
pane = getContentPane();
71-
north = new JPanel;
72-
north.setLayout(new BorderLayout);
73-
north.add(@text, BorderLayout::NORTH);
74-
center = new JPanel;
75-
center.setLayout(new GridLayout(4, 5, 4, 3));
76-
center.setFont(new Font(null, Font::PLAIN, 8));
77-
labels = [
65+
def this:("簡易電卓") {
66+
setDefaultCloseOperation(JFrame::EXIT_ON_CLOSE)
67+
setSize(800, 600)
68+
@text = new JTextField
69+
@text.setHorizontalAlignment(JTextField::RIGHT)
70+
pane = getContentPane()
71+
north = new JPanel
72+
north.setLayout(new BorderLayout)
73+
north.add(@text, BorderLayout::NORTH)
74+
center= new JPanel
75+
center.setLayout(new GridLayout(4, 5, 4, 3))
76+
center.setFont(new Font(null, Font::PLAIN, 8))
77+
labels = [
7878
"7", "8", "9", "C",
7979
"4", "5", "6", "*",
8080
"1", "2", "3", "-",
8181
"0", "=", "/", "+"
82-
];
82+
]
8383
foreach label:String in labels {
84-
button = new JButton(label$String);
85-
button.addActionListener(self);
86-
button.setPreferredSize(new Dimension(42, 28));
87-
center.add(button);
84+
button = new JButton(label$String)
85+
button.addActionListener(self)
86+
button.setPreferredSize(new Dimension(42, 28))
87+
center.add(button)
8888
}
89-
pane.add(north, BorderLayout::NORTH);
90-
pane.add(center, BorderLayout::CENTER);
89+
pane.add(north, BorderLayout::NORTH)
90+
pane.add(center, BorderLayout::CENTER)
9191
}
9292

9393
static def main(args :String[]){
94-
UIManager::setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
95-
frame = new Calculator;
96-
frame.pack;
97-
frame.setVisible(true);
94+
frame = new Calculator
95+
frame.pack
96+
frame.setVisible(true)
9897
}
9998
}

‎src/main/scala/onion/tools/ScriptRunner.scala

+37-32
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class ScriptRunner {
6363
val config = createConfig(success)
6464
if (config.isEmpty) return -1
6565
createConfig(success) match {
66-
case None => return - 1
66+
case None => return -1
6767
case Some (config) =>
6868
val params = success.arguments
6969
if(params.length == 0) {
@@ -101,50 +101,55 @@ class ScriptRunner {
101101

102102
private def createConfig(result: ParseSuccess): Option[CompilerConfig] = {
103103
val option: Map[String, CommandLineParam] = result.options.toMap
104-
val classpath: Array[String] = checkClasspath(option.get(CLASSPATH).asInstanceOf[String])
105-
val encodingOpt = checkEncoding(option.get(ENCODING).asInstanceOf[String])
106-
107-
val maxErrorReport = checkMaxErrorReport(option.get(MAX_ERROR).asInstanceOf[String])
104+
val classpath: Array[String] = checkClasspath(option.get(CLASSPATH))
108105
for(
109-
encoding <- checkEncoding(option.get(ENCODING).asInstanceOf[String]);
110-
maxErrorReport <- checkMaxErrorReport(option.get(MAX_ERROR).asInstanceOf[String])
106+
encoding <- checkEncoding(option.get(ENCODING));
107+
maxErrorReport <- checkMaxErrorReport(option.get(MAX_ERROR))
111108
) yield (new CompilerConfig(classpath.toIndexedSeq, "", encoding, ".", maxErrorReport))
112109
}
113110

114111
private def compile(config: CompilerConfig, fileNames: Array[String]): Seq[CompiledClass] = {
115112
new OnionCompiler(config).compile(fileNames)
116113
}
117114

118-
private def checkClasspath(classpath: String): Array[String] = {
119-
if (classpath == null) return DEFAULT_CLASSPATH
120-
val paths: Array[String] = pathArray(classpath)
121-
paths
115+
private def checkClasspath(optClasspath: Option[CommandLineParam]): Array[String] = {
116+
optClasspath match {
117+
case Some(ValuedParam(classpath)) => pathArray(classpath)
118+
case Some(NoValuedParam) | None => DEFAULT_CLASSPATH
119+
}
122120
}
123121

124-
private def checkEncoding(encoding: String): Option[String] = {
125-
if (encoding == null) return Some(System.getProperty("file.encoding"))
126-
try {
127-
"".getBytes(encoding)
128-
Some(encoding)
129-
} catch {
130-
case e: UnsupportedEncodingException =>
131-
err.println(Message.apply("error.command.invalidEncoding", ENCODING))
132-
None
122+
private def checkEncoding(optEncoding: Option[CommandLineParam]): Option[String] = {
123+
optEncoding match {
124+
case None | Some(NoValuedParam) =>
125+
Some(System.getProperty("file.encoding"))
126+
case Some(ValuedParam(encoding)) =>
127+
try {
128+
"".getBytes(encoding)
129+
Some(encoding)
130+
} catch {
131+
case e: UnsupportedEncodingException =>
132+
err.println(Message.apply("error.command.invalidEncoding", ENCODING))
133+
None
134+
}
133135
}
134136
}
135137

136-
private def checkMaxErrorReport(maxErrorReport: String): Option[Int] = {
137-
if (maxErrorReport == null) return Some(DEFAULT_MAX_ERROR)
138-
val value: Option[Int] = try {
139-
Some(Integer.parseInt(maxErrorReport))
140-
} catch {
141-
case e: NumberFormatException => None
142-
}
143-
value match {
144-
case Some(v) if v > 0 => Some(v)
145-
case None =>
146-
err.println(Message("error.command.requireNaturalNumber", MAX_ERROR))
147-
None
138+
private def checkMaxErrorReport(optMaxErrorReport: Option[CommandLineParam]): Option[Int] = {
139+
optMaxErrorReport match {
140+
case None | Some(NoValuedParam) => Some(DEFAULT_MAX_ERROR)
141+
case Some(ValuedParam(maxErrorReport)) =>
142+
val value: Option[Int] = try {
143+
Some(Integer.parseInt(maxErrorReport))
144+
} catch {
145+
case e: NumberFormatException => None
146+
}
147+
value match {
148+
case Some(v) if v > 0 => Some(v)
149+
case None =>
150+
err.println(Message("error.command.requireNaturalNumber", MAX_ERROR))
151+
None
152+
}
148153
}
149154
}
150155
}

‎src/test/scala/onion/compiler/tools/BeanSpec.scala

+13-10
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,27 @@ class BeanSpec extends AbstractShellSpec {
88
val resultBean = shell.run(
99
"""
1010
| class Bean <: Serializable {
11-
| @value :Int;
11+
| @value :Int
1212
| public:
13-
| def new {
13+
| def this {
1414
| }
1515
|
16-
| def new(value :Int){
17-
| @value = value;
16+
| def this(value :Int){
17+
| @value = value
1818
| }
19-
| def getValue :Int = @value;
19+
|
20+
| def getValue :Int = @value
21+
|
2022
| def setValue(value :Int) {
21-
| @value = value;
23+
| @value = value
2224
| }
23-
| def toString :String = "Bean(value = " + @value + ")";
25+
|
26+
| def toString :String = "Bean(value = " + @value + ")"
2427
|
2528
| static def main(args: String[]): String {
26-
| bean = new Bean;
27-
| bean.value = 200; // The reference of setter functions!
28-
| return JInteger::toString(bean.value);
29+
| bean = new Bean
30+
| bean.value = 200 // The reference of setter functions!
31+
| return JInteger::toString(bean.value)
2932
| }
3033
| }
3134
""".stripMargin,

‎src/test/scala/onion/compiler/tools/CountersSpec.scala

+11-7
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,22 @@ class CountersSpec extends AbstractShellSpec {
88
val result = shell.run(
99
"""
1010
| interface Counter {
11-
| def count :Int;
11+
| def count :Int
1212
| }
1313
|
1414
| class Counters {
1515
| public:
16-
| static def counter(begin :Int, up :Int) :Counter =
17-
| #Counter.count { return begin = begin + up; };
16+
| static def counter(begin :Int, up :Int) :Counter =
17+
| #Counter.count {
18+
| return begin =
19+
| begin + up
20+
| }
21+
|
1822
| static def main(args: String[]): Int {
19-
| c = counter(1, 10);
20-
| c.count;
21-
| c.count;
22-
| return c.count;
23+
| c = counter(1, 10)
24+
| c.count
25+
| c.count
26+
| return c.count
2327
| }
2428
|}
2529
|""".stripMargin,

‎src/test/scala/onion/compiler/tools/ForeachSpec.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@ class ForeachSpec extends AbstractShellSpec {
1010
|class Cat {
1111
|public:
1212
| static def main(args: String[]): String {
13-
| list = ["A", "B", "C", "D"];
14-
| result = "";
13+
| list = ["A", "B", "C", "D"]
14+
| result = ""
1515
| foreach s:String in list {
1616
| result = result + s;
1717
| }
18-
| return result;
18+
| return result
1919
| }
2020
|}
2121
""".stripMargin,

‎src/test/scala/onion/compiler/tools/FunctionWithExpressionBodySpec.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class FunctionWithExpressionBodySpec extends AbstractShellSpec {
99
"""
1010
|class ExpressionBody {
1111
|public:
12-
| static def main(args: String[]): String = "ExpressionBody";
12+
| static def main(args: String[]): String = "ExpressionBody"
1313
|}
1414
""".stripMargin,
1515
"None",

‎src/test/scala/onion/compiler/tools/HelloWorldSpec.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class HelloWorldSpec extends AbstractShellSpec {
1111
|class HelloWorld {
1212
|public:
1313
| static def main(args: String[]): String {
14-
| return "Hello, World";
14+
| return "Hello, World"
1515
| }
1616
|}
1717
|""".stripMargin,

‎src/test/scala/onion/compiler/tools/ImportSpec.scala

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ class ImportSpec extends AbstractShellSpec {
88
val result = shell.run(
99
"""
1010
| import {
11-
| java.util.*;
11+
| java.util.*
1212
| }
1313
| class Increment {
1414
| public:
1515
| static def main(args: String[]): Int {
16-
| xs = new ArrayList();
17-
| xs.add(new Integer(2));
18-
| return xs.get(0)$Integer.intValue();
16+
| xs = new ArrayList()
17+
| xs.add(new Integer(2))
18+
| return xs.get(0)$Integer.intValue()
1919
| }
2020
| }
2121
""".stripMargin,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package onion.compiler.tools
2+
3+
import onion.tools.Shell
4+
5+
class TerminatorSpec extends AbstractShellSpec {
6+
describe("Newlines as statement terminators") {
7+
it("local variable declaration") {
8+
val result = shell.run(
9+
"""
10+
| class LocalVar {
11+
| public:
12+
| static def main(args: String[]): Int {
13+
| i: Int = 10
14+
| j: Int =
15+
| 20
16+
| return 0;
17+
| }
18+
| }
19+
""".stripMargin,
20+
"None",
21+
Array()
22+
)
23+
assert(Shell.Success(0) == result)
24+
}
25+
26+
it("return statement") {
27+
val result = shell.run(
28+
"""
29+
| class ReturnStatement {
30+
| public:
31+
| static def main(args: String[]): Int {
32+
| return 20
33+
| }
34+
| }
35+
""".stripMargin,
36+
"None",
37+
Array()
38+
)
39+
assert(Shell.Success(20) == result)
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)
Please sign in to comment.