first commit wtf am I doing
This commit is contained in:
commit
78fe931f97
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
bin/
|
||||
obj/
|
||||
/packages/
|
||||
riderModule.iml
|
||||
/_ReSharper.Caches/
|
||||
.idea
|
||||
gen/
|
22
MeowLang.sln
Normal file
22
MeowLang.sln
Normal file
|
@ -0,0 +1,22 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "compiler", "compiler\compiler.csproj", "{1ABDD383-ABC6-4B3F-80FC-348879BF8AFE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "parser", "parser\parser.csproj", "{240E1F81-DB04-46CE-AB7B-60616B6D868C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1ABDD383-ABC6-4B3F-80FC-348879BF8AFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1ABDD383-ABC6-4B3F-80FC-348879BF8AFE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1ABDD383-ABC6-4B3F-80FC-348879BF8AFE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1ABDD383-ABC6-4B3F-80FC-348879BF8AFE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{240E1F81-DB04-46CE-AB7B-60616B6D868C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{240E1F81-DB04-46CE-AB7B-60616B6D868C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{240E1F81-DB04-46CE-AB7B-60616B6D868C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{240E1F81-DB04-46CE-AB7B-60616B6D868C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
316
README.md
Normal file
316
README.md
Normal file
|
@ -0,0 +1,316 @@
|
|||
# meow
|
||||
|
||||
most awesome language, mainly because it's not object-oriented and it's called meow.
|
||||
|
||||
Multiple dispatch!
|
||||
|
||||
Weird syntax!
|
||||
|
||||
Implicit interfaces, except we call them constraints! whyyyy did I do this?
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
<imports>
|
||||
|
||||
<declarations>
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
### imports
|
||||
|
||||
```
|
||||
import "std:strings" as str // standard library
|
||||
import "std:strings/ext" as strext // nested
|
||||
import "foo:bar" as fb // file bar from project foo
|
||||
import ":foo/bar" // relative to project root
|
||||
import "foo" // relative to current file
|
||||
import "./foo" as whatever // relative to current file
|
||||
import "../foobar" // relative to current file
|
||||
```
|
||||
|
||||
access public thingies from imports with `:`
|
||||
|
||||
```
|
||||
import foo;
|
||||
|
||||
foo:somefunction();
|
||||
foo:SomeType
|
||||
foo:SomeConstraint
|
||||
```
|
||||
|
||||
|
||||
### functions
|
||||
Functions are by default private to the current file, functions with `pub` are accessible from other files/projects.
|
||||
```
|
||||
fn x() {}
|
||||
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("renamed_foo2")] pub fn foo2(int a, Foo b, Bar c) -> int, int {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Functions can be overloaded on parameter and return types
|
||||
```
|
||||
fn a() -> s32 {
|
||||
return -1;
|
||||
}
|
||||
fn a() -> u32 {
|
||||
return 1;
|
||||
}
|
||||
|
||||
fn a(i32 x, i32 y) -> (i32, i32) {
|
||||
return y, x;
|
||||
}
|
||||
|
||||
fn a(u32 x) -> u32 {
|
||||
return x + 1;
|
||||
}
|
||||
```
|
||||
|
||||
### constraints
|
||||
constraints are kind of weird because they
|
||||
- can have multiple types, like, a constraint can constrain multiple types together
|
||||
- can be used both as a constraint on generic types and as a type themselves
|
||||
- but only can be used as a type when they constrain only one type, and then they're kinda like an interface?
|
||||
- fuck this is weird
|
||||
|
||||
```
|
||||
// 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
```
|
||||
|
||||
```
|
||||
// usage as type parameter constraints
|
||||
fn foo<T1, T2>(T1 x)
|
||||
where Foo T1 T2
|
||||
{
|
||||
T2 y = some_other_func(x);
|
||||
some_func(x, y);
|
||||
}
|
||||
|
||||
fn bar<T>(T a) -> i32
|
||||
where Bar T
|
||||
{
|
||||
T b = f1(a);
|
||||
return f2(b);
|
||||
}
|
||||
|
||||
// usage as interface types
|
||||
|
||||
Bar x = getSomeTypeThatIsBar();
|
||||
Bar y = f1(x);
|
||||
```
|
||||
|
||||
constraints can be embedded in other constraints like this:
|
||||
```
|
||||
constraint Arithmetic on A {
|
||||
operator+ (A, A) -> A;
|
||||
operator- (A, A) -> A;
|
||||
operator* (A, A) -> A;
|
||||
operator/ (A, A) -> A;
|
||||
}
|
||||
|
||||
constraint Foo on A {
|
||||
Arithmetic A;
|
||||
some_func(A) -> 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.
|
||||
They can contain underscores between digits which are ignored, e.g. `1_000` or `1_0_0_0`.
|
||||
Unprefixed numeric literals are decimal, prefixes exist for hexadecimal (`0x`), octal (`0o`) and binary (`0b`).
|
||||
|
||||
#### character
|
||||
The character literal is a single unicode character enclosed in single quotes, its value is the character's unicode code point.
|
||||
|
||||
#### bool
|
||||
`true` and `false`
|
||||
|
||||
#### string
|
||||
String literals are enclosed in double quotes (e.g. `"hello world"`).
|
||||
Their type is an `u8` array with length of the string in bytes.
|
||||
|
||||
|
||||
### types
|
||||
#### basic types
|
||||
- bool: `bool`
|
||||
- signed integer types: `s8`, `s16`, `s32`, `s64`, `s128`
|
||||
- unsigned integer types: `u8`, `u16`, `u32`, `u64`, `u128`
|
||||
- floating point types: `f32`, `f64` (possibly more?)
|
||||
- decimal type? `decimal`
|
||||
- complex types? `c64`, `c128` (does this refer to the total size or the size of each component?)
|
||||
|
||||
|
||||
#### compound types
|
||||
##### array & slice
|
||||
###### declaration
|
||||
```
|
||||
// array
|
||||
[u8; 10]
|
||||
// slice
|
||||
[u8]
|
||||
```
|
||||
###### use
|
||||
```
|
||||
let a: [u8] = "foo";
|
||||
let b: u8 = a[1];
|
||||
let d: [s32; 4] = {1,2,3,4};
|
||||
let e = [u8]{1,2,3,4};
|
||||
```
|
||||
##### struct
|
||||
###### declaration
|
||||
```
|
||||
struct Point {
|
||||
s32 x;
|
||||
s32 y;
|
||||
s32 z;
|
||||
}
|
||||
type Point = struct {
|
||||
s32 x;
|
||||
s32 y;
|
||||
s32 z;
|
||||
}
|
||||
|
||||
type Options = struct {
|
||||
struct {
|
||||
int foo;
|
||||
} api;
|
||||
}
|
||||
```
|
||||
##### use
|
||||
```
|
||||
let p1 = Point{
|
||||
x: 1,
|
||||
y: 2,
|
||||
z: 3,
|
||||
};
|
||||
let p2: Point = {
|
||||
x: 2,
|
||||
y: 3,
|
||||
z: 4,
|
||||
};
|
||||
|
||||
let x = p1.x;
|
||||
|
||||
p1.x = 2;
|
||||
|
||||
let opt = Options{
|
||||
api: {
|
||||
foo: 1
|
||||
}
|
||||
};
|
||||
|
||||
let a: Options@api = opt.api; // yeah this is weird, try to avoid it
|
||||
|
||||
```
|
||||
|
||||
##### enum
|
||||
###### declaration
|
||||
```
|
||||
enum A {
|
||||
Foo,
|
||||
Bar(u8)
|
||||
}
|
||||
|
||||
type A = enum {
|
||||
Foo,
|
||||
Bar(u8)
|
||||
}
|
||||
|
||||
type B = enum {
|
||||
X,
|
||||
Y(enum { // this is terrible but you can do it if you want for consistency reasons
|
||||
A,
|
||||
B
|
||||
})
|
||||
}
|
||||
|
||||
```
|
||||
###### use
|
||||
```
|
||||
let x = A'Foo;
|
||||
let y = A'Bar(10);
|
||||
let z = B'Y(B@Y'A); // don't do this why would you do this
|
||||
```
|
||||
|
||||
##### tuple
|
||||
###### declaration
|
||||
```
|
||||
type X = (s8, s8);
|
||||
tuple X(s8, s8);
|
||||
type Y = (struct {int a; int b}, enum {A, B}); // why would you do this aaaaa
|
||||
```
|
||||
###### use
|
||||
```
|
||||
let a: X = (1,2);
|
||||
let b = a.0;
|
||||
let c = a.1;
|
||||
let d = Y({a: 1, b: 2}, Y@1'A); // oh no
|
||||
let e: Y@1 = d.1;
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#### pointers
|
||||
Pointers are taken with the `&` operator and dereferenced with the `*` operator. They are mostly similar to C I think.
|
||||
Pointer types have a `*` appended to the type they point to.
|
||||
|
||||
```
|
||||
let a: int = 1;
|
||||
let b: int* = &a;
|
||||
let c = *b;
|
||||
```
|
||||
|
||||
A special `void*` type exists???? does it really? maybe? kinda yes? aaaaaaa
|
||||
|
||||
|
||||
Pointer arithmetic works the same as in C, except that arithmetic on void pointers is allowed?
|
||||
|
||||
```
|
||||
let a: [u8; 2] = {0,1};
|
||||
let b: u8* = &a[0];
|
||||
let c: u8* = b + 1;
|
||||
let d: u8 = *b; // 0
|
||||
let e: u8 = *c; // 1
|
||||
*(&a[0]+1) = 2; // a is now {0,2}
|
||||
```
|
||||
|
14
compiler/Compiler.cs
Normal file
14
compiler/Compiler.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using meowlang.parser;
|
||||
|
||||
namespace meowlang.compiler;
|
||||
|
||||
static class Compiler
|
||||
{
|
||||
private static void Main(string[] args)
|
||||
{
|
||||
var path = "example.mew";
|
||||
var model = Parser.Parse(path);
|
||||
Console.WriteLine(model.AutoToString());
|
||||
}
|
||||
}
|
26
compiler/compiler.csproj
Normal file
26
compiler/compiler.csproj
Normal file
|
@ -0,0 +1,26 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AssemblyName>meow</AssemblyName>
|
||||
<LangVersion>10</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Company />
|
||||
<Product>meow compiler</Product>
|
||||
<RootNamespace>meowlang.compiler</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\parser\parser.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="example.mew" />
|
||||
<Content Include="example.mew">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
91
compiler/example.mew
Normal file
91
compiler/example.mew
Normal file
|
@ -0,0 +1,91 @@
|
|||
import "std:strings";
|
||||
import "foo" as bar;
|
||||
import "./foobar";
|
||||
|
||||
/*
|
||||
fn foo() {}
|
||||
|
||||
pub fn bar(int x) -> int {}
|
||||
|
||||
pub fn multiret() -> int, int {}
|
||||
|
||||
[c_export] pub fn add(int a, int b) -> int {}
|
||||
|
||||
[c_export("add_floats")] pub fn add(float a, float b) -> float {}
|
||||
|
||||
fn sub<T>(T a, T b) -> T
|
||||
where SUBTRACT T
|
||||
{
|
||||
// do something
|
||||
}
|
||||
|
||||
|
||||
|
||||
fn ret_arr() -> [int; 10] {}
|
||||
fn ret_slice() -> [int] {}
|
||||
fn ret_multislice() -> [[int]] {}
|
||||
fn ret_ptr() -> int* {}
|
||||
fn ret_ptrslice() -> [int*] {}
|
||||
fn ret_arrayptr() -> [int; 5]* {}
|
||||
fn ret_tuple() -> (int, int) {}
|
||||
|
||||
fn ret_imported() -> strings:StringBuilder {}
|
||||
|
||||
fn ret_nested() -> foo@bar {}
|
||||
|
||||
fn ret_imported_nested() -> foo:bar@some@nested@shit {}
|
||||
|
||||
|
||||
constraint Foo A {
|
||||
whatever(A);
|
||||
}
|
||||
|
||||
constraint Bar B {
|
||||
constraint Foo B*;
|
||||
constraint Foo [B];
|
||||
constraint Foo (int, B);
|
||||
constraint Foo SomeType<B>;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
struct Foo {
|
||||
int something;
|
||||
struct {
|
||||
int foo;
|
||||
} bar;
|
||||
}
|
||||
|
||||
|
||||
Foo f;
|
||||
f.something
|
||||
|
||||
enum X {
|
||||
A,
|
||||
B,
|
||||
C
|
||||
}
|
||||
|
||||
enum X<T1, T2, T3> {
|
||||
A(T1),
|
||||
B(T2),
|
||||
C(T3),
|
||||
}
|
||||
|
||||
enum X<T1, T2, T3> where Constraint T1 T2 where Constraint T2 T3 {
|
||||
A(T1),
|
||||
B(T2),
|
||||
C(T3),
|
||||
}
|
||||
|
||||
struct X<T> {
|
||||
T a;
|
||||
}
|
||||
|
||||
tuple Point(int,int,int)
|
||||
|
||||
tuple Point<T> where Arithmetic T (T,T,T)
|
||||
|
||||
type A = Foo;
|
||||
|
||||
type F<X> = Foo<Bar<X>>;
|
277
parser/Meow.g4
Normal file
277
parser/Meow.g4
Normal file
|
@ -0,0 +1,277 @@
|
|||
grammar Meow;
|
||||
|
||||
file
|
||||
: importStatement* declaration* EOF
|
||||
;
|
||||
|
||||
importStatement
|
||||
: ImportKeyword importpath=StringLiteral (AsKeyword importname=Identifier)? ';'
|
||||
;
|
||||
|
||||
declaration
|
||||
: function ';'?
|
||||
| constraintDeclaration ';'?
|
||||
| structDeclaration ';'?
|
||||
| enumDeclaration ';'?
|
||||
| tupleDeclaration ';'?
|
||||
| typeAlias ';'?
|
||||
;
|
||||
|
||||
structDeclaration
|
||||
: StructKeyword name=Identifier (genericParameters constraint*)? structType
|
||||
;
|
||||
|
||||
enumDeclaration
|
||||
: EnumKeyword name=Identifier (genericParameters constraint*)? enumType
|
||||
;
|
||||
|
||||
tupleDeclaration
|
||||
: TupleKeyword name=Identifier (genericParameters constraint*)? tupleType
|
||||
;
|
||||
|
||||
typeAlias
|
||||
: TypeKeyword name=Identifier genericParameters? '=' typeReference
|
||||
;
|
||||
|
||||
|
||||
constraintDeclaration
|
||||
: ConstraintKeyword name=Identifier types+=Identifier+ '{' constraintRule* '}'
|
||||
;
|
||||
|
||||
constraintRule
|
||||
: embedConstraintRule
|
||||
| functionConstraintRule
|
||||
;
|
||||
|
||||
embedConstraintRule
|
||||
: ConstraintKeyword name=Identifier types+=typeReference+ ';'
|
||||
;
|
||||
|
||||
functionConstraintRule
|
||||
: name=Identifier constraintFunctionParameters functionReturn? ';'
|
||||
;
|
||||
|
||||
constraintFunctionParameters
|
||||
: '(' (typeReference (',' typeReference)*)? ')'
|
||||
;
|
||||
|
||||
function
|
||||
: attribute* pub=PubKeyword? FnKeyword name=Identifier functionParameters functionReturn? functionBody
|
||||
| attribute* pub=PubKeyword? FnKeyword name=Identifier genericParameters functionParameters functionReturn? constraint* functionBody
|
||||
;
|
||||
|
||||
|
||||
attribute
|
||||
: '[' name=Identifier ('(' (attributeValue (',' attributeValue)*)? ')')? ']'
|
||||
;
|
||||
|
||||
attributeValue
|
||||
: literal
|
||||
| id=Identifier
|
||||
;
|
||||
|
||||
literal
|
||||
: stringLiteral
|
||||
| numericLiteral
|
||||
| boolLiteral
|
||||
| characterLiteral
|
||||
;
|
||||
stringLiteral: val=StringLiteral;
|
||||
numericLiteral: val=NumericLiteral;
|
||||
boolLiteral: val=BoolLiteral;
|
||||
characterLiteral: val=CharacterLiteral;
|
||||
|
||||
genericParameters
|
||||
: '<' (name+=Identifier (',' name+=Identifier)*) '>'
|
||||
;
|
||||
|
||||
|
||||
functionParameters
|
||||
: '(' (functionParameter (',' functionParameter)*)? ')'
|
||||
;
|
||||
|
||||
functionParameter
|
||||
: typeReference name=Identifier
|
||||
;
|
||||
|
||||
functionReturn
|
||||
: '->' (typeReference (',' typeReference)*)
|
||||
;
|
||||
|
||||
constraint
|
||||
: WhereKeyword name=Identifier typenames+=Identifier+
|
||||
;
|
||||
|
||||
functionBody
|
||||
: '{' statement* expression? '}'
|
||||
;
|
||||
|
||||
|
||||
typeReference
|
||||
: nonPointerTypeReference pointer='*'?
|
||||
;
|
||||
|
||||
nonPointerTypeReference
|
||||
: typeName
|
||||
| arrayType
|
||||
| tupleType
|
||||
| StructKeyword structType
|
||||
| EnumKeyword enumType
|
||||
;
|
||||
|
||||
typeName
|
||||
: (importName=Identifier ':')? name+=Identifier ('<' genericType+=typeName (',' genericType+=typeName)* '>')? ('@' name+=Identifier)*
|
||||
;
|
||||
|
||||
arrayType
|
||||
: '[' typeReference (';' length=NumericLiteral)? ']'
|
||||
;
|
||||
|
||||
tupleType
|
||||
: '(' typeReference (',' typeReference)* ')'
|
||||
;
|
||||
|
||||
structType
|
||||
: '{' structMember* '}'
|
||||
;
|
||||
|
||||
structMember
|
||||
: typeReference name=Identifier ';'
|
||||
;
|
||||
|
||||
enumType
|
||||
: '{' enumMember (',' enumMember)* ','? '}'
|
||||
;
|
||||
|
||||
enumMember
|
||||
: name=Identifier ('(' typeReference ')')?
|
||||
;
|
||||
|
||||
|
||||
statement
|
||||
: breakStatement
|
||||
| continueStatement
|
||||
| returnStatement
|
||||
| loopStatement
|
||||
| expressionStatement
|
||||
;
|
||||
|
||||
breakStatement
|
||||
: BreakKeyword label=Identifier? ';'
|
||||
;
|
||||
continueStatement
|
||||
: ContinueKeyword label=Identifier? ';'
|
||||
;
|
||||
returnStatement
|
||||
: ReturnKeyword expression? ';'
|
||||
;
|
||||
loopStatement
|
||||
: LoopKeyword '{' statement* '}'
|
||||
| LoopKeyword condition=expression '{' statement* '}'
|
||||
| LoopKeyword init=expression? ';' condition=expression? ';' increment=expression? '{' statement* '}'
|
||||
;
|
||||
|
||||
expressionStatement
|
||||
: expression ';'
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
todo: use C operator precedence: https://en.cppreference.com/w/c/language/operator_precedence
|
||||
|
||||
binary operators:
|
||||
== != > >= < <=
|
||||
||
|
||||
&&
|
||||
+ -
|
||||
* / %
|
||||
&
|
||||
|
|
||||
^
|
||||
<<
|
||||
>>
|
||||
|
||||
unary operators:
|
||||
+
|
||||
-
|
||||
~
|
||||
!
|
||||
|
||||
|
||||
assignment:
|
||||
=
|
||||
+=
|
||||
-=
|
||||
/=
|
||||
*=
|
||||
%=
|
||||
&=
|
||||
|=
|
||||
^=
|
||||
<<=
|
||||
>>=
|
||||
|
||||
|
||||
*/
|
||||
expression
|
||||
: addExpression
|
||||
;
|
||||
|
||||
addExpression
|
||||
: multExpression ((op='+'|op='-') multExpression)*
|
||||
;
|
||||
|
||||
multExpression
|
||||
: terminalExpression ((op='*'|op='/'|op='%') terminalExpression)*
|
||||
;
|
||||
|
||||
terminalExpression
|
||||
: literal
|
||||
| structConstructor
|
||||
| arrayConstructor
|
||||
| enumConstructor
|
||||
| functionCall
|
||||
| ifExpression
|
||||
| switchExpression
|
||||
| blockExpression
|
||||
| parenthesisExpression
|
||||
;
|
||||
|
||||
///////////////////////////
|
||||
|
||||
ImportKeyword: 'import';
|
||||
AsKeyword: 'as';
|
||||
PubKeyword: 'pub';
|
||||
FnKeyword: 'fn';
|
||||
WhereKeyword: 'where';
|
||||
ConstraintKeyword: 'constraint';
|
||||
StructKeyword: 'struct';
|
||||
EnumKeyword: 'enum';
|
||||
TupleKeyword: 'tuple';
|
||||
TypeKeyword: 'type';
|
||||
BreakKeyword: 'break';
|
||||
ContinueKeyword: 'continue';
|
||||
ReturnKeyword: 'return';
|
||||
LoopKeyword: 'loop';
|
||||
|
||||
|
||||
|
||||
// start with letters (upper or lower case) followed by any alphanumeric symbol
|
||||
Identifier: [a-zA-Z_][a-zA-Z_0-9]*;
|
||||
|
||||
|
||||
|
||||
NumericLiteral: DecimalNumberLiteral /*| HexadecimalNumberLiteral | OctalNumberLiteral | BinaryNumberLiteral*/;
|
||||
|
||||
fragment DecimalNumberLiteral: DecimalNumberPart ('.' DecimalNumberPart)? | '.' DecimalNumberPart;
|
||||
fragment DecimalNumberPart: [0-9] [0-9_]*;
|
||||
BoolLiteral: 'true' | 'false' ;
|
||||
CharacterLiteral: '\'' (CharacterEscape | ~['\\]) '\'';
|
||||
fragment CharacterEscape: '\\\'' | '\\\\';
|
||||
StringLiteral: '"' (StringEscape | ~[\\"])*? '"';
|
||||
fragment StringEscape: '\\"' | '\\\\';
|
||||
|
||||
// comments and white space -> ignored
|
||||
BLOCK_COMMENT: '/*' .*? '*/' -> channel(HIDDEN);
|
||||
LINE_COMMENT: '//' ~[\n]* -> channel(HIDDEN);
|
||||
WS: [ \t\r\n\f]+ -> channel(HIDDEN);
|
3
parser/ModelBase.cs
Normal file
3
parser/ModelBase.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record ModelBase([property:Ignore] Span span);
|
20
parser/Parser.cs
Normal file
20
parser/Parser.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using Antlr4.Runtime;
|
||||
using meowlang.parser.antlr;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
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 file = parser.file();
|
||||
if (parser.NumberOfSyntaxErrors > 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return visitor.Visit(file);
|
||||
}
|
||||
}
|
3
parser/Span.cs
Normal file
3
parser/Span.cs
Normal file
|
@ -0,0 +1,3 @@
|
|||
namespace meowlang.parser;
|
||||
|
||||
public record Span(string Filename, int From, int To);
|
139
parser/Utils.cs
Normal file
139
parser/Utils.cs
Normal file
|
@ -0,0 +1,139 @@
|
|||
using System.Collections;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using Antlr4.Runtime;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace meowlang.parser;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
public class IgnoreAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
public static class ObjectExtensions
|
||||
{
|
||||
public static string AutoToString(this object? o, bool prettyPrint = true, bool encapsulate = true)
|
||||
{
|
||||
if (o == null) return "null";
|
||||
var type = o.GetType();
|
||||
if (o is string s)
|
||||
{
|
||||
var escaped = s.Replace("\\", "\\\\").Replace("\"", "\\\"");
|
||||
return $"\"{escaped}\"";
|
||||
}
|
||||
|
||||
if (o is bool b)
|
||||
{
|
||||
return b ? "true" : "false";
|
||||
}
|
||||
|
||||
if (type.IsPrimitive)
|
||||
{
|
||||
return o.ToString()!;
|
||||
}
|
||||
|
||||
if (type.IsEnum)
|
||||
{
|
||||
var val = Enum.GetName(type, o);
|
||||
return $"\"{val}\"";
|
||||
}
|
||||
|
||||
string json;
|
||||
|
||||
if (type.IsAssignableTo(typeof(IEnumerable)))
|
||||
{
|
||||
var enumerable = (o as IEnumerable)!.Cast<object>();
|
||||
var sb = new StringBuilder();
|
||||
sb.Append('[');
|
||||
sb.AppendJoin(", ", enumerable.Select(x => x.AutoToString(false)));
|
||||
sb.Append(']');
|
||||
json = sb.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
var properties = type.GetProperties();
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.Append('{');
|
||||
sb.Append($"\"@type\": \"{type.Name}\"");
|
||||
|
||||
|
||||
for (var index = 0; index < properties.Length; index++)
|
||||
{
|
||||
var propertyInfo = properties[index];
|
||||
if (propertyInfo.GetCustomAttribute<IgnoreAttribute>() != null) continue;
|
||||
sb.Append(',');
|
||||
sb.Append($"\"{propertyInfo.Name}\": ");
|
||||
var propertyValue = propertyInfo.GetValue(o);
|
||||
sb.Append(propertyValue.AutoToString());
|
||||
}
|
||||
|
||||
sb.Append('}');
|
||||
json = sb.ToString();
|
||||
}
|
||||
|
||||
if (prettyPrint)
|
||||
{
|
||||
var temp = JsonConvert.DeserializeObject(json);
|
||||
json = JsonConvert.SerializeObject(temp, Formatting.Indented);
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ParserRuleContextExtensions
|
||||
{
|
||||
public static Span GetSpan(this ParserRuleContext context)
|
||||
{
|
||||
return new Span(context.Start.TokenSource.SourceName, context.Start.StartIndex, context.Stop.StopIndex);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class TokenExtensions
|
||||
{
|
||||
public static Span GetSpan(this IToken token)
|
||||
{
|
||||
return new Span(token.TokenSource.SourceName, token.StartIndex, token.StopIndex);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class StringExtensions
|
||||
{
|
||||
public static string Unescape(this string str)
|
||||
{
|
||||
StringBuilder builder = new();
|
||||
var startPos = 0;
|
||||
int backslashPos;
|
||||
while ((backslashPos = str.IndexOf('\\', startPos)) > -1)
|
||||
{
|
||||
builder.Append(str[startPos..backslashPos]);
|
||||
int length;
|
||||
string ch;
|
||||
switch (str[backslashPos + 1])
|
||||
{
|
||||
case '\\':
|
||||
ch = "\\";
|
||||
length = 1;
|
||||
break;
|
||||
case '\'':
|
||||
ch = "'";
|
||||
length = 1;
|
||||
break;
|
||||
case '"':
|
||||
ch = "\"";
|
||||
length = 1;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidEscapeSequenceException($"\\{str[backslashPos + 1]}");
|
||||
}
|
||||
|
||||
builder.Append(ch);
|
||||
startPos = backslashPos + length + 1;
|
||||
}
|
||||
|
||||
builder.Append(str[startPos..]);
|
||||
return builder.ToString();
|
||||
}
|
||||
}
|
412
parser/Visitor.cs
Normal file
412
parser/Visitor.cs
Normal file
|
@ -0,0 +1,412 @@
|
|||
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);
|
15
parser/parser.csproj
Normal file
15
parser/parser.csproj
Normal file
|
@ -0,0 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>meowlang.parser</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Antlr4.Runtime.Standard" Version="4.9.3" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
Loading…
Reference in a new issue