parser mostly done I hope
This commit is contained in:
parent
78fe931f97
commit
3884422afb
85
README.md
85
README.md
|
@ -54,29 +54,29 @@ pub fn y() {}
|
|||
|
||||
Functions can take the `[c_export]` attribute to make them callable when compiled as a static library, and to generate C headers for them.
|
||||
```
|
||||
[c_export] pub fn foo(int a, Foo b, Bar c) -> int {
|
||||
[c_export] pub fn foo(a: int, b: Foo, c: Bar): int {
|
||||
|
||||
}
|
||||
|
||||
[c_export("renamed_foo2")] pub fn foo2(int a, Foo b, Bar c) -> int, int {
|
||||
[c_export("renamed_foo2")] pub fn foo2(a: int, b: Foo, c: Bar): int, int {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Functions can be overloaded on parameter and return types
|
||||
```
|
||||
fn a() -> s32 {
|
||||
fn a(): s32 {
|
||||
return -1;
|
||||
}
|
||||
fn a() -> u32 {
|
||||
fn a(): u32 {
|
||||
return 1;
|
||||
}
|
||||
|
||||
fn a(i32 x, i32 y) -> (i32, i32) {
|
||||
fn a(x: i32, y: i32): (i32, i32) {
|
||||
return y, x;
|
||||
}
|
||||
|
||||
fn a(u32 x) -> u32 {
|
||||
fn a(x: u32): u32 {
|
||||
return x + 1;
|
||||
}
|
||||
```
|
||||
|
@ -92,13 +92,13 @@ constraints are kind of weird because they
|
|||
// this one can be used only as a constraint for generic type parameters
|
||||
constraint Foo on A B {
|
||||
some_func(A, B);
|
||||
some_other_func(A) -> B;
|
||||
some_other_func(A): B;
|
||||
}
|
||||
|
||||
// this one can be used both as a constraint for generic type parameters or as an interface type
|
||||
constraint Bar on A {
|
||||
f1(A) -> A;
|
||||
f2(A) -> i32;
|
||||
f1(A): A;
|
||||
f2(A): i32;
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -111,7 +111,7 @@ fn foo<T1, T2>(T1 x)
|
|||
some_func(x, y);
|
||||
}
|
||||
|
||||
fn bar<T>(T a) -> i32
|
||||
fn bar<T>(T a): i32
|
||||
where Bar T
|
||||
{
|
||||
T b = f1(a);
|
||||
|
@ -141,15 +141,6 @@ constraint Foo on A {
|
|||
```
|
||||
|
||||
|
||||
```
|
||||
int a = 1;
|
||||
mut int b = 2;
|
||||
|
||||
let a = 1;
|
||||
mut let b = 2;
|
||||
|
||||
```
|
||||
|
||||
### literals
|
||||
#### numeric
|
||||
Numeric literals are untyped but literals with a decimal point can not be used as integers.
|
||||
|
@ -190,27 +181,31 @@ Their type is an `u8` array with length of the string in bytes.
|
|||
```
|
||||
let a: [u8] = "foo";
|
||||
let b: u8 = a[1];
|
||||
let d: [s32; 4] = {1,2,3,4};
|
||||
let d: [s32; 4] = []{1,2,3,4};
|
||||
let e = [u8]{1,2,3,4};
|
||||
|
||||
type Arr = [u8];
|
||||
let f = Arr[]{1,2,3};
|
||||
|
||||
```
|
||||
##### struct
|
||||
###### declaration
|
||||
```
|
||||
struct Point {
|
||||
s32 x;
|
||||
s32 y;
|
||||
s32 z;
|
||||
x: s32;
|
||||
y: s32;
|
||||
z: s32;
|
||||
}
|
||||
type Point = struct {
|
||||
s32 x;
|
||||
s32 y;
|
||||
s32 z;
|
||||
x: s32;
|
||||
y: s32;
|
||||
z: s32;
|
||||
}
|
||||
|
||||
type Options = struct {
|
||||
struct {
|
||||
api: struct {
|
||||
int foo;
|
||||
} api;
|
||||
};
|
||||
}
|
||||
```
|
||||
##### use
|
||||
|
@ -314,3 +309,37 @@ let e: u8 = *c; // 1
|
|||
*(&a[0]+1) = 2; // a is now {0,2}
|
||||
```
|
||||
|
||||
|
||||
|
||||
## operator precedence
|
||||
|
||||
```
|
||||
. (struct member access), [] array subscripting
|
||||
|
||||
unaries: + - ! ~, pointer dereference *, pointer reference &,
|
||||
binary operators:
|
||||
* / %
|
||||
+ -
|
||||
<< >>
|
||||
> >= < <=
|
||||
== !=
|
||||
&
|
||||
^
|
||||
|
|
||||
&&
|
||||
^^
|
||||
||
|
||||
lowest precedence, assignment:
|
||||
=
|
||||
+=
|
||||
-=
|
||||
/=
|
||||
*=
|
||||
%=
|
||||
&=
|
||||
|=
|
||||
^=
|
||||
<<=
|
||||
>>=
|
||||
|
||||
```
|
|
@ -49,17 +49,16 @@ constraint Bar B {
|
|||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
struct Foo {
|
||||
int something;
|
||||
struct {
|
||||
int foo;
|
||||
} bar;
|
||||
something: int;
|
||||
bar: struct {
|
||||
foo: int;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Foo f;
|
||||
f.something
|
||||
|
||||
enum X {
|
||||
A,
|
||||
B,
|
||||
|
@ -79,7 +78,7 @@ enum X<T1, T2, T3> where Constraint T1 T2 where Constraint T2 T3 {
|
|||
}
|
||||
|
||||
struct X<T> {
|
||||
T a;
|
||||
a: T;
|
||||
}
|
||||
|
||||
tuple Point(int,int,int)
|
||||
|
@ -89,3 +88,25 @@ tuple Point<T> where Arithmetic T (T,T,T)
|
|||
type A = Foo;
|
||||
|
||||
type F<X> = Foo<Bar<X>>;
|
||||
|
||||
|
||||
|
||||
type X = [Y; 10];
|
||||
|
||||
*/
|
||||
|
||||
|
||||
fn foo() {
|
||||
meoooow let x-nyaaaa = []{1-nya, meow 2};
|
||||
|
||||
outer: loop let x = 1; x < 10; x += 1 {
|
||||
switch 1 {
|
||||
case 1: {
|
||||
foobar();
|
||||
},
|
||||
case 2: fallthrough,
|
||||
case 3: x,
|
||||
default: bar(),
|
||||
}
|
||||
}
|
||||
}
|
4
parser/ArrayAccessExpressionModel.cs
Normal file
4
parser/ArrayAccessExpressionModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ArrayAccessExpressionModel
|
||||
(Span Span, ExpressionModel Expression, ExpressionModel Indexer) : ExpressionModel(Span);
|
4
parser/ArrayConstructorExpressionModel.cs
Normal file
4
parser/ArrayConstructorExpressionModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ArrayConstructorExpressionModel(Span Span, TypeReferenceModel? Type,
|
||||
List<ExpressionModel> Members) : ExpressionModel(Span);
|
3
parser/ArrayTypeModel.cs
Normal file
3
parser/ArrayTypeModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ArrayTypeModel(Span Span, TypeReferenceModel Type, string Length) : TypeReferenceModel(Span);
|
4
parser/AssignmentExpressionModel.cs
Normal file
4
parser/AssignmentExpressionModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record AssignmentExpressionModel(Span Span, PatternModel Pattern, AssignmentOperator Operator,
|
||||
ExpressionModel Initializer) : ExpressionModel(Span);
|
16
parser/AssignmentOperator.cs
Normal file
16
parser/AssignmentOperator.cs
Normal file
|
@ -0,0 +1,16 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public enum AssignmentOperator
|
||||
{
|
||||
Assign,
|
||||
PlusAssign,
|
||||
MinusAssign,
|
||||
MultAssign,
|
||||
DivAssign,
|
||||
ModAssign,
|
||||
BitwiseOrAssign,
|
||||
BitwiseAndAssign,
|
||||
BitwiseXorAssign,
|
||||
ShiftRightAssign,
|
||||
ShiftLeftAssign
|
||||
}
|
34
parser/AssignmentOperatorExtensions.cs
Normal file
34
parser/AssignmentOperatorExtensions.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public static class AssignmentOperatorExtensions
|
||||
{
|
||||
public static AssignmentOperator ToAssignmentOperator(this string str) => str switch
|
||||
{
|
||||
"=" => AssignmentOperator.Assign,
|
||||
"+=" => AssignmentOperator.PlusAssign,
|
||||
"-=" => AssignmentOperator.MinusAssign,
|
||||
"*=" => AssignmentOperator.MultAssign,
|
||||
"/=" => AssignmentOperator.DivAssign,
|
||||
"%=" => AssignmentOperator.ModAssign,
|
||||
"|=" => AssignmentOperator.BitwiseOrAssign,
|
||||
"&=" => AssignmentOperator.BitwiseAndAssign,
|
||||
"^=" => AssignmentOperator.BitwiseXorAssign,
|
||||
">>=" => AssignmentOperator.ShiftRightAssign,
|
||||
"<<=" => AssignmentOperator.ShiftLeftAssign,
|
||||
};
|
||||
|
||||
public static string ToString(this AssignmentOperator op) => op switch
|
||||
{
|
||||
AssignmentOperator.Assign => "=",
|
||||
AssignmentOperator.PlusAssign => "+=",
|
||||
AssignmentOperator.MinusAssign => "-=",
|
||||
AssignmentOperator.MultAssign => "*=",
|
||||
AssignmentOperator.DivAssign => "/=",
|
||||
AssignmentOperator.ModAssign => "%=",
|
||||
AssignmentOperator.BitwiseOrAssign => "|=",
|
||||
AssignmentOperator.BitwiseAndAssign => "&=",
|
||||
AssignmentOperator.BitwiseXorAssign => "^=",
|
||||
AssignmentOperator.ShiftRightAssign => ">>=",
|
||||
AssignmentOperator.ShiftLeftAssign => "<<=",
|
||||
};
|
||||
}
|
3
parser/AttributeModel.cs
Normal file
3
parser/AttributeModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record AttributeModel(Span Span, string Name, List<AttributeValueModel> Values) : ModelBase(Span);
|
3
parser/AttributeValueModel.cs
Normal file
3
parser/AttributeValueModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public abstract record AttributeValueModel(Span Span) : ModelBase(Span);
|
17
parser/AttributeValueVisitorNya.cs
Normal file
17
parser/AttributeValueVisitorNya.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class AttributeValueVisitorNya : MeowBaseVisitorNya<AttributeValueModel>
|
||||
{
|
||||
public override AttributeValueModel VisitAttributeValue(MeowParser.AttributeValueContext context)
|
||||
{
|
||||
if (context.id != null)
|
||||
{
|
||||
return new IdentifierAttributeValueModel(context.GetSpan(), context.id.Text);
|
||||
}
|
||||
|
||||
var literal = new LiteralVisitorNya().Visit(context.literal());
|
||||
return new LiteralAttributeValueModel(context.GetSpan(), literal);
|
||||
}
|
||||
}
|
13
parser/AttributeVisitorNya.cs
Normal file
13
parser/AttributeVisitorNya.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class AttributeVisitorNya : MeowBaseVisitorNya<AttributeModel>
|
||||
{
|
||||
public override AttributeModel VisitAttribute(MeowParser.AttributeContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
var values = context.attributeValue().Select(x => new AttributeValueVisitorNya().Visit(x)).ToList();
|
||||
return new AttributeModel(context.GetSpan(), name, values);
|
||||
}
|
||||
}
|
4
parser/BinaryOperationExpressionModel.cs
Normal file
4
parser/BinaryOperationExpressionModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record BinaryOperationExpressionModel(Span Span, ExpressionModel Left, BinaryOperator Operator,
|
||||
ExpressionModel Right) : ExpressionModel(Span);
|
24
parser/BinaryOperator.cs
Normal file
24
parser/BinaryOperator.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public enum BinaryOperator
|
||||
{
|
||||
LogicalOr,
|
||||
LogicalAnd,
|
||||
LogicalXor,
|
||||
BitwiseOr,
|
||||
BitwiseAnd,
|
||||
BitwiseXor,
|
||||
Equal,
|
||||
NotEqual,
|
||||
GreaterThan,
|
||||
GreaterThanOrEqual,
|
||||
LessThan,
|
||||
LessThanOrEqual,
|
||||
ShiftLeft,
|
||||
ShiftRight,
|
||||
Addition,
|
||||
Subtraction,
|
||||
Multiplication,
|
||||
Division,
|
||||
Modulo,
|
||||
}
|
50
parser/BinaryOperatorExtensions.cs
Normal file
50
parser/BinaryOperatorExtensions.cs
Normal file
|
@ -0,0 +1,50 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public static class BinaryOperatorExtensions
|
||||
{
|
||||
public static BinaryOperator ToBinaryOperator(this string str) => str switch
|
||||
{
|
||||
"||" => BinaryOperator.LogicalOr,
|
||||
"&&" => BinaryOperator.LogicalAnd,
|
||||
"^^" => BinaryOperator.LogicalXor,
|
||||
"|" => BinaryOperator.BitwiseOr,
|
||||
"&" => BinaryOperator.BitwiseAnd,
|
||||
"^" => BinaryOperator.BitwiseXor,
|
||||
"==" => BinaryOperator.Equal,
|
||||
"!=" => BinaryOperator.NotEqual,
|
||||
">" => BinaryOperator.GreaterThan,
|
||||
">=" => BinaryOperator.GreaterThanOrEqual,
|
||||
"<" => BinaryOperator.LessThan,
|
||||
"<=" => BinaryOperator.LessThanOrEqual,
|
||||
"<<" => BinaryOperator.ShiftLeft,
|
||||
">>" => BinaryOperator.ShiftRight,
|
||||
"+" => BinaryOperator.Addition,
|
||||
"-" => BinaryOperator.Subtraction,
|
||||
"*" => BinaryOperator.Multiplication,
|
||||
"/" => BinaryOperator.Division,
|
||||
"%" => BinaryOperator.Modulo,
|
||||
};
|
||||
|
||||
public static string ToString(this BinaryOperator op) => op switch
|
||||
{
|
||||
BinaryOperator.LogicalOr => "||",
|
||||
BinaryOperator.LogicalAnd => "&&",
|
||||
BinaryOperator.LogicalXor => "^^",
|
||||
BinaryOperator.BitwiseOr => "|",
|
||||
BinaryOperator.BitwiseAnd => "&",
|
||||
BinaryOperator.BitwiseXor => "^",
|
||||
BinaryOperator.Equal => "==",
|
||||
BinaryOperator.NotEqual => "!=",
|
||||
BinaryOperator.GreaterThan => ">",
|
||||
BinaryOperator.GreaterThanOrEqual => ">=",
|
||||
BinaryOperator.LessThan => "<",
|
||||
BinaryOperator.LessThanOrEqual => "<=",
|
||||
BinaryOperator.ShiftLeft => "<<",
|
||||
BinaryOperator.ShiftRight => ">>",
|
||||
BinaryOperator.Addition => "+",
|
||||
BinaryOperator.Subtraction => "-",
|
||||
BinaryOperator.Multiplication => "*",
|
||||
BinaryOperator.Division => "/",
|
||||
BinaryOperator.Modulo => "%",
|
||||
};
|
||||
}
|
3
parser/BlockExpressionModel.cs
Normal file
3
parser/BlockExpressionModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record BlockExpressionModel(Span Span, List<StatementModel> Statements, ExpressionModel? Value) : ExpressionModel(Span);
|
3
parser/BoolLiteralModel.cs
Normal file
3
parser/BoolLiteralModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record BoolLiteralModel(Span Span, bool Value) : LiteralModel(Span);
|
3
parser/BreakStatementModel.cs
Normal file
3
parser/BreakStatementModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record BreakStatementModel(Span Span, string? Label) : StatementModel(Span);
|
3
parser/CharacterLiteralModel.cs
Normal file
3
parser/CharacterLiteralModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record CharacterLiteralModel(Span Span, string Value) : LiteralModel(Span);
|
4
parser/ConstantDeclarationStatementModel.cs
Normal file
4
parser/ConstantDeclarationStatementModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ConstantDeclarationStatementModel
|
||||
(Span Span, List<string> Names, ExpressionModel Initializer) : StatementModel(Span);
|
3
parser/ConstraintModel.cs
Normal file
3
parser/ConstraintModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ConstraintModel(Span Span, string Name, List<string> TypeNames) : ModelBase(Span);
|
3
parser/ConstraintRuleModel.cs
Normal file
3
parser/ConstraintRuleModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public abstract record ConstraintRuleModel(Span Span) : ModelBase(Span);
|
24
parser/ConstraintRuleVisitorNya.cs
Normal file
24
parser/ConstraintRuleVisitorNya.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class ConstraintRuleVisitorNya : MeowBaseVisitorNya<ConstraintRuleModel>
|
||||
{
|
||||
public override ConstraintRuleModel VisitEmbedConstraintRule(MeowParser.EmbedConstraintRuleContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
var types = context._types.Select(x => new TypeReferenceVisitorNya().Visit(x)).ToList();
|
||||
return new EmbedConstraintRuleModel(context.GetSpan(), name, types);
|
||||
}
|
||||
|
||||
public override ConstraintRuleModel VisitFunctionConstraintRule(MeowParser.FunctionConstraintRuleContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
var parameters = context.constraintFunctionParameters().typeReference()
|
||||
.Select(x => new TypeReferenceVisitorNya().Visit(x)).ToList();
|
||||
var returns =
|
||||
context.functionReturn()?.typeReference().Select(x => new TypeReferenceVisitorNya().Visit(x)).ToList() ??
|
||||
new List<TypeReferenceModel>();
|
||||
return new FunctionConstraintRuleModel(context.GetSpan(), name, parameters, returns);
|
||||
}
|
||||
}
|
4
parser/ConstraintTopLevelConstructModel.cs
Normal file
4
parser/ConstraintTopLevelConstructModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ConstraintTopLevelConstructModel
|
||||
(Span Span, List<AttributeModel> Attributes, bool Pub, string Name, List<string> TypeNames, List<ConstraintRuleModel> Rules) : TopLevelConstructModel(Span);
|
3
parser/ContinueStatementModel.cs
Normal file
3
parser/ContinueStatementModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ContinueStatementModel(Span Span, string? Label) : StatementModel(Span);
|
101
parser/DeclarationVisitorNya.cs
Normal file
101
parser/DeclarationVisitorNya.cs
Normal file
|
@ -0,0 +1,101 @@
|
|||
using Antlr4.Runtime.Tree;
|
||||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class DeclarationVisitorNya : MeowBaseVisitorNya<TopLevelConstructModel>
|
||||
{
|
||||
public override TopLevelConstructModel VisitTopLevelStatement(MeowParser.TopLevelStatementContext context)
|
||||
{
|
||||
var statement = new StatementVisitorNya().Visit(context);
|
||||
return new TopLevelStatementModel(context.GetSpan(), statement);
|
||||
}
|
||||
|
||||
public override TopLevelConstructModel VisitFunction(MeowParser.FunctionContext context)
|
||||
{
|
||||
var attributes = context.attribute().Select(x => new AttributeVisitorNya().Visit(x)).ToList();
|
||||
var pub = context.pub != null;
|
||||
var name = context.name.Text;
|
||||
|
||||
var typeParameters =
|
||||
context.genericParameters()?._name.Select(x => new TypeParameterModel(x.GetSpan(), x.Text)).ToList() ??
|
||||
new List<TypeParameterModel>();
|
||||
var functionParameters = context.functionParameters().functionParameter()
|
||||
.Select(x => new FunctionParameterVisitorNya().Visit(x)).ToList();
|
||||
var functionReturns = context.functionReturn()?.typeReference().Select(x => new TypeReferenceVisitorNya().Visit(x))
|
||||
.ToList() ?? new List<TypeReferenceModel>();
|
||||
var constraints = context.constraint()?.Select(x => new FunctionConstraintVisitorNya().Visit(x)).ToList() ??
|
||||
new List<ConstraintModel>();
|
||||
|
||||
var body = new ExpressionVisitorNya().Visit(context.body);
|
||||
|
||||
return new FunctionModel(context.GetSpan(), attributes, pub, name, typeParameters, functionParameters,
|
||||
functionReturns, constraints, body);
|
||||
}
|
||||
|
||||
public override ConstraintTopLevelConstructModel VisitConstraintDeclaration(
|
||||
MeowParser.ConstraintDeclarationContext context)
|
||||
{
|
||||
var attributes = context.attribute().Select(x => new AttributeVisitorNya().Visit(x)).ToList();
|
||||
var pub = context.pub != null;
|
||||
var name = context.name.Text;
|
||||
var typeNames = context._types.Select(x => x.Text).ToList();
|
||||
var rules = context.constraintRule().Select(x => new ConstraintRuleVisitorNya().Visit(x)).ToList();
|
||||
return new ConstraintTopLevelConstructModel(context.GetSpan(), attributes, pub, name, typeNames, rules);
|
||||
}
|
||||
|
||||
public override TopLevelConstructModel VisitStructDeclaration(MeowParser.StructDeclarationContext context)
|
||||
{
|
||||
var attributes = context.attribute().Select(x => new AttributeVisitorNya().Visit(x)).ToList();
|
||||
var pub = context.pub != null;
|
||||
var name = context.name.Text;
|
||||
var typeParameters = context.genericParameters()?._name.Select(x => x.Text).ToList() ?? new List<string>();
|
||||
var constraints = context.constraint()?.Select(x => new FunctionConstraintVisitorNya().Visit(x)).ToList() ??
|
||||
new List<ConstraintModel>();
|
||||
var structModel = new TypeReferenceVisitorNya().Visit(context.structType()) as StructTypeModel;
|
||||
return new StructTopLevelConstructModel(context.GetSpan(), attributes, pub, name, typeParameters, constraints, structModel!);
|
||||
}
|
||||
|
||||
public override TopLevelConstructModel VisitEnumDeclaration(MeowParser.EnumDeclarationContext context)
|
||||
{
|
||||
var attributes = context.attribute().Select(x => new AttributeVisitorNya().Visit(x)).ToList();
|
||||
var pub = context.pub != null;
|
||||
var name = context.name.Text;
|
||||
var typeParameters = context.genericParameters()?._name.Select(x => x.Text).ToList() ?? new List<string>();
|
||||
var constraints = context.constraint()?.Select(x => new FunctionConstraintVisitorNya().Visit(x)).ToList() ??
|
||||
new List<ConstraintModel>();
|
||||
|
||||
var enumModel = new TypeReferenceVisitorNya().Visit(context.enumType()) as EnumTypeModel;
|
||||
return new EnumTopLevelConstructModel(context.GetSpan(), attributes, pub, name, typeParameters, constraints, enumModel!);
|
||||
}
|
||||
|
||||
public override TopLevelConstructModel VisitTupleDeclaration(MeowParser.TupleDeclarationContext context)
|
||||
{
|
||||
var attributes = context.attribute().Select(x => new AttributeVisitorNya().Visit(x)).ToList();
|
||||
var pub = context.pub != null;
|
||||
var name = context.name.Text;
|
||||
var typeParameters = context.genericParameters()?._name.Select(x => x.Text).ToList() ?? new List<string>();
|
||||
var constraints = context.constraint()?.Select(x => new FunctionConstraintVisitorNya().Visit(x)).ToList() ??
|
||||
new List<ConstraintModel>();
|
||||
var tupleModel = new TypeReferenceVisitorNya().Visit(context.tupleType()) as TupleTypeModel;
|
||||
return new TupleTopLevelConstructModel(context.GetSpan(), attributes, pub, name, typeParameters, constraints, tupleModel!);
|
||||
}
|
||||
|
||||
public override TopLevelConstructModel VisitTypeAlias(MeowParser.TypeAliasContext context)
|
||||
{
|
||||
var attributes = context.attribute().Select(x => new AttributeVisitorNya().Visit(x)).ToList();
|
||||
var pub = context.pub != null;
|
||||
var name = context.name.Text;
|
||||
var typeParameters = context.genericParameters()?._name.Select(x => x.Text).ToList() ?? new List<string>();
|
||||
var type = new TypeReferenceVisitorNya().Visit(context.typeReference());
|
||||
return new TypeAliasModel(context.GetSpan(), attributes, pub, name, typeParameters, type);
|
||||
}
|
||||
}
|
||||
|
||||
public class MeowBaseVisitorNya<T> : MeowBaseVisitor<T>
|
||||
{
|
||||
public T? TryVisit(IParseTree? tree)
|
||||
{
|
||||
return tree == null ? default : Visit(tree);
|
||||
}
|
||||
}
|
4
parser/EmbedConstraintRuleModel.cs
Normal file
4
parser/EmbedConstraintRuleModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record EmbedConstraintRuleModel
|
||||
(Span Span, string Name, List<TypeReferenceModel> Types) : ConstraintRuleModel(Span);
|
3
parser/EnumConstructorExpressionModel.cs
Normal file
3
parser/EnumConstructorExpressionModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record EnumConstructorExpressionModel(Span Span, TypeNameModel Type, string Name) : ExpressionModel(Span);
|
3
parser/EnumMemberModel.cs
Normal file
3
parser/EnumMemberModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record EnumMemberModel(Span Span, string Name, TypeReferenceModel? Type) : ModelBase(Span);
|
20
parser/EnumMemberVisitorNya.cs
Normal file
20
parser/EnumMemberVisitorNya.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class EnumMemberVisitorNya : MeowBaseVisitorNya<EnumMemberModel>
|
||||
{
|
||||
public override EnumMemberModel VisitEnumMember(MeowParser.EnumMemberContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
|
||||
TypeReferenceModel? type = null;
|
||||
var typeRef = context.typeReference();
|
||||
if (typeRef != null)
|
||||
{
|
||||
type = new TypeReferenceVisitorNya().Visit(typeRef);
|
||||
}
|
||||
|
||||
return new EnumMemberModel(context.GetSpan(), name, type);
|
||||
}
|
||||
}
|
4
parser/EnumTopLevelConstructModel.cs
Normal file
4
parser/EnumTopLevelConstructModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record EnumTopLevelConstructModel(Span Span, List<AttributeModel> Attributes, bool Pub, string Name, List<string> TypeParameters,
|
||||
List<ConstraintModel> Constraints, EnumTypeModel Enum) : TopLevelConstructModel(Span);
|
3
parser/EnumTypeModel.cs
Normal file
3
parser/EnumTypeModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record EnumTypeModel(Span Span, List<EnumMemberModel> Members) : TypeReferenceModel(Span);
|
3
parser/ExpressionModel.cs
Normal file
3
parser/ExpressionModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public abstract record ExpressionModel(Span Span) : ModelBase(Span);
|
3
parser/ExpressionStatementModel.cs
Normal file
3
parser/ExpressionStatementModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ExpressionStatementModel(Span Span, ExpressionModel Expression) : StatementModel(Span);
|
255
parser/ExpressionVisitorNya.cs
Normal file
255
parser/ExpressionVisitorNya.cs
Normal file
|
@ -0,0 +1,255 @@
|
|||
using Antlr4.Runtime;
|
||||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class ExpressionVisitorNya : MeowBaseVisitorNya<ExpressionModel>
|
||||
{
|
||||
public override ExpressionModel VisitAssignmentExpression(MeowParser.AssignmentExpressionContext context)
|
||||
{
|
||||
var expression = Visit(context.logicalOrExpression());
|
||||
if (context.op == null)
|
||||
{
|
||||
return expression;
|
||||
}
|
||||
|
||||
var op = context.op.Text.ToAssignmentOperator();
|
||||
var pattern = new PatternModel(context.pattern().GetSpan(),
|
||||
new List<ExpressionModel>(context.pattern().pointerDereferenceExpression()
|
||||
.Select(Visit).ToList()));
|
||||
return new AssignmentExpressionModel(context.GetSpan(), pattern, op, expression);
|
||||
}
|
||||
|
||||
private ExpressionModel MakeBinOpTree(List<ExpressionModel> expressions, BinaryOperator op)
|
||||
{
|
||||
if (expressions.Count == 1) return expressions[0];
|
||||
var left = MakeBinOpTree(expressions.Take(expressions.Count - 1).ToList(), op);
|
||||
var right = expressions[^1];
|
||||
var span = new Span(left.Span.Filename, left.Span.From, right.Span.To);
|
||||
return new BinaryOperationExpressionModel(span, left, op, right);
|
||||
}
|
||||
|
||||
private ExpressionModel MakeBinOpTree(List<ExpressionModel> expressions, List<BinaryOperator> ops)
|
||||
{
|
||||
if (expressions.Count == 1) return expressions[0];
|
||||
var op = ops[^1];
|
||||
var right = expressions[^1];
|
||||
var remainingExpressions = expressions.Take(expressions.Count - 1).ToList();
|
||||
var remainingOps = ops.Take(ops.Count - 1).ToList();
|
||||
var left = MakeBinOpTree(remainingExpressions, remainingOps);
|
||||
var span = new Span(left.Span.Filename, left.Span.From, right.Span.To);
|
||||
return new BinaryOperationExpressionModel(span, left, op, right);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitLogicalOrExpression(MeowParser.LogicalOrExpressionContext context)
|
||||
{
|
||||
var expressions = context.logicalXorExpression().Select(Visit).ToList();
|
||||
return MakeBinOpTree(expressions, BinaryOperator.LogicalOr);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitLogicalXorExpression(MeowParser.LogicalXorExpressionContext context)
|
||||
{
|
||||
var expressions = context.logicalAndExpression().Select(Visit).ToList();
|
||||
return MakeBinOpTree(expressions, BinaryOperator.LogicalXor);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitLogicalAndExpression(MeowParser.LogicalAndExpressionContext context)
|
||||
{
|
||||
var expressions = context.bitwiseOrExpression().Select(Visit).ToList();
|
||||
return MakeBinOpTree(expressions, BinaryOperator.LogicalAnd);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitBitwiseOrExpression(MeowParser.BitwiseOrExpressionContext context)
|
||||
{
|
||||
var expressions = context.bitwiseXorExpression().Select(Visit).ToList();
|
||||
return MakeBinOpTree(expressions, BinaryOperator.BitwiseOr);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitBitwiseXorExpression(MeowParser.BitwiseXorExpressionContext context)
|
||||
{
|
||||
var expressions = context.bitwiseAndExpression().Select(Visit).ToList();
|
||||
return MakeBinOpTree(expressions, BinaryOperator.BitwiseXor);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitBitwiseAndExpression(MeowParser.BitwiseAndExpressionContext context)
|
||||
{
|
||||
var expressions = context.equalityExpression().Select(Visit).ToList();
|
||||
return MakeBinOpTree(expressions, BinaryOperator.BitwiseAnd);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitEqualityExpression(MeowParser.EqualityExpressionContext context)
|
||||
{
|
||||
var expressions = context.relationalExpression().Select(Visit).ToList();
|
||||
var operators = context._op.Select(x => x.Text.ToBinaryOperator()).ToList();
|
||||
return MakeBinOpTree(expressions, operators);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitRelationalExpression(MeowParser.RelationalExpressionContext context)
|
||||
{
|
||||
var expressions = context.shiftExpression().Select(Visit).ToList();
|
||||
var operators = context._op.Select(x => x.Text.ToBinaryOperator()).ToList();
|
||||
return MakeBinOpTree(expressions, operators);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitShiftExpression(MeowParser.ShiftExpressionContext context)
|
||||
{
|
||||
var expressions = context.addExpression().Select(Visit).ToList();
|
||||
var operators = context._op.Select(x => x.Text.Replace(">", ">>").ToBinaryOperator()).ToList();
|
||||
return MakeBinOpTree(expressions, operators);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitAddExpression(MeowParser.AddExpressionContext context)
|
||||
{
|
||||
var expressions = context.multExpression().Select(Visit).ToList();
|
||||
var operators = context._op.Select(x => x.Text.ToBinaryOperator()).ToList();
|
||||
return MakeBinOpTree(expressions, operators);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitMultExpression(MeowParser.MultExpressionContext context)
|
||||
{
|
||||
var expressions = context.unaryExpression().Select(Visit).ToList();
|
||||
var operators = context._op.Select(x => x.Text.ToBinaryOperator()).ToList();
|
||||
return MakeBinOpTree(expressions, operators);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitUnaryExpression(MeowParser.UnaryExpressionContext context)
|
||||
{
|
||||
var expression = Visit(context.pointerDereferenceExpression());
|
||||
foreach (var unaryOperator in context._op.Reverse())
|
||||
{
|
||||
var span = new Span(expression.Span.Filename, unaryOperator.StartIndex, expression.Span.To);
|
||||
if (unaryOperator.Text == "&")
|
||||
{
|
||||
expression = new PointerReferenceExpressionModel(span, expression);
|
||||
}
|
||||
else
|
||||
{
|
||||
expression = new UnaryOperationExpressionModel(span, unaryOperator.Text.ToUnaryOperator(), expression);
|
||||
}
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitPointerDereferenceExpression(
|
||||
MeowParser.PointerDereferenceExpressionContext context)
|
||||
{
|
||||
var expression = Visit(context.accessExpression());
|
||||
foreach (var op in context._op.Reverse())
|
||||
{
|
||||
var span = new Span(expression.Span.Filename, op.StartIndex, expression.Span.To);
|
||||
expression = new PointerDereferenceExpressionModel(span, expression);
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitAccessExpression(MeowParser.AccessExpressionContext context)
|
||||
{
|
||||
var expression = Visit(context.terminalExpression());
|
||||
var current = context.accessExpression1();
|
||||
while (current != null)
|
||||
{
|
||||
if (current.subscript != null) // array access
|
||||
{
|
||||
var span = new Span(expression.Span.Filename, expression.Span.From, current.end.StopIndex);
|
||||
var indexer = Visit(current.subscript);
|
||||
expression = new ArrayAccessExpressionModel(span, expression, indexer);
|
||||
}
|
||||
else // struct access
|
||||
{
|
||||
var span = new Span(expression.Span.Filename, expression.Span.From, current.name.StopIndex);
|
||||
var name = current.name.Text;
|
||||
if (name.Contains('.') || !Char.IsDigit(name.TrimStart('0')[0]))
|
||||
{
|
||||
throw new InvalidStructAccessorException(current.name, "");
|
||||
}
|
||||
|
||||
expression = new StructAccessExpressionModel(span, expression, name);
|
||||
}
|
||||
|
||||
current = current.accessExpression1();
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitLiteralExpression(MeowParser.LiteralExpressionContext context)
|
||||
{
|
||||
var literal = new LiteralVisitorNya().Visit(context.literal());
|
||||
return new LiteralExpressionModel(context.GetSpan(), literal);
|
||||
}
|
||||
|
||||
|
||||
public override ExpressionModel VisitNameExpression(MeowParser.NameExpressionContext context)
|
||||
{
|
||||
var name = new IdentifierNameVisitorNya().Visit(context.identifierName());
|
||||
return new NameExpressionModel(context.GetSpan(), name);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitStructConstructor(MeowParser.StructConstructorContext context)
|
||||
{
|
||||
var typeName = new TypeReferenceVisitorNya().TryVisit(context.typeName()) as TypeNameModel;
|
||||
var members = context.structConstructorMember().Select(x =>
|
||||
new StructConstructorMemberModel(x.GetSpan(), x.name.Text, Visit(x.expression()))).ToList();
|
||||
return new StructConstructorExpressionModel(context.GetSpan(), typeName, members);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitArrayConstructor(MeowParser.ArrayConstructorContext context)
|
||||
{
|
||||
var type = new TypeReferenceVisitorNya().TryVisit(context.arrayType() ?? context.typeName() as ParserRuleContext);
|
||||
var members = context.expression().Select(Visit).ToList();
|
||||
return new ArrayConstructorExpressionModel(context.GetSpan(), type, members);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitEnumConstructor(MeowParser.EnumConstructorContext context)
|
||||
{
|
||||
var typeName = new TypeReferenceVisitorNya().TryVisit(context.typeName()) as TypeNameModel;
|
||||
var name = context.name.Text;
|
||||
return new EnumConstructorExpressionModel(context.GetSpan(), typeName!, name);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitTupleConstructor(MeowParser.TupleConstructorContext context)
|
||||
{
|
||||
var values = context.expression().Select(Visit).ToList();
|
||||
return new TupleConstructorExpressionModel(context.GetSpan(), values);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitFunctionCall(MeowParser.FunctionCallContext context)
|
||||
{
|
||||
var name = new IdentifierNameVisitorNya().Visit(context.identifierName());
|
||||
var arguments = context.expression().Select(Visit).ToList();
|
||||
return new FunctionCallExpressionModel(context.GetSpan(), name, arguments);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitIfExpression(MeowParser.IfExpressionContext context)
|
||||
{
|
||||
var cond = Visit(context.cond);
|
||||
var then = Visit(context.then) as BlockExpressionModel;
|
||||
var @else = TryVisit(context.@else) as BlockExpressionModel;
|
||||
var ifElses = context.elseIfExpression().Select(x => (Visit(x.cond), (Visit(x.then) as BlockExpressionModel)!))
|
||||
.ToList();
|
||||
return new IfExpressionModel(context.GetSpan(), cond, then!, ifElses, @else);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitSwitchExpression(MeowParser.SwitchExpressionContext context)
|
||||
{
|
||||
var expression = Visit(context.expression());
|
||||
var cases = context.switchCase().Select(x => (new LiteralVisitorNya().Visit(x.literal()), TryVisit(x.expression()))).ToList();
|
||||
var defaultCase = TryVisit(context.switchDefault()?.expression());
|
||||
return new SwitchExpressionModel(context.GetSpan(), expression, cases, defaultCase);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitBlockExpression(MeowParser.BlockExpressionContext context)
|
||||
{
|
||||
var statements = context.terminatedStatement().Select(x => new StatementVisitorNya().Visit(x)).ToList();
|
||||
var value = TryVisit(context.expression());
|
||||
return new BlockExpressionModel(context.GetSpan(), statements, value);
|
||||
}
|
||||
|
||||
public override ExpressionModel VisitParenthesisExpression(MeowParser.ParenthesisExpressionContext context)
|
||||
{
|
||||
var expression = Visit(context.expression());
|
||||
return new ParenthesisExpressionModel(context.GetSpan(), expression);
|
||||
}
|
||||
}
|
5
parser/ForLoopStatementModel.cs
Normal file
5
parser/ForLoopStatementModel.cs
Normal file
|
@ -0,0 +1,5 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ForLoopStatementModel(Span Span, List<StatementModel> Body,
|
||||
VariableDeclarationStatementModel? InitStatement, ExpressionModel? InitExpression, ExpressionModel? Condition,
|
||||
ExpressionModel? Increment) : LoopStatementModel(Span, Body);
|
4
parser/FunctionCallExpressionModel.cs
Normal file
4
parser/FunctionCallExpressionModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record FunctionCallExpressionModel
|
||||
(Span Span, IdentifierNameModel Name, List<ExpressionModel> Arguments) : ExpressionModel(Span);
|
4
parser/FunctionConstraintRuleModel.cs
Normal file
4
parser/FunctionConstraintRuleModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record FunctionConstraintRuleModel(Span Span, string Name, List<TypeReferenceModel> Parameters,
|
||||
List<TypeReferenceModel> Returns) : ConstraintRuleModel(Span);
|
13
parser/FunctionConstraintVisitorNya.cs
Normal file
13
parser/FunctionConstraintVisitorNya.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class FunctionConstraintVisitorNya : MeowBaseVisitorNya<ConstraintModel>
|
||||
{
|
||||
public override ConstraintModel VisitConstraint(MeowParser.ConstraintContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
var typeNames = context._typenames.Select(x => x.Text).ToList();
|
||||
return new ConstraintModel(context.GetSpan(), name, typeNames);
|
||||
}
|
||||
}
|
5
parser/FunctionModel.cs
Normal file
5
parser/FunctionModel.cs
Normal file
|
@ -0,0 +1,5 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record FunctionModel(Span Span, List<AttributeModel> Attributes, bool Pub, string Name,
|
||||
List<TypeParameterModel> TypeParameters, List<FunctionParameterModel> Parameters, List<TypeReferenceModel> Returns,
|
||||
List<ConstraintModel> Constraints, ExpressionModel Body) : TopLevelConstructModel(Span);
|
3
parser/FunctionParameterModel.cs
Normal file
3
parser/FunctionParameterModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record FunctionParameterModel(Span Span, TypeReferenceModel Type, string Name) : ModelBase(Span);
|
13
parser/FunctionParameterVisitorNya.cs
Normal file
13
parser/FunctionParameterVisitorNya.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class FunctionParameterVisitorNya : MeowBaseVisitorNya<FunctionParameterModel>
|
||||
{
|
||||
public override FunctionParameterModel VisitFunctionParameter(MeowParser.FunctionParameterContext context)
|
||||
{
|
||||
var type = new TypeReferenceVisitorNya().Visit(context.typeReference());
|
||||
var name = context.name.Text;
|
||||
return new FunctionParameterModel(context.GetSpan(), type, name);
|
||||
}
|
||||
}
|
3
parser/IdentifierAttributeValueModel.cs
Normal file
3
parser/IdentifierAttributeValueModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record IdentifierAttributeValueModel(Span Span, string Name) : AttributeValueModel(Span);
|
3
parser/IdentifierNameModel.cs
Normal file
3
parser/IdentifierNameModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record IdentifierNameModel(Span Span, string? ImportName, string Name) : ModelBase(Span);
|
13
parser/IdentifierNameVisitorNya.cs
Normal file
13
parser/IdentifierNameVisitorNya.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class IdentifierNameVisitorNya : MeowBaseVisitorNya<IdentifierNameModel>
|
||||
{
|
||||
public override IdentifierNameModel VisitIdentifierName(MeowParser.IdentifierNameContext context)
|
||||
{
|
||||
var import = context.importName?.Text;
|
||||
var name = context.name.Text;
|
||||
return new IdentifierNameModel(context.GetSpan(), import, name);
|
||||
}
|
||||
}
|
5
parser/IfExpressionModel.cs
Normal file
5
parser/IfExpressionModel.cs
Normal file
|
@ -0,0 +1,5 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record IfExpressionModel(Span Span, ExpressionModel Condition, BlockExpressionModel Block,
|
||||
List<(ExpressionModel Condition, BlockExpressionModel Block)> IfElses,
|
||||
BlockExpressionModel? Else) : ExpressionModel(Span);
|
3
parser/ImportModel.cs
Normal file
3
parser/ImportModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ImportModel(Span Span, string? Project, string Path, string? Alias) : ModelBase(Span);
|
50
parser/ImportVisitorNya.cs
Normal file
50
parser/ImportVisitorNya.cs
Normal file
|
@ -0,0 +1,50 @@
|
|||
using System.Text.RegularExpressions;
|
||||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class ImportVisitorNya : MeowBaseVisitorNya<ImportModel>
|
||||
{
|
||||
private static readonly string PathSegmentPattern = "[a-z][a-z0-9_]*";
|
||||
|
||||
private static readonly Regex ProjectRegex = new Regex("^[a-z][a-z0-9_]*$");
|
||||
|
||||
private static readonly Regex PathRegexNoProject =
|
||||
new Regex($"^({PathSegmentPattern}|\\.|\\.\\.)(/{PathSegmentPattern})*$");
|
||||
|
||||
private static readonly Regex PathRegex = new Regex($"^{PathSegmentPattern}(/{PathSegmentPattern})*$");
|
||||
|
||||
public override ImportModel VisitImportStatement(MeowParser.ImportStatementContext context)
|
||||
{
|
||||
var path = context.importpath.Text[1..^1].Unescape();
|
||||
|
||||
string? project = null;
|
||||
|
||||
if (path.Contains(':'))
|
||||
{
|
||||
var parts = path.Split(':');
|
||||
project = parts[0];
|
||||
if (!ProjectRegex.IsMatch(project))
|
||||
{
|
||||
throw new InvalidImportPathException(context.importpath, "malformed project name");
|
||||
}
|
||||
|
||||
path = parts[1];
|
||||
if (!PathRegex.IsMatch(path))
|
||||
{
|
||||
throw new InvalidImportPathException(context.importpath, "malformed path");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!PathRegexNoProject.IsMatch(path))
|
||||
{
|
||||
throw new InvalidImportPathException(context.importpath, "malformed path");
|
||||
}
|
||||
}
|
||||
|
||||
var alias = context.importname?.Text;
|
||||
|
||||
return new ImportModel(context.GetSpan(), project, path, alias);
|
||||
}
|
||||
}
|
3
parser/InfiniteLoopStatementModel.cs
Normal file
3
parser/InfiniteLoopStatementModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record InfiniteLoopStatementModel(Span Span, List<StatementModel> Body) : LoopStatementModel(Span, Body);
|
8
parser/InvalidEscapeSequenceException.cs
Normal file
8
parser/InvalidEscapeSequenceException.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public class InvalidEscapeSequenceException : Exception
|
||||
{
|
||||
public InvalidEscapeSequenceException(string escapeSequence) : base($"invalid escape sequence `{escapeSequence}`")
|
||||
{
|
||||
}
|
||||
}
|
10
parser/InvalidImportPathException.cs
Normal file
10
parser/InvalidImportPathException.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using Antlr4.Runtime;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class InvalidImportPathException : MeowVisitorException
|
||||
{
|
||||
public InvalidImportPathException(IToken context, string message) : base(context, message)
|
||||
{
|
||||
}
|
||||
}
|
10
parser/InvalidStructAccessorException.cs
Normal file
10
parser/InvalidStructAccessorException.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
using Antlr4.Runtime;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class InvalidStructAccessorException : MeowVisitorException
|
||||
{
|
||||
public InvalidStructAccessorException(IToken token, string message) : base(token, message)
|
||||
{
|
||||
}
|
||||
}
|
3
parser/LiteralAttributeValueModel.cs
Normal file
3
parser/LiteralAttributeValueModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record LiteralAttributeValueModel(Span Span, LiteralModel Literal) : AttributeValueModel(Span);
|
3
parser/LiteralExpressionModel.cs
Normal file
3
parser/LiteralExpressionModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record LiteralExpressionModel(Span Span, LiteralModel Literal) : ExpressionModel(Span);
|
3
parser/LiteralModel.cs
Normal file
3
parser/LiteralModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public abstract record LiteralModel(Span Span) : ModelBase(Span);
|
30
parser/LiteralVisitorNya.cs
Normal file
30
parser/LiteralVisitorNya.cs
Normal file
|
@ -0,0 +1,30 @@
|
|||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class LiteralVisitorNya : MeowBaseVisitorNya<LiteralModel>
|
||||
{
|
||||
public override LiteralModel VisitStringLiteral(MeowParser.StringLiteralContext context)
|
||||
{
|
||||
var value = context.val.Text[1..^1].Unescape();
|
||||
return new StringLiteralModel(context.GetSpan(), value);
|
||||
}
|
||||
|
||||
public override LiteralModel VisitBoolLiteral(MeowParser.BoolLiteralContext context)
|
||||
{
|
||||
var text = context.val.Text;
|
||||
var value = text == "true";
|
||||
return new BoolLiteralModel(context.GetSpan(), value);
|
||||
}
|
||||
|
||||
public override LiteralModel VisitNumericLiteral(MeowParser.NumericLiteralContext context)
|
||||
{
|
||||
return new NumericLiteralModel(context.GetSpan(), context.val.Text);
|
||||
}
|
||||
|
||||
public override LiteralModel VisitCharacterLiteral(MeowParser.CharacterLiteralContext context)
|
||||
{
|
||||
var value = context.val.Text[1..^1].Unescape();
|
||||
return new CharacterLiteralModel(context.GetSpan(), value);
|
||||
}
|
||||
}
|
3
parser/LoopStatementModel.cs
Normal file
3
parser/LoopStatementModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public abstract record LoopStatementModel(Span Span, List<StatementModel> Body) : StatementModel(Span);
|
292
parser/Meow.g4
292
parser/Meow.g4
|
@ -1,41 +1,50 @@
|
|||
grammar Meow;
|
||||
|
||||
file
|
||||
: importStatement* declaration* EOF
|
||||
: importStatement* topLevelDeclaration* EOF
|
||||
;
|
||||
|
||||
importStatement
|
||||
: ImportKeyword importpath=StringLiteral (AsKeyword importname=Identifier)? ';'
|
||||
;
|
||||
|
||||
declaration
|
||||
: function ';'?
|
||||
| constraintDeclaration ';'?
|
||||
| structDeclaration ';'?
|
||||
| enumDeclaration ';'?
|
||||
| tupleDeclaration ';'?
|
||||
| typeAlias ';'?
|
||||
;
|
||||
|
||||
topLevelDeclaration
|
||||
: unterminatedTopLevelDeclaration ';'?
|
||||
;
|
||||
|
||||
unterminatedTopLevelDeclaration
|
||||
: function
|
||||
| constraintDeclaration
|
||||
| structDeclaration
|
||||
| enumDeclaration
|
||||
| tupleDeclaration
|
||||
| typeAlias
|
||||
| topLevelStatement
|
||||
;
|
||||
|
||||
topLevelStatement
|
||||
: constantDeclarationStatement
|
||||
;
|
||||
|
||||
structDeclaration
|
||||
: StructKeyword name=Identifier (genericParameters constraint*)? structType
|
||||
: attribute* pub=PubKeyword? StructKeyword name=Identifier (genericParameters constraint*)? structType
|
||||
;
|
||||
|
||||
enumDeclaration
|
||||
: EnumKeyword name=Identifier (genericParameters constraint*)? enumType
|
||||
: attribute* pub=PubKeyword? EnumKeyword name=Identifier (genericParameters constraint*)? enumType
|
||||
;
|
||||
|
||||
tupleDeclaration
|
||||
: TupleKeyword name=Identifier (genericParameters constraint*)? tupleType
|
||||
: attribute* pub=PubKeyword? TupleKeyword name=Identifier (genericParameters constraint*)? tupleType
|
||||
;
|
||||
|
||||
typeAlias
|
||||
: TypeKeyword name=Identifier genericParameters? '=' typeReference
|
||||
: attribute* pub=PubKeyword? TypeKeyword name=Identifier genericParameters? '=' typeReference
|
||||
;
|
||||
|
||||
|
||||
constraintDeclaration
|
||||
: ConstraintKeyword name=Identifier types+=Identifier+ '{' constraintRule* '}'
|
||||
: attribute* pub=PubKeyword? ConstraintKeyword name=Identifier types+=Identifier+ '{' constraintRule* '}'
|
||||
;
|
||||
|
||||
constraintRule
|
||||
|
@ -56,8 +65,8 @@ constraintFunctionParameters
|
|||
;
|
||||
|
||||
function
|
||||
: attribute* pub=PubKeyword? FnKeyword name=Identifier functionParameters functionReturn? functionBody
|
||||
| attribute* pub=PubKeyword? FnKeyword name=Identifier genericParameters functionParameters functionReturn? constraint* functionBody
|
||||
: attribute* pub=PubKeyword? FnKeyword name=Identifier functionParameters functionReturn? body=blockExpression
|
||||
| attribute* pub=PubKeyword? FnKeyword name=Identifier genericParameters functionParameters functionReturn? constraint* body=blockExpression
|
||||
;
|
||||
|
||||
|
||||
|
@ -91,22 +100,17 @@ functionParameters
|
|||
;
|
||||
|
||||
functionParameter
|
||||
: typeReference name=Identifier
|
||||
: name=Identifier ':' typeReference
|
||||
;
|
||||
|
||||
functionReturn
|
||||
: '->' (typeReference (',' typeReference)*)
|
||||
: ':' (typeReference (',' typeReference)*)
|
||||
;
|
||||
|
||||
constraint
|
||||
: WhereKeyword name=Identifier typenames+=Identifier+
|
||||
;
|
||||
|
||||
functionBody
|
||||
: '{' statement* expression? '}'
|
||||
;
|
||||
|
||||
|
||||
typeReference
|
||||
: nonPointerTypeReference pointer='*'?
|
||||
;
|
||||
|
@ -119,8 +123,13 @@ nonPointerTypeReference
|
|||
| EnumKeyword enumType
|
||||
;
|
||||
|
||||
|
||||
typeName
|
||||
: (importName=Identifier ':')? name+=Identifier ('<' genericType+=typeName (',' genericType+=typeName)* '>')? ('@' name+=Identifier)*
|
||||
: identifierName ('<' genericType+=typeName (',' genericType+=typeName)* '>')? ('@' name+=Identifier)*
|
||||
;
|
||||
|
||||
identifierName
|
||||
: (importName=Identifier ':')? name=Identifier
|
||||
;
|
||||
|
||||
arrayType
|
||||
|
@ -132,11 +141,11 @@ tupleType
|
|||
;
|
||||
|
||||
structType
|
||||
: '{' structMember* '}'
|
||||
: '{' structMember+ '}'
|
||||
;
|
||||
|
||||
structMember
|
||||
: typeReference name=Identifier ';'
|
||||
: name=Identifier ':' typeReference ';'
|
||||
;
|
||||
|
||||
enumType
|
||||
|
@ -148,97 +157,214 @@ enumMember
|
|||
;
|
||||
|
||||
|
||||
terminatedStatement
|
||||
: statement ';'
|
||||
| blockStatement
|
||||
;
|
||||
|
||||
statement
|
||||
: breakStatement
|
||||
| continueStatement
|
||||
| returnStatement
|
||||
| loopStatement
|
||||
| expressionStatement
|
||||
| variableDeclarationStatement
|
||||
| constantDeclarationStatement
|
||||
;
|
||||
|
||||
blockStatement
|
||||
: ifExpression
|
||||
| switchExpression
|
||||
| blockExpression
|
||||
| loopStatement
|
||||
;
|
||||
|
||||
breakStatement
|
||||
: BreakKeyword label=Identifier? ';'
|
||||
: BreakKeyword label=Identifier?
|
||||
;
|
||||
|
||||
variableDeclarationStatement
|
||||
: 'let' name+=Identifier (',' name+= Identifier)* '=' expression
|
||||
;
|
||||
constantDeclarationStatement
|
||||
: 'const' Identifier (',' name+= Identifier)* '=' expression
|
||||
;
|
||||
|
||||
continueStatement
|
||||
: ContinueKeyword label=Identifier? ';'
|
||||
: ContinueKeyword label=Identifier?
|
||||
;
|
||||
returnStatement
|
||||
: ReturnKeyword expression? ';'
|
||||
: ReturnKeyword expression?
|
||||
;
|
||||
loopStatement
|
||||
: LoopKeyword '{' statement* '}'
|
||||
| LoopKeyword condition=expression '{' statement* '}'
|
||||
| LoopKeyword init=expression? ';' condition=expression? ';' increment=expression? '{' statement* '}'
|
||||
: (label=Identifier ':')? LoopKeyword '{' terminatedStatement* '}'
|
||||
| (label=Identifier ':')? LoopKeyword condition=expression '{' terminatedStatement* '}'
|
||||
| (label=Identifier ':')? LoopKeyword (initExpression=expression|initDeclaration=variableDeclarationStatement)? forIndicator=';' condition=expression? ';' increment=expression? '{' terminatedStatement* '}'
|
||||
;
|
||||
|
||||
expressionStatement
|
||||
: expression ';'
|
||||
: expression
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
todo: use C operator precedence: https://en.cppreference.com/w/c/language/operator_precedence
|
||||
|
||||
binary operators:
|
||||
== != > >= < <=
|
||||
||
|
||||
&&
|
||||
+ -
|
||||
* / %
|
||||
&
|
||||
|
|
||||
^
|
||||
<<
|
||||
>>
|
||||
|
||||
unary operators:
|
||||
+
|
||||
-
|
||||
~
|
||||
!
|
||||
|
||||
|
||||
assignment:
|
||||
=
|
||||
+=
|
||||
-=
|
||||
/=
|
||||
*=
|
||||
%=
|
||||
&=
|
||||
|=
|
||||
^=
|
||||
<<=
|
||||
>>=
|
||||
|
||||
|
||||
*/
|
||||
expression
|
||||
: addExpression
|
||||
: assignmentExpression
|
||||
;
|
||||
|
||||
assignmentExpression
|
||||
: pattern op=AssignmentOperator logicalOrExpression
|
||||
| logicalOrExpression
|
||||
;
|
||||
|
||||
pattern
|
||||
: pointerDereferenceExpression (',' pointerDereferenceExpression)*
|
||||
;
|
||||
|
||||
logicalOrExpression
|
||||
: logicalXorExpression ('||' logicalXorExpression)*
|
||||
;
|
||||
|
||||
logicalXorExpression
|
||||
: logicalAndExpression ('^^' logicalAndExpression)*
|
||||
;
|
||||
|
||||
logicalAndExpression
|
||||
: bitwiseOrExpression ('&&' bitwiseOrExpression)*
|
||||
;
|
||||
|
||||
bitwiseOrExpression
|
||||
: bitwiseXorExpression ('|' bitwiseXorExpression)*
|
||||
;
|
||||
|
||||
bitwiseXorExpression
|
||||
: bitwiseAndExpression ('^' bitwiseAndExpression)*
|
||||
;
|
||||
|
||||
bitwiseAndExpression
|
||||
: equalityExpression ('&' equalityExpression)*
|
||||
;
|
||||
|
||||
equalityExpression
|
||||
: relationalExpression ((op+='=='|op+='!=') relationalExpression)*
|
||||
;
|
||||
|
||||
relationalExpression
|
||||
: shiftExpression ((op+='<'|op+='>'|op+='<='|op+='>=') shiftExpression)*
|
||||
;
|
||||
|
||||
shiftExpression
|
||||
: addExpression ((op+='<<'|op+='>' '>') addExpression)*
|
||||
;
|
||||
|
||||
addExpression
|
||||
: multExpression ((op='+'|op='-') multExpression)*
|
||||
: multExpression ((op+='+'|op+='-') multExpression)*
|
||||
;
|
||||
|
||||
multExpression
|
||||
: terminalExpression ((op='*'|op='/'|op='%') terminalExpression)*
|
||||
: unaryExpression ((op+='*'|op+='/'|op+='%') unaryExpression)*
|
||||
;
|
||||
|
||||
unaryExpression
|
||||
: (op+='!'|op+='~'|op+='-'|op+='&')* pointerDereferenceExpression
|
||||
;
|
||||
|
||||
pointerDereferenceExpression
|
||||
: op+='*'* accessExpression
|
||||
;
|
||||
|
||||
accessExpression
|
||||
: terminalExpression accessExpression1?
|
||||
;
|
||||
|
||||
accessExpression1
|
||||
: '[' subscript=expression end=']' accessExpression1?
|
||||
| '.' (name=Identifier|name=NumericLiteral) accessExpression1?
|
||||
;
|
||||
|
||||
|
||||
terminalExpression
|
||||
: literal
|
||||
: literalExpression
|
||||
| nameExpression
|
||||
| structConstructor
|
||||
| arrayConstructor
|
||||
| enumConstructor
|
||||
| tupleConstructor
|
||||
| functionCall
|
||||
| ifExpression
|
||||
| switchExpression
|
||||
| blockExpression
|
||||
| parenthesisExpression
|
||||
;
|
||||
|
||||
literalExpression
|
||||
: literal
|
||||
;
|
||||
|
||||
nameExpression
|
||||
: identifierName
|
||||
;
|
||||
|
||||
structConstructor
|
||||
: typeName? '{' structConstructorMember (',' structConstructorMember)* ','? '}'
|
||||
;
|
||||
|
||||
structConstructorMember
|
||||
: name=Identifier ':' expression
|
||||
;
|
||||
|
||||
arrayConstructor
|
||||
: (arrayType | typeName? '[' ']') '{' (expression (',' expression)* ','?)? '}'
|
||||
;
|
||||
|
||||
enumConstructor
|
||||
: typeName? '\'' name=Identifier
|
||||
;
|
||||
|
||||
tupleConstructor
|
||||
: '(' ')'
|
||||
| '(' expression ',' ')'
|
||||
| '(' expression (',' expression)+ ','? ')'
|
||||
;
|
||||
|
||||
|
||||
functionCall
|
||||
: identifierName '(' (expression (',' expression)*)? ')'
|
||||
;
|
||||
|
||||
ifExpression
|
||||
: IfKeyword cond=expression then=blockExpression elseIfExpression* (ElseKeyword else=blockExpression)?
|
||||
;
|
||||
|
||||
elseIfExpression
|
||||
: ElseKeyword IfKeyword cond=expression then=blockExpression
|
||||
;
|
||||
|
||||
|
||||
switchExpression
|
||||
: SwitchKeyword expression '{' (switchDefault ','?)? '}'
|
||||
| SwitchKeyword expression '{' switchCase (',' switchCase)* (',' switchDefault ','?)? '}'
|
||||
;
|
||||
|
||||
switchCase
|
||||
: CaseKeyword literal ':' (expression|FallthroughKeyword)
|
||||
;
|
||||
|
||||
switchDefault
|
||||
: DefaultKeyword ':' expression
|
||||
;
|
||||
|
||||
blockExpression
|
||||
: '{' terminatedStatement* expression? '}'
|
||||
;
|
||||
|
||||
parenthesisExpression
|
||||
: '(' expression ')'
|
||||
;
|
||||
|
||||
|
||||
///////////////////////////
|
||||
|
||||
|
||||
MeowKeyword: 'm' 'e'+ 'o'* 'w' -> channel(HIDDEN); // ignores all me+o*ws in the code
|
||||
NyaKeyword: '-ny' 'a'+ -> channel(HIDDEN); // ignores all -nya+s in the code
|
||||
|
||||
ImportKeyword: 'import';
|
||||
AsKeyword: 'as';
|
||||
PubKeyword: 'pub';
|
||||
|
@ -253,6 +379,16 @@ BreakKeyword: 'break';
|
|||
ContinueKeyword: 'continue';
|
||||
ReturnKeyword: 'return';
|
||||
LoopKeyword: 'loop';
|
||||
IfKeyword: 'if';
|
||||
ElseKeyword: 'else';
|
||||
SwitchKeyword: 'switch';
|
||||
CaseKeyword: 'case';
|
||||
FallthroughKeyword: 'fallthrough';
|
||||
DefaultKeyword: 'default';
|
||||
|
||||
|
||||
AssignmentOperator: '='|'+='|'-='|'*='|'/='|'%='|'&='|'|='|'^='|'<<='|'>>=';
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
13
parser/MeowVisitorException.cs
Normal file
13
parser/MeowVisitorException.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using Antlr4.Runtime;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class MeowVisitorException : Exception
|
||||
{
|
||||
public IToken Token { get; }
|
||||
|
||||
public MeowVisitorException(IToken token, string message) : base(message)
|
||||
{
|
||||
Token = token;
|
||||
}
|
||||
}
|
3
parser/Model.cs
Normal file
3
parser/Model.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record Model(Span Span, List<ImportModel> Imports, List<TopLevelConstructModel> Declarations) : ModelBase(Span);
|
|
@ -1,3 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ModelBase([property:Ignore] Span span);
|
||||
public record ModelBase([property:Ignore] Span Span);
|
3
parser/NameExpressionModel.cs
Normal file
3
parser/NameExpressionModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record NameExpressionModel(Span Span, IdentifierNameModel Name): ExpressionModel(Span);
|
3
parser/NumericLiteralModel.cs
Normal file
3
parser/NumericLiteralModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record NumericLiteralModel(Span Span, string StringValue) : LiteralModel(Span);
|
3
parser/ParenthesisExpressionModel.cs
Normal file
3
parser/ParenthesisExpressionModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ParenthesisExpressionModel(Span Span, ExpressionModel Expression) : ExpressionModel(Span);
|
|
@ -8,8 +8,9 @@ public class Parser
|
|||
public static Model? Parse(string path)
|
||||
{
|
||||
var lexer = new MeowLexer(new AntlrFileStream(path));
|
||||
var parser = new MeowParser(new CommonTokenStream(lexer));
|
||||
var visitor = new Visitor();
|
||||
var tokenStream = new CommonTokenStream(lexer);
|
||||
var parser = new MeowParser(tokenStream);
|
||||
var visitor = new VisitorNya();
|
||||
var file = parser.file();
|
||||
if (parser.NumberOfSyntaxErrors > 0)
|
||||
{
|
||||
|
|
3
parser/PatternModel.cs
Normal file
3
parser/PatternModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record PatternModel(Span Span, List<ExpressionModel> Expressions) : ModelBase(Span);
|
3
parser/PointerDereferenceExpressionModel.cs
Normal file
3
parser/PointerDereferenceExpressionModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record PointerDereferenceExpressionModel(Span Span, ExpressionModel Expression) : ExpressionModel(Span);
|
3
parser/PointerReferenceExpressionModel.cs
Normal file
3
parser/PointerReferenceExpressionModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record PointerReferenceExpressionModel(Span Span, ExpressionModel Expression) : ExpressionModel(Span);
|
3
parser/PointerTypeReferenceModel.cs
Normal file
3
parser/PointerTypeReferenceModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record PointerTypeReferenceModel(Span Span, TypeReferenceModel Type) : TypeReferenceModel(Span);
|
3
parser/ReturnStatementModel.cs
Normal file
3
parser/ReturnStatementModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ReturnStatementModel(Span Span, ExpressionModel? Expression) : StatementModel(Span);
|
3
parser/SliceTypeModel.cs
Normal file
3
parser/SliceTypeModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record SliceTypeModel(Span Span, TypeReferenceModel Type) : TypeReferenceModel(Span);
|
3
parser/StatementModel.cs
Normal file
3
parser/StatementModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public abstract record StatementModel(Span Span) : ModelBase(Span);
|
83
parser/StatementVisitorNya.cs
Normal file
83
parser/StatementVisitorNya.cs
Normal file
|
@ -0,0 +1,83 @@
|
|||
using Antlr4.Runtime;
|
||||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class StatementVisitorNya : MeowBaseVisitorNya<StatementModel>
|
||||
{
|
||||
public override StatementModel VisitTerminatedStatement(MeowParser.TerminatedStatementContext context)
|
||||
{
|
||||
return Visit(context.statement() ?? context.blockStatement() as ParserRuleContext);
|
||||
}
|
||||
|
||||
public override StatementModel VisitBlockStatement(MeowParser.BlockStatementContext context)
|
||||
{
|
||||
if (context.loopStatement() != null)
|
||||
{
|
||||
return Visit(context.loopStatement());
|
||||
}
|
||||
|
||||
var expression = new ExpressionVisitorNya().Visit(context);
|
||||
return new ExpressionStatementModel(context.GetSpan(), expression);
|
||||
}
|
||||
|
||||
public override StatementModel VisitLoopStatement(MeowParser.LoopStatementContext context)
|
||||
{
|
||||
var body = context.terminatedStatement().Select(Visit).ToList();
|
||||
if (context.condition == null)
|
||||
{
|
||||
return new InfiniteLoopStatementModel(context.GetSpan(), body);
|
||||
}
|
||||
|
||||
var condition = new ExpressionVisitorNya().Visit(context.condition);
|
||||
if (context.forIndicator == null)
|
||||
{
|
||||
return new WhileLoopStatementModel(context.GetSpan(), body, condition);
|
||||
}
|
||||
|
||||
var increment = new ExpressionVisitorNya().TryVisit(context.increment);
|
||||
var initStatement = TryVisit(context.initDeclaration) as VariableDeclarationStatementModel;
|
||||
var initExpression = new ExpressionVisitorNya().TryVisit(context.initExpression);
|
||||
return new ForLoopStatementModel(context.GetSpan(), body, initStatement, initExpression, condition, increment);
|
||||
}
|
||||
|
||||
public override StatementModel VisitBreakStatement(MeowParser.BreakStatementContext context)
|
||||
{
|
||||
var label = context.label?.Text;
|
||||
return new BreakStatementModel(context.GetSpan(), label);
|
||||
}
|
||||
|
||||
public override StatementModel VisitContinueStatement(MeowParser.ContinueStatementContext context)
|
||||
{
|
||||
var label = context.label?.Text;
|
||||
return new ContinueStatementModel(context.GetSpan(), label);
|
||||
}
|
||||
|
||||
public override StatementModel VisitReturnStatement(MeowParser.ReturnStatementContext context)
|
||||
{
|
||||
var expression = new ExpressionVisitorNya().TryVisit(context.expression());
|
||||
return new ReturnStatementModel(context.GetSpan(), expression);
|
||||
}
|
||||
|
||||
public override StatementModel VisitExpressionStatement(MeowParser.ExpressionStatementContext context)
|
||||
{
|
||||
var expression = new ExpressionVisitorNya().Visit(context.expression());
|
||||
return new ExpressionStatementModel(context.GetSpan(), expression);
|
||||
}
|
||||
|
||||
public override StatementModel VisitVariableDeclarationStatement(
|
||||
MeowParser.VariableDeclarationStatementContext context)
|
||||
{
|
||||
var names = context._name.Select(x => x.Text).ToList();
|
||||
var initializer = new ExpressionVisitorNya().Visit(context.expression());
|
||||
return new VariableDeclarationStatementModel(context.GetSpan(), names, initializer);
|
||||
}
|
||||
|
||||
public override StatementModel VisitConstantDeclarationStatement(
|
||||
MeowParser.ConstantDeclarationStatementContext context)
|
||||
{
|
||||
var names = context._name.Select(x => x.Text).ToList();
|
||||
var initializer = new ExpressionVisitorNya().Visit(context.expression());
|
||||
return new ConstantDeclarationStatementModel(context.GetSpan(), names, initializer);
|
||||
}
|
||||
}
|
3
parser/StringLiteralModel.cs
Normal file
3
parser/StringLiteralModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record StringLiteralModel(Span Span, string Value) : LiteralModel(Span);
|
3
parser/StructAccessExpressionModel.cs
Normal file
3
parser/StructAccessExpressionModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record StructAccessExpressionModel(Span Span, ExpressionModel Expression, string Name) : ExpressionModel(Span);
|
4
parser/StructConstructorExpressionModel.cs
Normal file
4
parser/StructConstructorExpressionModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record StructConstructorExpressionModel(Span Span, TypeNameModel? Type,
|
||||
List<StructConstructorMemberModel> Members) : ExpressionModel(Span);
|
3
parser/StructConstructorMemberModel.cs
Normal file
3
parser/StructConstructorMemberModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record StructConstructorMemberModel(Span Span, string Name, ExpressionModel Value) : ModelBase(Span);
|
3
parser/StructMemberModel.cs
Normal file
3
parser/StructMemberModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record StructMemberModel(Span Span, TypeReferenceModel Type, string Name) : ModelBase(Span);
|
13
parser/StructMemberVisitorNya.cs
Normal file
13
parser/StructMemberVisitorNya.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class StructMemberVisitorNya : MeowBaseVisitorNya<StructMemberModel>
|
||||
{
|
||||
public override StructMemberModel VisitStructMember(MeowParser.StructMemberContext context)
|
||||
{
|
||||
var type = new TypeReferenceVisitorNya().Visit(context.typeReference());
|
||||
var name = context.name.Text;
|
||||
return new StructMemberModel(context.GetSpan(), type, name);
|
||||
}
|
||||
}
|
4
parser/StructTopLevelConstructModel.cs
Normal file
4
parser/StructTopLevelConstructModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record StructTopLevelConstructModel(Span Span, List<AttributeModel> Attributes, bool Pub, string Name, List<string> TypeParameters,
|
||||
List<ConstraintModel> Constraints, StructTypeModel Struct) : TopLevelConstructModel(Span);
|
3
parser/StructTypeModel.cs
Normal file
3
parser/StructTypeModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record StructTypeModel(Span Span, List<StructMemberModel> Members) : TypeReferenceModel(Span);
|
4
parser/SwitchExpressionModel.cs
Normal file
4
parser/SwitchExpressionModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record SwitchExpressionModel(Span Span, ExpressionModel Expression,
|
||||
List<(LiteralModel Value, ExpressionModel? Body)> Cases, ExpressionModel? Default) : ExpressionModel(Span);
|
3
parser/TopLevelConstructModel.cs
Normal file
3
parser/TopLevelConstructModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public abstract record TopLevelConstructModel(Span Span) : ModelBase(Span);
|
3
parser/TopLevelStatementModel.cs
Normal file
3
parser/TopLevelStatementModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record TopLevelStatementModel(Span Span, StatementModel Statement): TopLevelConstructModel(Span);
|
3
parser/TupleConstructorExpressionModel.cs
Normal file
3
parser/TupleConstructorExpressionModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record TupleConstructorExpressionModel(Span Span, List<ExpressionModel> Values) : ExpressionModel(Span);
|
4
parser/TupleTopLevelConstructModel.cs
Normal file
4
parser/TupleTopLevelConstructModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record TupleTopLevelConstructModel(Span Span, List<AttributeModel> Attributes, bool Pub, string Name, List<string> TypeParameters,
|
||||
List<ConstraintModel> Constraints, TupleTypeModel Tuple) : TopLevelConstructModel(Span);
|
3
parser/TupleTypeModel.cs
Normal file
3
parser/TupleTypeModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record TupleTypeModel(Span Span, List<TypeReferenceModel> Types) : TypeReferenceModel(Span);
|
5
parser/TypeAliasModel.cs
Normal file
5
parser/TypeAliasModel.cs
Normal file
|
@ -0,0 +1,5 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record TypeAliasModel
|
||||
(Span Span, List<AttributeModel> Attributes, bool Pub, string Name, List<string> TypeParameters, TypeReferenceModel Type) : TopLevelConstructModel(Span);
|
||||
|
4
parser/TypeNameModel.cs
Normal file
4
parser/TypeNameModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record TypeNameModel(Span Span, IdentifierNameModel Name, List<TypeReferenceModel> TypeParameters,
|
||||
List<string> Nested) : TypeReferenceModel(Span);
|
3
parser/TypeParameterModel.cs
Normal file
3
parser/TypeParameterModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record TypeParameterModel(Span Span, string Name) : ModelBase(Span);
|
3
parser/TypeReferenceModel.cs
Normal file
3
parser/TypeReferenceModel.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public abstract record TypeReferenceModel(Span Span) : ModelBase(Span);
|
54
parser/TypeReferenceVisitorNya.cs
Normal file
54
parser/TypeReferenceVisitorNya.cs
Normal file
|
@ -0,0 +1,54 @@
|
|||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class TypeReferenceVisitorNya : MeowBaseVisitorNya<TypeReferenceModel>
|
||||
{
|
||||
public override TypeReferenceModel VisitTypeReference(MeowParser.TypeReferenceContext context)
|
||||
{
|
||||
var type = Visit(context.nonPointerTypeReference());
|
||||
if (context.pointer != null)
|
||||
{
|
||||
return new PointerTypeReferenceModel(context.GetSpan(), type);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
public override TypeReferenceModel VisitTypeName(MeowParser.TypeNameContext context)
|
||||
{
|
||||
var name = new IdentifierNameVisitorNya().Visit(context.identifierName());
|
||||
var typeParameters = context._genericType.Select(Visit).ToList();
|
||||
var nestedName = context._name.Select(x => x.Text).ToList();
|
||||
return new TypeNameModel(context.GetSpan(), name, typeParameters, nestedName);
|
||||
}
|
||||
|
||||
public override TypeReferenceModel VisitArrayType(MeowParser.ArrayTypeContext context)
|
||||
{
|
||||
var type = Visit(context.typeReference());
|
||||
if (context.length == null)
|
||||
{
|
||||
return new SliceTypeModel(context.GetSpan(), type);
|
||||
}
|
||||
|
||||
return new ArrayTypeModel(context.GetSpan(), type, context.length.Text);
|
||||
}
|
||||
|
||||
public override TypeReferenceModel VisitTupleType(MeowParser.TupleTypeContext context)
|
||||
{
|
||||
var types = context.typeReference().Select(Visit).ToList();
|
||||
return new TupleTypeModel(context.GetSpan(), types);
|
||||
}
|
||||
|
||||
public override TypeReferenceModel VisitStructType(MeowParser.StructTypeContext context)
|
||||
{
|
||||
var members = context.structMember().Select(x => new StructMemberVisitorNya().Visit(x)).ToList();
|
||||
return new StructTypeModel(context.GetSpan(), members);
|
||||
}
|
||||
|
||||
public override TypeReferenceModel VisitEnumType(MeowParser.EnumTypeContext context)
|
||||
{
|
||||
var members = context.enumMember().Select(x => new EnumMemberVisitorNya().Visit(x)).ToList();
|
||||
return new EnumTypeModel(context.GetSpan(), members);
|
||||
}
|
||||
}
|
4
parser/UnaryOperationExpressionModel.cs
Normal file
4
parser/UnaryOperationExpressionModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record UnaryOperationExpressionModel
|
||||
(Span Span, UnaryOperator Operator, ExpressionModel Expression) : ExpressionModel(Span);
|
8
parser/UnaryOperator.cs
Normal file
8
parser/UnaryOperator.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public enum UnaryOperator
|
||||
{
|
||||
LogicalNot,
|
||||
BitwiseNot,
|
||||
Negative,
|
||||
}
|
18
parser/UnaryOperatorExtensions.cs
Normal file
18
parser/UnaryOperatorExtensions.cs
Normal file
|
@ -0,0 +1,18 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public static class UnaryOperatorExtensions
|
||||
{
|
||||
public static UnaryOperator ToUnaryOperator(this string str) => str switch
|
||||
{
|
||||
"!" => UnaryOperator.LogicalNot,
|
||||
"~" => UnaryOperator.BitwiseNot,
|
||||
"-" => UnaryOperator.Negative,
|
||||
};
|
||||
|
||||
public static string ToString(this UnaryOperator op) => op switch
|
||||
{
|
||||
UnaryOperator.LogicalNot => "!",
|
||||
UnaryOperator.BitwiseNot => "~",
|
||||
UnaryOperator.Negative => "-",
|
||||
};
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Antlr4.Runtime;
|
||||
using Newtonsoft.Json;
|
||||
|
@ -41,6 +42,12 @@ public static class ObjectExtensions
|
|||
|
||||
string json;
|
||||
|
||||
if (o is ITuple t)
|
||||
{
|
||||
var values = Enumerable.Range(0, t.Length).Select(i => t[i]).ToList();
|
||||
return values.AutoToString();
|
||||
}
|
||||
|
||||
if (type.IsAssignableTo(typeof(IEnumerable)))
|
||||
{
|
||||
var enumerable = (o as IEnumerable)!.Cast<object>();
|
||||
|
|
4
parser/VariableDeclarationStatementModel.cs
Normal file
4
parser/VariableDeclarationStatementModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record VariableDeclarationStatementModel
|
||||
(Span Span, List<string> Names, ExpressionModel Initializer) : StatementModel(Span);
|
|
@ -1,412 +0,0 @@
|
|||
using System.Reflection.Metadata;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Antlr4.Runtime;
|
||||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class InvalidEscapeSequenceException : Exception
|
||||
{
|
||||
public InvalidEscapeSequenceException(string escapeSequence) : base($"invalid escape sequence `{escapeSequence}`")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class MeowVisitorException : Exception
|
||||
{
|
||||
public IToken Token { get; }
|
||||
|
||||
public MeowVisitorException(IToken token, string message) : base(message)
|
||||
{
|
||||
Token = token;
|
||||
}
|
||||
}
|
||||
|
||||
public class InvalidImportPathException : MeowVisitorException
|
||||
{
|
||||
public InvalidImportPathException(IToken context, string message) : base(context, message)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class Visitor : MeowBaseVisitor<Model>
|
||||
{
|
||||
public override Model VisitFile(MeowParser.FileContext context)
|
||||
{
|
||||
var imports = context.importStatement().Select(x => new ImportVisitor().Visit(x)).ToList();
|
||||
var declarations = context.declaration().Select(x => new DeclarationVisitor().Visit(x)).ToList();
|
||||
|
||||
return new Model(context.GetSpan(), imports, declarations);
|
||||
}
|
||||
}
|
||||
|
||||
public class ImportVisitor : MeowBaseVisitor<ImportModel>
|
||||
{
|
||||
private static readonly string PathSegmentPattern = "[a-z][a-z0-9_]*";
|
||||
|
||||
private static readonly Regex ProjectRegex = new Regex("^[a-z][a-z0-9_]*$");
|
||||
|
||||
private static readonly Regex PathRegexNoProject =
|
||||
new Regex($"^({PathSegmentPattern}|\\.|\\.\\.)(/{PathSegmentPattern})*$");
|
||||
|
||||
private static readonly Regex PathRegex = new Regex($"^{PathSegmentPattern}(/{PathSegmentPattern})*$");
|
||||
|
||||
public override ImportModel VisitImportStatement(MeowParser.ImportStatementContext context)
|
||||
{
|
||||
var path = context.importpath.Text[1..^1].Unescape();
|
||||
|
||||
string? project = null;
|
||||
|
||||
if (path.Contains(':'))
|
||||
{
|
||||
var parts = path.Split(':');
|
||||
project = parts[0];
|
||||
if (!ProjectRegex.IsMatch(project))
|
||||
{
|
||||
throw new InvalidImportPathException(context.importpath, "malformed project name");
|
||||
}
|
||||
|
||||
path = parts[1];
|
||||
if (!PathRegex.IsMatch(path))
|
||||
{
|
||||
throw new InvalidImportPathException(context.importpath, "malformed path");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!PathRegexNoProject.IsMatch(path))
|
||||
{
|
||||
throw new InvalidImportPathException(context.importpath, "malformed path");
|
||||
}
|
||||
}
|
||||
|
||||
var alias = context.importname?.Text;
|
||||
|
||||
return new ImportModel(context.GetSpan(), project, path, alias);
|
||||
}
|
||||
}
|
||||
|
||||
public class DeclarationVisitor : MeowBaseVisitor<DeclarationModel>
|
||||
{
|
||||
public override DeclarationModel VisitFunction(MeowParser.FunctionContext context)
|
||||
{
|
||||
var attributes = context.attribute().Select(x => new AttributeVisitor().Visit(x)).ToList();
|
||||
var pub = context.pub != null;
|
||||
var name = context.name.Text;
|
||||
|
||||
var typeParameters =
|
||||
context.genericParameters()?._name.Select(x => new TypeParameterModel(x.GetSpan(), x.Text)).ToList() ??
|
||||
new List<TypeParameterModel>();
|
||||
var functionParameters = context.functionParameters().functionParameter()
|
||||
.Select(x => new FunctionParameterVisitor().Visit(x)).ToList();
|
||||
var functionReturns = context.functionReturn()?.typeReference().Select(x => new TypeReferenceVisitor().Visit(x))
|
||||
.ToList() ?? new List<TypeReferenceModel>();
|
||||
var constraints = context.constraint()?.Select(x => new FunctionConstraintVisitor().Visit(x)).ToList() ??
|
||||
new List<ConstraintModel>();
|
||||
|
||||
return new FunctionModel(context.GetSpan(), attributes, pub, name, typeParameters, functionParameters,
|
||||
functionReturns, constraints,
|
||||
new FunctionBodyModel(context.functionBody().GetSpan())); // TODO: visit function body
|
||||
}
|
||||
|
||||
public override ConstraintDeclarationModel VisitConstraintDeclaration(
|
||||
MeowParser.ConstraintDeclarationContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
var typeNames = context._types.Select(x => x.Text).ToList();
|
||||
var rules = context.constraintRule().Select(x => new ConstraintRuleVisitor().Visit(x)).ToList();
|
||||
return new ConstraintDeclarationModel(context.GetSpan(), name, typeNames, rules);
|
||||
}
|
||||
|
||||
public override DeclarationModel VisitStructDeclaration(MeowParser.StructDeclarationContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
var typeParameters = context.genericParameters()?._name.Select(x => x.Text).ToList() ?? new List<string>();
|
||||
var constraints = context.constraint()?.Select(x => new FunctionConstraintVisitor().Visit(x)).ToList() ??
|
||||
new List<ConstraintModel>();
|
||||
var structModel = new TypeReferenceVisitor().Visit(context.structType()) as StructTypeModel;
|
||||
return new StructDeclarationModel(context.GetSpan(), name, typeParameters, constraints, structModel!);
|
||||
}
|
||||
|
||||
public override DeclarationModel VisitEnumDeclaration(MeowParser.EnumDeclarationContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
var typeParameters = context.genericParameters()?._name.Select(x => x.Text).ToList() ?? new List<string>();
|
||||
var constraints = context.constraint()?.Select(x => new FunctionConstraintVisitor().Visit(x)).ToList() ??
|
||||
new List<ConstraintModel>();
|
||||
|
||||
var enumModel = new TypeReferenceVisitor().Visit(context.enumType()) as EnumTypeModel;
|
||||
return new EnumDeclarationModel(context.GetSpan(), name, typeParameters, constraints, enumModel!);
|
||||
}
|
||||
|
||||
public override DeclarationModel VisitTupleDeclaration(MeowParser.TupleDeclarationContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
var typeParameters = context.genericParameters()?._name.Select(x => x.Text).ToList() ?? new List<string>();
|
||||
var constraints = context.constraint()?.Select(x => new FunctionConstraintVisitor().Visit(x)).ToList() ??
|
||||
new List<ConstraintModel>();
|
||||
var tupleModel = new TypeReferenceVisitor().Visit(context.tupleType()) as TupleTypeModel;
|
||||
return new TupleDeclarationModel(context.GetSpan(), name, typeParameters, constraints, tupleModel!);
|
||||
}
|
||||
|
||||
public override DeclarationModel VisitTypeAlias(MeowParser.TypeAliasContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
var typeParameters = context.genericParameters()?._name.Select(x => x.Text).ToList() ?? new List<string>();
|
||||
var type = new TypeReferenceVisitor().Visit(context.typeReference());
|
||||
return new TypeAliasModel(context.GetSpan(), name, typeParameters, type);
|
||||
}
|
||||
}
|
||||
|
||||
public class AttributeVisitor : MeowBaseVisitor<AttributeModel>
|
||||
{
|
||||
public override AttributeModel VisitAttribute(MeowParser.AttributeContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
var values = context.attributeValue().Select(x => new AttributeValueVisitor().Visit(x)).ToList();
|
||||
return new AttributeModel(context.GetSpan(), name, values);
|
||||
}
|
||||
}
|
||||
|
||||
public class AttributeValueVisitor : MeowBaseVisitor<AttributeValueModel>
|
||||
{
|
||||
public override AttributeValueModel VisitAttributeValue(MeowParser.AttributeValueContext context)
|
||||
{
|
||||
if (context.id != null)
|
||||
{
|
||||
return new IdentifierAttributeValueModel(context.GetSpan(), context.id.Text);
|
||||
}
|
||||
|
||||
var literal = new LiteralVisitor().Visit(context.literal());
|
||||
return new LiteralAttributeValueModel(context.GetSpan(), literal);
|
||||
}
|
||||
}
|
||||
|
||||
public class FunctionParameterVisitor : MeowBaseVisitor<FunctionParameterModel>
|
||||
{
|
||||
public override FunctionParameterModel VisitFunctionParameter(MeowParser.FunctionParameterContext context)
|
||||
{
|
||||
var type = new TypeReferenceVisitor().Visit(context.typeReference());
|
||||
var name = context.name.Text;
|
||||
return new FunctionParameterModel(context.GetSpan(), type, name);
|
||||
}
|
||||
}
|
||||
|
||||
public class TypeReferenceVisitor : MeowBaseVisitor<TypeReferenceModel>
|
||||
{
|
||||
public override TypeReferenceModel VisitTypeReference(MeowParser.TypeReferenceContext context)
|
||||
{
|
||||
var type = Visit(context.nonPointerTypeReference());
|
||||
if (context.pointer != null)
|
||||
{
|
||||
return new PointerTypeReferenceModel(context.GetSpan(), type);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
public override TypeReferenceModel VisitTypeName(MeowParser.TypeNameContext context)
|
||||
{
|
||||
var import = context.importName?.Text;
|
||||
var nestedName = context._name.Select(x => x.Text).ToList();
|
||||
|
||||
var typeParameters = context._genericType.Select(Visit).ToList();
|
||||
|
||||
return new TypeNameModel(context.GetSpan(), import, nestedName[0], typeParameters, nestedName.Skip(1).ToList());
|
||||
}
|
||||
|
||||
public override TypeReferenceModel VisitArrayType(MeowParser.ArrayTypeContext context)
|
||||
{
|
||||
var type = Visit(context.typeReference());
|
||||
if (context.length == null)
|
||||
{
|
||||
return new SliceTypeModel(context.GetSpan(), type);
|
||||
}
|
||||
|
||||
return new ArrayTypeModel(context.GetSpan(), type, context.length.Text);
|
||||
}
|
||||
|
||||
public override TypeReferenceModel VisitTupleType(MeowParser.TupleTypeContext context)
|
||||
{
|
||||
var types = context.typeReference().Select(Visit).ToList();
|
||||
return new TupleTypeModel(context.GetSpan(), types);
|
||||
}
|
||||
|
||||
public override TypeReferenceModel VisitStructType(MeowParser.StructTypeContext context)
|
||||
{
|
||||
var members = context.structMember().Select(x => new StructMemberVisitor().Visit(x)).ToList();
|
||||
return new StructTypeModel(context.GetSpan(), members);
|
||||
}
|
||||
|
||||
public override TypeReferenceModel VisitEnumType(MeowParser.EnumTypeContext context)
|
||||
{
|
||||
var members = context.enumMember().Select(x => new EnumMemberVisitor().Visit(x)).ToList();
|
||||
return new EnumTypeModel(context.GetSpan(), members);
|
||||
}
|
||||
}
|
||||
|
||||
public class StructMemberVisitor : MeowBaseVisitor<StructMemberModel>
|
||||
{
|
||||
public override StructMemberModel VisitStructMember(MeowParser.StructMemberContext context)
|
||||
{
|
||||
var type = new TypeReferenceVisitor().Visit(context.typeReference());
|
||||
var name = context.name.Text;
|
||||
return new StructMemberModel(context.GetSpan(), type, name);
|
||||
}
|
||||
}
|
||||
|
||||
public class EnumMemberVisitor : MeowBaseVisitor<EnumMemberModel>
|
||||
{
|
||||
public override EnumMemberModel VisitEnumMember(MeowParser.EnumMemberContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
|
||||
TypeReferenceModel? type = null;
|
||||
var typeRef = context.typeReference();
|
||||
if (typeRef != null)
|
||||
{
|
||||
type = new TypeReferenceVisitor().Visit(typeRef);
|
||||
}
|
||||
|
||||
return new EnumMemberModel(context.GetSpan(), name, type);
|
||||
}
|
||||
}
|
||||
|
||||
public class FunctionConstraintVisitor : MeowBaseVisitor<ConstraintModel>
|
||||
{
|
||||
public override ConstraintModel VisitConstraint(MeowParser.ConstraintContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
var typeNames = context._typenames.Select(x => x.Text).ToList();
|
||||
return new ConstraintModel(context.GetSpan(), name, typeNames);
|
||||
}
|
||||
}
|
||||
|
||||
public class LiteralVisitor : MeowBaseVisitor<LiteralModel>
|
||||
{
|
||||
public override LiteralModel VisitStringLiteral(MeowParser.StringLiteralContext context)
|
||||
{
|
||||
var value = context.val.Text[1..^1].Unescape();
|
||||
return new StringLiteralModel(context.GetSpan(), value);
|
||||
}
|
||||
|
||||
public override LiteralModel VisitBoolLiteral(MeowParser.BoolLiteralContext context)
|
||||
{
|
||||
var text = context.val.Text;
|
||||
var value = text == "true";
|
||||
return new BoolLiteralModel(context.GetSpan(), value);
|
||||
}
|
||||
|
||||
public override LiteralModel VisitNumericLiteral(MeowParser.NumericLiteralContext context)
|
||||
{
|
||||
return new NumericLiteralModel(context.GetSpan(), context.val.Text);
|
||||
}
|
||||
|
||||
public override LiteralModel VisitCharacterLiteral(MeowParser.CharacterLiteralContext context)
|
||||
{
|
||||
var value = context.val.Text[1..^1].Unescape();
|
||||
return new CharacterLiteralModel(context.GetSpan(), value);
|
||||
}
|
||||
}
|
||||
|
||||
public class ConstraintRuleVisitor : MeowBaseVisitor<ConstraintRuleModel>
|
||||
{
|
||||
public override ConstraintRuleModel VisitEmbedConstraintRule(MeowParser.EmbedConstraintRuleContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
var types = context._types.Select(x => new TypeReferenceVisitor().Visit(x)).ToList();
|
||||
return new EmbedConstraintRuleModel(context.GetSpan(), name, types);
|
||||
}
|
||||
|
||||
public override ConstraintRuleModel VisitFunctionConstraintRule(MeowParser.FunctionConstraintRuleContext context)
|
||||
{
|
||||
var name = context.name.Text;
|
||||
var parameters = context.constraintFunctionParameters().typeReference()
|
||||
.Select(x => new TypeReferenceVisitor().Visit(x)).ToList();
|
||||
var returns =
|
||||
context.functionReturn()?.typeReference().Select(x => new TypeReferenceVisitor().Visit(x)).ToList() ??
|
||||
new List<TypeReferenceModel>();
|
||||
return new FunctionConstraintRuleModel(context.GetSpan(), name, parameters, returns);
|
||||
}
|
||||
}
|
||||
|
||||
public record Model(Span span, List<ImportModel> Imports, List<DeclarationModel> Declarations) : ModelBase(span);
|
||||
|
||||
public record ImportModel(Span span, string? Project, string Path, string? Alias) : ModelBase(span);
|
||||
|
||||
public abstract record DeclarationModel(Span span) : ModelBase(span);
|
||||
|
||||
public record FunctionModel(Span span, List<AttributeModel> Attributes, bool Pub, string Name,
|
||||
List<TypeParameterModel> TypeParameters, List<FunctionParameterModel> Parameters, List<TypeReferenceModel> Returns,
|
||||
List<ConstraintModel> Constraints, FunctionBodyModel Body) : DeclarationModel(span);
|
||||
|
||||
public record AttributeModel(Span span, string Name, List<AttributeValueModel> Values) : ModelBase(span);
|
||||
|
||||
public abstract record AttributeValueModel(Span span) : ModelBase(span);
|
||||
|
||||
public record IdentifierAttributeValueModel(Span span, string Name) : AttributeValueModel(span);
|
||||
|
||||
public record LiteralAttributeValueModel(Span span, LiteralModel Literal) : AttributeValueModel(span);
|
||||
|
||||
public record TypeParameterModel(Span span, string Name) : ModelBase(span);
|
||||
|
||||
public record FunctionParameterModel(Span span, TypeReferenceModel Type, string Name) : ModelBase(span);
|
||||
|
||||
public abstract record TypeReferenceModel(Span span) : ModelBase(span);
|
||||
|
||||
public record PointerTypeReferenceModel(Span span, TypeReferenceModel Type) : TypeReferenceModel(span);
|
||||
|
||||
public record TypeNameModel(Span span, string? ImportName, string Name, List<TypeReferenceModel> TypeParameters,
|
||||
List<string> Nested) : TypeReferenceModel(span);
|
||||
|
||||
public record ArrayTypeModel(Span span, TypeReferenceModel Type, string Length) : TypeReferenceModel(span);
|
||||
|
||||
public record SliceTypeModel(Span span, TypeReferenceModel Type) : TypeReferenceModel(span);
|
||||
|
||||
public record TupleTypeModel(Span span, List<TypeReferenceModel> Types) : TypeReferenceModel(span);
|
||||
|
||||
public record StructTypeModel(Span span, List<StructMemberModel> Members) : TypeReferenceModel(span);
|
||||
|
||||
public record StructMemberModel(Span span, TypeReferenceModel Type, string Name) : ModelBase(span);
|
||||
|
||||
public record EnumTypeModel(Span span, List<EnumMemberModel> Members) : TypeReferenceModel(span);
|
||||
|
||||
public record EnumMemberModel(Span span, string Name, TypeReferenceModel? Type) : ModelBase(span);
|
||||
|
||||
public record ConstraintModel(Span span, string Name, List<string> TypeNames) : ModelBase(span);
|
||||
|
||||
public record FunctionBodyModel(Span span) : ModelBase(span);
|
||||
|
||||
public abstract record LiteralModel(Span span) : ModelBase(span);
|
||||
|
||||
public record StringLiteralModel(Span span, string Value) : LiteralModel(span);
|
||||
|
||||
public record CharacterLiteralModel(Span span, string Value) : LiteralModel(span);
|
||||
|
||||
public record NumericLiteralModel(Span span, string StringValue) : LiteralModel(span);
|
||||
|
||||
public record BoolLiteralModel(Span span, bool Value) : LiteralModel(span);
|
||||
|
||||
public record ConstraintDeclarationModel
|
||||
(Span span, string Name, List<string> TypeNames, List<ConstraintRuleModel> Rules) : DeclarationModel(span);
|
||||
|
||||
public abstract record ConstraintRuleModel(Span span) : ModelBase(span);
|
||||
|
||||
public record EmbedConstraintRuleModel
|
||||
(Span span, string Name, List<TypeReferenceModel> Types) : ConstraintRuleModel(span);
|
||||
|
||||
public record FunctionConstraintRuleModel(Span span, string Name, List<TypeReferenceModel> Parameters,
|
||||
List<TypeReferenceModel> Returns) : ConstraintRuleModel(span);
|
||||
|
||||
public record StructDeclarationModel(Span span, string Name, List<string> TypeParameters,
|
||||
List<ConstraintModel> Constraints, StructTypeModel Struct) : DeclarationModel(span);
|
||||
|
||||
public record EnumDeclarationModel(Span span, string Name, List<string> TypeParameters,
|
||||
List<ConstraintModel> Constraints, EnumTypeModel Enum) : DeclarationModel(span);
|
||||
|
||||
public record TupleDeclarationModel(Span span, string Name, List<string> TypeParameters,
|
||||
List<ConstraintModel> Constraints, TupleTypeModel Tuple) : DeclarationModel(span);
|
||||
|
||||
public record TypeAliasModel
|
||||
(Span span, string Name, List<string> TypeParameters, TypeReferenceModel Type) : DeclarationModel(span);
|
17
parser/VisitorNya.cs
Normal file
17
parser/VisitorNya.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
using System.Linq.Expressions;
|
||||
using System.Reflection.Metadata;
|
||||
using System.Text;
|
||||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
public class VisitorNya : MeowBaseVisitorNya<Model>
|
||||
{
|
||||
public override Model VisitFile(MeowParser.FileContext context)
|
||||
{
|
||||
var imports = context.importStatement().Select(x => new ImportVisitorNya().Visit(x)).ToList();
|
||||
var declarations = context.topLevelDeclaration().Select(x => new DeclarationVisitorNya().Visit(x)).ToList();
|
||||
|
||||
return new Model(context.GetSpan(), imports, declarations);
|
||||
}
|
||||
}
|
4
parser/WhileLoopStatementModel.cs
Normal file
4
parser/WhileLoopStatementModel.cs
Normal file
|
@ -0,0 +1,4 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record WhileLoopStatementModel
|
||||
(Span Span, List<StatementModel> Body, ExpressionModel Condition) : LoopStatementModel(Span, Body);
|
Loading…
Reference in a new issue