parser mostly done I hope

This commit is contained in:
Gwendolyn 2022-02-12 18:30:04 +01:00
parent 78fe931f97
commit 3884422afb
100 changed files with 1448 additions and 529 deletions

View file

@ -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:
=
+=
-=
/=
*=
%=
&=
|=
^=
<<=
>>=
```

View file

@ -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(),
}
}
}

View file

@ -0,0 +1,4 @@
namespace meowlang.parser;
public record ArrayAccessExpressionModel
(Span Span, ExpressionModel Expression, ExpressionModel Indexer) : ExpressionModel(Span);

View 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
View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record ArrayTypeModel(Span Span, TypeReferenceModel Type, string Length) : TypeReferenceModel(Span);

View file

@ -0,0 +1,4 @@
namespace meowlang.parser;
public record AssignmentExpressionModel(Span Span, PatternModel Pattern, AssignmentOperator Operator,
ExpressionModel Initializer) : ExpressionModel(Span);

View file

@ -0,0 +1,16 @@
namespace meowlang.parser;
public enum AssignmentOperator
{
Assign,
PlusAssign,
MinusAssign,
MultAssign,
DivAssign,
ModAssign,
BitwiseOrAssign,
BitwiseAndAssign,
BitwiseXorAssign,
ShiftRightAssign,
ShiftLeftAssign
}

View 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
View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record AttributeModel(Span Span, string Name, List<AttributeValueModel> Values) : ModelBase(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public abstract record AttributeValueModel(Span Span) : ModelBase(Span);

View 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);
}
}

View 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);
}
}

View 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
View 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,
}

View 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 => "%",
};
}

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record BlockExpressionModel(Span Span, List<StatementModel> Statements, ExpressionModel? Value) : ExpressionModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record BoolLiteralModel(Span Span, bool Value) : LiteralModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record BreakStatementModel(Span Span, string? Label) : StatementModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record CharacterLiteralModel(Span Span, string Value) : LiteralModel(Span);

View file

@ -0,0 +1,4 @@
namespace meowlang.parser;
public record ConstantDeclarationStatementModel
(Span Span, List<string> Names, ExpressionModel Initializer) : StatementModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record ConstraintModel(Span Span, string Name, List<string> TypeNames) : ModelBase(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public abstract record ConstraintRuleModel(Span Span) : ModelBase(Span);

View 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);
}
}

View 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);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record ContinueStatementModel(Span Span, string? Label) : StatementModel(Span);

View 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);
}
}

View file

@ -0,0 +1,4 @@
namespace meowlang.parser;
public record EmbedConstraintRuleModel
(Span Span, string Name, List<TypeReferenceModel> Types) : ConstraintRuleModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record EnumConstructorExpressionModel(Span Span, TypeNameModel Type, string Name) : ExpressionModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record EnumMemberModel(Span Span, string Name, TypeReferenceModel? Type) : ModelBase(Span);

View 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);
}
}

View 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
View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record EnumTypeModel(Span Span, List<EnumMemberModel> Members) : TypeReferenceModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public abstract record ExpressionModel(Span Span) : ModelBase(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record ExpressionStatementModel(Span Span, ExpressionModel Expression) : StatementModel(Span);

View 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);
}
}

View 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);

View file

@ -0,0 +1,4 @@
namespace meowlang.parser;
public record FunctionCallExpressionModel
(Span Span, IdentifierNameModel Name, List<ExpressionModel> Arguments) : ExpressionModel(Span);

View file

@ -0,0 +1,4 @@
namespace meowlang.parser;
public record FunctionConstraintRuleModel(Span Span, string Name, List<TypeReferenceModel> Parameters,
List<TypeReferenceModel> Returns) : ConstraintRuleModel(Span);

View 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
View 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);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record FunctionParameterModel(Span Span, TypeReferenceModel Type, string Name) : ModelBase(Span);

View 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);
}
}

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record IdentifierAttributeValueModel(Span Span, string Name) : AttributeValueModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record IdentifierNameModel(Span Span, string? ImportName, string Name) : ModelBase(Span);

View 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);
}
}

View 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
View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record ImportModel(Span Span, string? Project, string Path, string? Alias) : ModelBase(Span);

View 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);
}
}

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record InfiniteLoopStatementModel(Span Span, List<StatementModel> Body) : LoopStatementModel(Span, Body);

View file

@ -0,0 +1,8 @@
namespace meowlang.parser;
public class InvalidEscapeSequenceException : Exception
{
public InvalidEscapeSequenceException(string escapeSequence) : base($"invalid escape sequence `{escapeSequence}`")
{
}
}

View file

@ -0,0 +1,10 @@
using Antlr4.Runtime;
namespace meowlang.parser;
public class InvalidImportPathException : MeowVisitorException
{
public InvalidImportPathException(IToken context, string message) : base(context, message)
{
}
}

View file

@ -0,0 +1,10 @@
using Antlr4.Runtime;
namespace meowlang.parser;
public class InvalidStructAccessorException : MeowVisitorException
{
public InvalidStructAccessorException(IToken token, string message) : base(token, message)
{
}
}

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record LiteralAttributeValueModel(Span Span, LiteralModel Literal) : AttributeValueModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record LiteralExpressionModel(Span Span, LiteralModel Literal) : ExpressionModel(Span);

3
parser/LiteralModel.cs Normal file
View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public abstract record LiteralModel(Span Span) : ModelBase(Span);

View 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);
}
}

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public abstract record LoopStatementModel(Span Span, List<StatementModel> Body) : StatementModel(Span);

View file

@ -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: '='|'+='|'-='|'*='|'/='|'%='|'&='|'|='|'^='|'<<='|'>>=';

View 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
View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record Model(Span Span, List<ImportModel> Imports, List<TopLevelConstructModel> Declarations) : ModelBase(Span);

View file

@ -1,3 +1,3 @@
namespace meowlang.parser;
public record ModelBase([property:Ignore] Span span);
public record ModelBase([property:Ignore] Span Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record NameExpressionModel(Span Span, IdentifierNameModel Name): ExpressionModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record NumericLiteralModel(Span Span, string StringValue) : LiteralModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record ParenthesisExpressionModel(Span Span, ExpressionModel Expression) : ExpressionModel(Span);

View file

@ -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
View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record PatternModel(Span Span, List<ExpressionModel> Expressions) : ModelBase(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record PointerDereferenceExpressionModel(Span Span, ExpressionModel Expression) : ExpressionModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record PointerReferenceExpressionModel(Span Span, ExpressionModel Expression) : ExpressionModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record PointerTypeReferenceModel(Span Span, TypeReferenceModel Type) : TypeReferenceModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record ReturnStatementModel(Span Span, ExpressionModel? Expression) : StatementModel(Span);

3
parser/SliceTypeModel.cs Normal file
View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record SliceTypeModel(Span Span, TypeReferenceModel Type) : TypeReferenceModel(Span);

3
parser/StatementModel.cs Normal file
View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public abstract record StatementModel(Span Span) : ModelBase(Span);

View 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);
}
}

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record StringLiteralModel(Span Span, string Value) : LiteralModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record StructAccessExpressionModel(Span Span, ExpressionModel Expression, string Name) : ExpressionModel(Span);

View file

@ -0,0 +1,4 @@
namespace meowlang.parser;
public record StructConstructorExpressionModel(Span Span, TypeNameModel? Type,
List<StructConstructorMemberModel> Members) : ExpressionModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record StructConstructorMemberModel(Span Span, string Name, ExpressionModel Value) : ModelBase(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record StructMemberModel(Span Span, TypeReferenceModel Type, string Name) : ModelBase(Span);

View 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);
}
}

View 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);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record StructTypeModel(Span Span, List<StructMemberModel> Members) : TypeReferenceModel(Span);

View 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);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public abstract record TopLevelConstructModel(Span Span) : ModelBase(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record TopLevelStatementModel(Span Span, StatementModel Statement): TopLevelConstructModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record TupleConstructorExpressionModel(Span Span, List<ExpressionModel> Values) : ExpressionModel(Span);

View 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
View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record TupleTypeModel(Span Span, List<TypeReferenceModel> Types) : TypeReferenceModel(Span);

5
parser/TypeAliasModel.cs Normal file
View 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
View file

@ -0,0 +1,4 @@
namespace meowlang.parser;
public record TypeNameModel(Span Span, IdentifierNameModel Name, List<TypeReferenceModel> TypeParameters,
List<string> Nested) : TypeReferenceModel(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public record TypeParameterModel(Span Span, string Name) : ModelBase(Span);

View file

@ -0,0 +1,3 @@
namespace meowlang.parser;
public abstract record TypeReferenceModel(Span Span) : ModelBase(Span);

View 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);
}
}

View 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
View file

@ -0,0 +1,8 @@
namespace meowlang.parser;
public enum UnaryOperator
{
LogicalNot,
BitwiseNot,
Negative,
}

View 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 => "-",
};
}

View file

@ -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>();

View file

@ -0,0 +1,4 @@
namespace meowlang.parser;
public record VariableDeclarationStatementModel
(Span Span, List<string> Names, ExpressionModel Initializer) : StatementModel(Span);

View file

@ -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
View 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);
}
}

View file

@ -0,0 +1,4 @@
namespace meowlang.parser;
public record WhileLoopStatementModel
(Span Span, List<StatementModel> Body, ExpressionModel Condition) : LoopStatementModel(Span, Body);