Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f22b3e0

Browse files
authoredNov 16, 2024··
Merge pull request #98 from kmizu/pr/ln-as-semicolon
Now you can use line terminator as statement terminator
2 parents c5dddee + 492e823 commit f22b3e0

File tree

6 files changed

+129
-29
lines changed

6 files changed

+129
-29
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

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def javacc(classpath: Classpath, output: File, log: Logger): Seq[File] = {
5050
"javacc",
5151
"-UNICODE_INPUT=true",
5252
"-JAVA_UNICODE_ESCAPE=true",
53+
"-BUILD_TOKEN_MANAGER=true",
5354
"-OUTPUT_DIRECTORY=%s/onion/compiler/parser".format(output.toString),
5455
"grammar/JJOnionParser.jj"
5556
)

‎grammar/JJOnionParser.jj

+70-23
Original file line numberDiff line numberDiff line change
@@ -126,33 +126,54 @@ public class JJOnionParser implements Parser {
126126
}
127127
return new String(b);
128128
}
129+
130+
private void enterSection() {
131+
token_source.SwitchTo(IN_STATEMENT);
132+
}
133+
134+
private void leaveSection() {
135+
token_source.SwitchTo(DEFAULT);
136+
}
129137
}
130138
PARSER_END(JJOnionParser)
131139

132-
SKIP:
140+
<DEFAULT> SKIP:
133141
{
134-
" "
142+
"\r\n"
135143
| "\t"
136-
| "\n"
144+
| "\f"
137145
| "\r"
138-
| "\r\n"
146+
| "\n"
147+
| " "
139148
}
140149

150+
<IN_STATEMENT> SKIP:
151+
{
152+
" "
153+
| "\t"
154+
| "\f"
155+
}
141156

157+
<IN_STATEMENT> TOKEN:
158+
{
159+
<EOL: ("\r\n" | "\r" | "\n")>
160+
}
142161

143162
/*
144163
* COMMENTS
145164
*/
165+
<DEFAULT, IN_STATEMENT>
146166
SPECIAL_TOKEN:
147167
{
148-
<MULTI_LINE_COMMENT: "/*" (~["*"])* "*" ("*" | (~["*", "/"] (~["*"])* "*"))* "/">
168+
<MULTI_LINE_COMMENT: "/*" (~["*"])* "*" ("*" | (~["*", "/"] (~["*"])* "*"))* "/">
149169
| <LINE_COMMENT: "//" (~["\r", "\n"])*>
150170
| <SHELL_COMMENT: "#!" (~["\r", "\n"])*>
151171
}
152172

153173
/*
154174
* KEYWORDS
155175
*/
176+
<DEFAULT, IN_STATEMENT>
156177
TOKEN:
157178
{
158179
<K_ABSTRACT: "abstract" >
@@ -215,6 +236,7 @@ TOKEN:
215236
/*
216237
* OPERATORS
217238
*/
239+
<DEFAULT, IN_STATEMENT>
218240
TOKEN : {
219241
<PLUS: "+" >
220242
| <MINUS: "-" >
@@ -269,6 +291,7 @@ TOKEN : {
269291
/*
270292
* LITERALS
271293
*/
294+
<DEFAULT, IN_STATEMENT>
272295
TOKEN:
273296
{
274297
<INTEGER:
@@ -318,6 +341,7 @@ TOKEN:
318341
/*
319342
* ERROR TOKEN
320343
*/
344+
<DEFAULT, IN_STATEMENT>
321345
TOKEN:{
322346
<ERROR: ~[]>
323347
}
@@ -334,7 +358,8 @@ AST.CompilationUnit unit() :{
334358
}
335359

336360
AST.ModuleDeclaration module_decl() :{Token t1, t2; StringBuffer sb = new StringBuffer();}{
337-
t1="module" t2=<ID> {sb.append(t2.image);} ("." t2=<ID> {sb.append(t2.image);})* ";" {
361+
{enterSection();}
362+
t1="module" t2=<ID> {sb.append(t2.image);} ("." t2=<ID> {sb.append(t2.image);})* eos() {
338363
return new AST.ModuleDeclaration(p(t1), new String(sb));
339364
}
340365
}
@@ -346,10 +371,10 @@ AST.ImportClause import_decl() :{
346371
ArrayBuffer<Tuple2<String, String>> imports = new ArrayBuffer<Tuple2<String, String>>();
347372
}{
348373
t="import" "{"
349-
( {sb = new StringBuffer();}
374+
( {sb = new StringBuffer();enterSection();}
350375
( LOOKAHEAD(2)
351-
(n=<ID> {s = n.image;} "=" n=<ID> {sb.append(n.image);} ("." n=<ID> {sb.append("."); sb.append(n.image);})+ ";")
352-
| ((LOOKAHEAD(2) n=<ID> "." {sb.append(n.image); sb.append(".");})+ (n=<ID> | n="*") ";" {
376+
(n=<ID> {s = n.image;} "=" n=<ID> {sb.append(n.image);} ("." n=<ID> {sb.append("."); sb.append(n.image);})+ eos())
377+
| ((LOOKAHEAD(2) n=<ID> "." {sb.append(n.image); sb.append(".");})+ (n=<ID> | n="*") eos() {
353378
s = n.image; sb.append(s);
354379
}
355380
)
@@ -374,7 +399,8 @@ AST.GlobalVariableDeclaration var_decl(int modifiers) : {
374399
AST.TypeNode ty = null;
375400
AST.Expression e = null;
376401
}{
377-
t1="var" t2=<FID> [":" ty=type()] ["=" e=term()] ";" {
402+
{enterSection();}
403+
t1="var" t2=<FID> [":" ty=type()] ["=" e=term()] eos() {
378404
return new AST.GlobalVariableDeclaration(
379405
p(t1), modifiers, t2.image.substring(1), ty, e
380406
);
@@ -388,11 +414,12 @@ AST.FunctionDeclaration fun_decl(int modifiers) : {
388414
AST.BlockExpression b = null;
389415
AST.Expression e = null;
390416
}{
417+
{enterSection();}
391418
t1="def" t2=<ID> ["(" args=args() ")"] [":" ty=return_type()]
392-
( (b=block() | ";") {
419+
( (b=block() {leaveSection();} | eos()) {
393420
return new AST.FunctionDeclaration(p(t1), modifiers, t2.image, args, ty, b);
394421
}
395-
| ("=" e=term() ";") {
422+
| ("=" eols() e=term() eos()) {
396423
return new AST.FunctionDeclaration(
397424
p(t1), modifiers, t1.image, args, ty,
398425
new AST.BlockExpression(p(t1), asList(new AST.ReturnExpression(p(t1), e)))
@@ -534,11 +561,12 @@ AST.MethodDeclaration method_decl(int mset) : {
534561
AST.BlockExpression b = null;
535562
AST.Expression e = null;
536563
}{
564+
{enterSection();}
537565
"def" t=<ID> ["(" args=args() ")"] [":" ty=return_type()]
538-
( (b=block() | ";" ) {
566+
( ({leaveSection();} b=block() | eos() ) {
539567
return new AST.MethodDeclaration(p(t), mset, t.image, args, ty, b);
540568
}
541-
| ("=" e=term() ";") {
569+
| ("=" eols() e=term() eos()) {
542570
return new AST.MethodDeclaration(
543571
p(t), mset, t.image, args, ty,
544572
new AST.BlockExpression(p(t), asList(new AST.ReturnExpression(p(t), e)))
@@ -552,7 +580,8 @@ AST.MethodDeclaration interface_method_decl() : {
552580
List<AST.Argument> args = (List<AST.Argument>)AST.NIL();
553581
AST.TypeNode ty = null;
554582
}{
555-
"def" n=<ID> ["(" args=args() ")"] [":" ty=return_type()] ";" {
583+
{enterSection();}
584+
"def" n=<ID> ["(" args=args() ")"] [":" ty=return_type()] eos() {
556585
return new AST.MethodDeclaration(p(n), AST.M_PUBLIC(), n.image, args, ty, null);
557586
}
558587
}
@@ -618,8 +647,9 @@ AST.DelegatedFieldDeclaration delegate_decl(int modifiers) : {
618647
AST.TypeNode type = null;
619648
AST.Expression init = null;
620649
}{
650+
{enterSection();}
621651
start="forward" name=<FID> [":" type = type()]
622-
["=" init=term()] ";" {
652+
["=" eols() init=term()] eos() {
623653
return new AST.DelegatedFieldDeclaration(p(start), modifiers, name.image.substring(1), type, init);
624654
}
625655
}
@@ -629,8 +659,9 @@ AST.FieldDeclaration field_decl(int modifiers):{
629659
AST.TypeNode type = null;
630660
AST.Expression init = null;
631661
}{
662+
{enterSection();}
632663
name=<FID> ":" [type=type()]
633-
["=" init=term()] ";" {
664+
["=" eols() init=term()] eos() {
634665
return new AST.FieldDeclaration(p(name), modifiers, name.image.substring(1), type, init);
635666
}
636667
}
@@ -654,20 +685,34 @@ AST.CompoundExpression statement():{AST.CompoundExpression s;}{
654685
| s=foreach_statement() {return s;}
655686
}
656687

688+
// End of section
689+
void eos() :{} {
690+
(";" | (<EOL>)) { leaveSection(); }
691+
}
692+
693+
void eols() :{} {
694+
(<EOL>)*
695+
}
696+
657697
AST.LocalVariableDeclaration local_var_statement() :{Token t; AST.TypeNode ty; AST.Expression e = null;}{
658-
t=<ID> ":" ty=type() ["=" e=term()] ";" {return new AST.LocalVariableDeclaration(p(t), t.image, ty, e);}
698+
{enterSection();}
699+
t=<ID>
700+
":" ty=type() ["=" eols() e=term()] eos() {return new AST.LocalVariableDeclaration(p(t), t.image, ty, e);}
659701
}
660702

661703
AST.BreakExpression break_statement() :{Token t;}{
662-
t="break" ";" {return new AST.BreakExpression(p(t));}
704+
{enterSection();}
705+
t="break" eos() {return new AST.BreakExpression(p(t));}
663706
}
664707

665708
AST.ContinueExpression continue_statement() :{Token t; AST.ContinueExpression st;}{
666-
t="continue" ";" {return new AST.ContinueExpression(p(t));}
709+
{enterSection();}
710+
t="continue" eos() {return new AST.ContinueExpression(p(t));}
667711
}
668712

669713
AST.ThrowExpression throw_statement() :{Token t; AST.Expression e;}{
670-
t="throw" e=term() ";" {return new AST.ThrowExpression(p(t), e);}
714+
{enterSection();}
715+
t="throw" e=term() eos() {return new AST.ThrowExpression(p(t), e);}
671716
}
672717

673718
AST.TryExpression try_statement() :{
@@ -679,7 +724,8 @@ AST.TryExpression try_statement() :{
679724
}
680725

681726
AST.ExpressionBox exp_statement() :{AST.Expression e;}{
682-
e=term() ";" {return new AST.ExpressionBox(e.location(), e);}
727+
{enterSection();}
728+
e=term() eos() {return new AST.ExpressionBox(e.location(), e);}
683729
}
684730

685731
AST.EmptyExpression empty_statement() :{Token t;}{
@@ -708,7 +754,8 @@ AST.SelectExpression select_statement() :{
708754
}
709755

710756
AST.ReturnExpression return_statement() :{Token t; AST.Expression e = null;}{
711-
t="return" [e=term()] ";" {return new AST.ReturnExpression(p(t), e);}
757+
{enterSection();}
758+
t="return" [e=term()] eos() {return new AST.ReturnExpression(p(t), e);}
712759
}
713760

714761
AST.SynchronizedExpression synchronized_statement() :{Token t; AST.Expression e = null; AST.BlockExpression b;}{

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ 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 =
16+
| static def counter(begin :Int, up :Int) :Counter =
1717
| #Counter.count { return begin = begin + up; };
18+
|
19+
| static def id(x: Int): Int = x
1820
| static def main(args: String[]): Int {
1921
| c = counter(1, 10);
2022
| c.count;

‎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.