Compare commits

..

No commits in common. "grammar-overhaul" and "main" have entirely different histories.

10 changed files with 261 additions and 1223 deletions

View File

@ -1,6 +1,5 @@
use crate::spec::{ use crate::spec::{
BuildBooleanOn, ChildSpec, SingleBooleanChildToBuild, SingleChildToBuild, BuildBooleanOn, ChildSpec, SingleChildToBuild, StructBuildSpec, VecChildToBuild,
SingleTypeChildToBuild, StructBuildSpec, VecChild, VecChildToBuild,
}; };
use convert_case::{Case, Casing}; use convert_case::{Case, Casing};
use proc_macro2::TokenStream; use proc_macro2::TokenStream;
@ -10,45 +9,33 @@ pub fn make_build_fn_name(s: &str) -> String {
format!("build_{}", s.to_case(Case::Snake)) format!("build_{}", s.to_case(Case::Snake))
} }
fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream {
let (child_ident, child_type_ident) = match vec_child.build() {
VecChildToBuild::Type(vec_type_child) => (
format_ident!("{}", vec_type_child.var_name()),
format_ident!("{}", vec_type_child.build()),
),
};
quote! {
let mut #child_ident: Vec<Box<#child_type_ident>> = vec![]
}
}
fn make_single_type_child_holder(single_type_child: &SingleTypeChildToBuild) -> TokenStream {
let child_ident = format_ident!("{}", single_type_child.var_name());
let child_type_ident = format_ident!("{}", single_type_child.build());
quote! {
let mut #child_ident: Option<Box<#child_type_ident>> = None
}
}
fn make_single_boolean_child_holder(
single_boolean_child: &SingleBooleanChildToBuild,
) -> TokenStream {
let child_ident = format_ident!("{}", single_boolean_child.var_name());
quote! {
let mut #child_ident: bool = false
}
}
fn make_child_holder(child_spec: &ChildSpec) -> Option<TokenStream> { fn make_child_holder(child_spec: &ChildSpec) -> Option<TokenStream> {
match child_spec { match child_spec {
ChildSpec::SkipChild(_) => None, ChildSpec::SkipChild(_) => None,
ChildSpec::VecChild(vec_child) => Some(make_vec_child_holder(vec_child)), ChildSpec::VecChild(vec_child) => {
let (child_ident, child_type_ident) = match vec_child.build() {
VecChildToBuild::Type(vec_type_child) => (
format_ident!("{}", vec_type_child.var_name()),
format_ident!("{}", vec_type_child.build()),
),
};
Some(quote! {
let mut #child_ident: Vec<#child_type_ident> = vec![]
})
}
ChildSpec::SingleChild(single_child) => match single_child.build() { ChildSpec::SingleChild(single_child) => match single_child.build() {
SingleChildToBuild::Type(single_type_child) => { SingleChildToBuild::Type(single_type_child) => {
Some(make_single_type_child_holder(single_type_child)) let child_ident = format_ident!("{}", single_type_child.var_name());
let child_type_ident = format_ident!("{}", single_type_child.build());
Some(quote! {
let mut #child_ident: Option<#child_type_ident> = None;
})
} }
SingleChildToBuild::Boolean(boolean_child) => { SingleChildToBuild::Boolean(boolean_child) => {
Some(make_single_boolean_child_holder(boolean_child)) let child_ident = format_ident!("{}", boolean_child.var_name());
Some(quote! {
let #child_ident: bool = false
})
} }
}, },
} }
@ -65,7 +52,7 @@ fn make_match_action(child_spec: &ChildSpec) -> TokenStream {
), ),
}; };
quote! { quote! {
#child_name_ident.push(Box::new(#build_fn_ident(inner_pair))) #child_name_ident.push(#build_fn_ident(inner_pair))
} }
} }
ChildSpec::SingleChild(single_child) => match single_child.build() { ChildSpec::SingleChild(single_child) => match single_child.build() {
@ -73,7 +60,7 @@ fn make_match_action(child_spec: &ChildSpec) -> TokenStream {
let child_name_ident = format_ident!("{}", single_type_child.var_name()); let child_name_ident = format_ident!("{}", single_type_child.var_name());
let build_fn_ident = format_ident!("{}", single_type_child.with()); let build_fn_ident = format_ident!("{}", single_type_child.with());
quote! { quote! {
#child_name_ident = Some(Box::new(#build_fn_ident(inner_pair))) #child_name_ident = Some(#build_fn_ident(inner_pair))
} }
} }
SingleChildToBuild::Boolean(single_boolean_child) => { SingleChildToBuild::Boolean(single_boolean_child) => {
@ -103,57 +90,6 @@ fn make_rule_matcher(child_spec: &ChildSpec) -> TokenStream {
} }
} }
fn make_child_arg(child_spec: &ChildSpec) -> Option<TokenStream> {
match child_spec {
ChildSpec::SkipChild(_) => None,
ChildSpec::VecChild(vec_child) => {
let child_ident = match vec_child.build() {
VecChildToBuild::Type(vec_type_child) => {
format_ident!("{}", vec_type_child.var_name())
}
};
Some(quote! { #child_ident })
}
ChildSpec::SingleChild(single_child) => match single_child.build() {
SingleChildToBuild::Type(single_type_child) => {
let child_ident = format_ident!("{}", single_type_child.var_name());
if single_type_child.optional() {
Some(quote! { #child_ident })
} else if let Some(or_else) = single_type_child.or_else() {
let child_type_ident = format_ident!("{}", single_type_child.build());
let or_else_ident = format_ident!("{}", or_else);
Some(quote! {
#child_ident.unwrap_or_else(|| Box::new(#child_type_ident::#or_else_ident()))
})
} else {
Some(quote! { #child_ident.unwrap() })
}
}
SingleChildToBuild::Boolean(single_boolean_child) => {
let child_ident = format_ident!("{}", single_boolean_child.var_name());
Some(quote! { #child_ident })
}
},
}
}
fn make_return_value_stream(build_spec: &StructBuildSpec) -> TokenStream {
let type_ident = format_ident!("{}", build_spec.build());
let child_args = build_spec
.children()
.iter()
.map(|child| make_child_arg(child))
.filter(|child_arg| child_arg.is_some())
.map(|child_arg| child_arg.unwrap())
.collect::<Vec<_>>();
quote! {
#type_ident::new(
#(#child_args,)*
)
}
}
pub fn make_struct_build_fn(build_spec: &StructBuildSpec) -> TokenStream { pub fn make_struct_build_fn(build_spec: &StructBuildSpec) -> TokenStream {
let build_fn_ident = format_ident!("{}", build_spec.with()); let build_fn_ident = format_ident!("{}", build_spec.with());
let pair_ident = format_ident!("{}_pair", build_spec.build().to_case(Case::Snake)); let pair_ident = format_ident!("{}_pair", build_spec.build().to_case(Case::Snake));
@ -181,66 +117,11 @@ pub fn make_struct_build_fn(build_spec: &StructBuildSpec) -> TokenStream {
} }
}; };
let new_stream = make_return_value_stream(build_spec);
quote! { quote! {
fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident { fn #build_fn_ident(#pair_ident: Pair<Rule>) -> #return_type_ident {
#(#child_holders;)* #(#child_holders;)*
#iter_stream #iter_stream
#new_stream
} }
} }
} }
#[cfg(test)]
mod tests {
use super::*;
use crate::spec::VecTypeChildToBuild;
#[test]
fn vec_child_holder() {
let vec_child = VecChild::new(
"test_child",
"Test",
VecChildToBuild::Type(VecTypeChildToBuild::new(
"TestType",
"test_child",
"build_test_child",
)),
);
assert_eq!(
make_vec_child_holder(&vec_child).to_string(),
quote! {
let mut test_child: Vec<Box<TestType>> = vec![]
}
.to_string()
);
}
#[test]
fn single_type_child_holder() {
let single_type_child = SingleTypeChildToBuild::from_build_or_rule("TestType", None, false);
assert_eq!(
make_single_type_child_holder(&single_type_child).to_string(),
quote! {
let mut test_type: Option<Box<TestType>> = None
}
.to_string()
);
}
#[test]
fn single_boolean_child_holder() {
let single_boolean_child =
SingleBooleanChildToBuild::new("test_child", BuildBooleanOn::RulePresent);
assert_eq!(
make_single_boolean_child_holder(&single_boolean_child).to_string(),
quote! {
let mut test_child: bool = false
}
.to_string()
);
}
}

View File

@ -46,58 +46,35 @@ fn get_vec_child(name: &str, rule: &str, build: &Yaml) -> ChildSpec {
)) ))
} }
fn get_single_child_to_build(name: &str, rule: &str, optional: bool, build: &Yaml) -> SingleChildToBuild { fn get_single_child_to_build(name: &str, rule: &str, build: &Yaml) -> SingleChildToBuild {
if build.is_hash() { if build.is_hash() {
match build["type"].as_str() { let r#type = build["type"].as_str().unwrap();
Some(r#type) => { let var_name = build["var"]
let var_name = build["var"] .as_str()
.as_str() .map(|s| s.to_string())
.map(|s| s.to_string()) .unwrap_or(name.to_string());
.unwrap_or(name.to_string()); let on = build["on"].as_str().unwrap();
let on = build["on"].as_str().unwrap(); if r#type.eq("boolean") && on.eq("rule_present") {
if r#type.eq("boolean") && on.eq("rule_present") { SingleChildToBuild::Boolean(SingleBooleanChildToBuild::new(
SingleChildToBuild::Boolean(SingleBooleanChildToBuild::new( &var_name,
&var_name, BuildBooleanOn::RulePresent,
BuildBooleanOn::RulePresent, ))
)) } else {
} else { todo!("currently on boolean types with on: rule_present are supported")
todo!("currently on boolean types with on: rule_present are supported")
}
},
None => {
let or_else = build["or_else"]
.as_str()
.map(|s| s.to_string())
.or_else(|| {
let or_else_default = build["or_else_default"]
.as_bool()
.unwrap_or_else(|| false);
if or_else_default {
Some(String::from("default"))
} else {
None
}
});
SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(
rule,
or_else,
optional,
))
}
} }
} else { } else {
match build.as_str() { match build.as_str() {
Some(s) => SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(s, None, optional)), Some(s) => SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(s)),
None => SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(rule, None, optional)), None => SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(rule)),
} }
} }
} }
fn get_single_child(name: &str, rule: &str, optional: bool, build: &Yaml) -> ChildSpec { fn get_single_child(name: &str, rule: &str, build: &Yaml) -> ChildSpec {
ChildSpec::SingleChild(SingleChild::new( ChildSpec::SingleChild(SingleChild::new(
name, name,
rule, rule,
get_single_child_to_build(name, rule, optional, build), get_single_child_to_build(name, rule, build),
)) ))
} }
@ -115,25 +92,18 @@ fn get_child_specs(children: &Yaml) -> Vec<ChildSpec> {
.map(|(name, props)| (name.as_str().unwrap(), props)) .map(|(name, props)| (name.as_str().unwrap(), props))
.unwrap(); .unwrap();
let rule = props["rule"] let rule = props["rule"].as_str().unwrap();
.as_str()
.map(|s| s.to_string())
.unwrap_or(name.to_case(Case::Pascal));
if get_skip(&props["skip"]) { if get_skip(&props["skip"]) {
return ChildSpec::SkipChild(SkipChild::new(name, &rule)); return ChildSpec::SkipChild(SkipChild::new(name, rule));
} }
let build = &props["build"]; let build = &props["build"];
if get_vec(&props["vec"]) { if get_vec(&props["vec"]) {
get_vec_child(name, &rule, build) get_vec_child(name, rule, build)
} else { } else {
let optional = props["optional"] get_single_child(name, rule, build)
.as_bool()
.unwrap_or_else(|| false);
get_single_child(name, &rule, optional, build)
} }
} else { } else {
ChildSpec::SingleChild(SingleChild::from_name_snake(child_spec.as_str().unwrap())) ChildSpec::SingleChild(SingleChild::from_name_snake(child_spec.as_str().unwrap()))

View File

@ -9,7 +9,6 @@ use proc_macro2::TokenStream;
use quote::quote; use quote::quote;
use spec::BuildSpec; use spec::BuildSpec;
use syn::File; use syn::File;
use syn::spanned::Spanned;
fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) { fn debug_built_spec(build_spec: &BuildSpec, token_stream: &TokenStream) {
println!("*** BuildSpec ***"); println!("*** BuildSpec ***");

View File

@ -233,8 +233,6 @@ impl SingleChild {
rule: name.to_case(Case::Pascal), rule: name.to_case(Case::Pascal),
build: SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule( build: SingleChildToBuild::Type(SingleTypeChildToBuild::from_build_or_rule(
&name.to_case(Case::Pascal), &name.to_case(Case::Pascal),
None,
false,
)), )),
} }
} }
@ -274,22 +272,14 @@ pub struct SingleTypeChildToBuild {
build: String, build: String,
var_name: String, var_name: String,
with: String, with: String,
or_else: Option<String>,
optional: bool,
} }
impl SingleTypeChildToBuild { impl SingleTypeChildToBuild {
pub fn from_build_or_rule( pub fn from_build_or_rule(build_or_rule: &str) -> Self {
build_or_rule: &str,
or_else: Option<String>,
optional: bool,
) -> Self {
Self { Self {
build: build_or_rule.to_string(), build: build_or_rule.to_string(),
var_name: build_or_rule.to_case(Case::Snake), var_name: build_or_rule.to_case(Case::Snake),
with: make_build_fn_name(build_or_rule), with: make_build_fn_name(build_or_rule),
or_else,
optional,
} }
} }
@ -307,16 +297,6 @@ impl SingleTypeChildToBuild {
pub fn with(&self) -> &str { pub fn with(&self) -> &str {
&self.with &self.with
} }
/// The default fn to call when unwrapping the child (before passing as arg to new).
pub fn or_else(&self) -> Option<&str> {
self.or_else.as_deref()
}
/// If the type should be wrapped in an Option.
pub fn optional(&self) -> bool {
self.optional
}
} }
#[derive(Debug)] #[derive(Debug)]

View File

@ -64,15 +64,9 @@ fn handle_single_type_child(
let child_ident_mut = format_ident!("{}_mut", single_type_child.var_name()); let child_ident_mut = format_ident!("{}_mut", single_type_child.var_name());
let child_type_ident = format_ident!("{}", single_type_child.build()); let child_type_ident = format_ident!("{}", single_type_child.build());
member_names.push(child_ident.clone()); member_names.push(child_ident.clone());
if single_type_child.optional() { annotated_members.push(quote! {
annotated_members.push(quote! { #child_ident: Box<#child_type_ident>
#child_ident: Option<Box<#child_type_ident>> });
});
} else {
annotated_members.push(quote! {
#child_ident: Box<#child_type_ident>
})
}
accessors.push(quote! { accessors.push(quote! {
pub fn #child_ident(&self) -> &#child_type_ident { pub fn #child_ident(&self) -> &#child_type_ident {
self.#child_ident.as_ref() self.#child_ident.as_ref()

View File

@ -1,5 +0,0 @@
use math::add
fn main()
println add(1, 2) // 3
end

View File

@ -1,3 +0,0 @@
mod math
pub fn add(a: Int, b: Int) = a + b

View File

@ -9,52 +9,22 @@ $defs:
type: object type: object
additionalProperties: false additionalProperties: false
description: A definition of a node type. description: A definition of a node type.
oneOf:
- $ref: "#/$defs/StructNodeDefinition"
- $ref: "#/$defs/EnumNodeDefinition"
- $ref: "#/$defs/LeafEnumNodeDefinition"
StructNodeDefinition:
type: object
additionalProperties: false
description: A description of a Struct node to be built.
properties: properties:
type:
const: struct
children: children:
type: array
description: Ordered child fields for this node. description: Ordered child fields for this node.
items: items:
$ref: "#/$defs/StructChildDefinition" $ref: "#/$defs/StructChildDefinition"
required:
- children
EnumNodeDefinition:
type: object
additionalProperties: false
description: A description of an Enum node to be built.
properties:
type:
const: enum
rules: rules:
type: array type: array
description: Alternative parse rules that build this node. description: Alternative parse rules that build this node.
items: items:
$ref: "#/$defs/EnumChildDefinition" $ref: "#/$defs/EnumChildDefinition"
required: oneOf:
- rules - required:
LeafEnumNodeDefinition: - "children"
type: object - required:
additionalProperties: false - "rules"
description: A description of a leaf-enum node to be built.
properties:
type:
const: leaf_enum
rules:
type: array
description: Alternative parse rules that build this node.
items:
$ref: "#/$defs/LeafEnumChildDefinition"
required:
- type
- rules
StructChildDefinition: StructChildDefinition:
description: A definition of a node's child. Either a bare child name (string) in snake case, or an object. description: A definition of a node's child. Either a bare child name (string) in snake case, or an object.
oneOf: oneOf:
@ -108,36 +78,18 @@ $defs:
properties: properties:
rule: rule:
type: string type: string
description: The type to build, in Pascal case.
optional:
type: boolean
description: If true, this child will be stored as an Option.
build: build:
oneOf: oneOf:
- type: string - type: string
- $ref: "#/$defs/SingleChildBuildDefinition" - $ref: "#/$defs/SingleChildBuildDefinition"
required:
- rule
SingleChildBuildDefinition: SingleChildBuildDefinition:
type: object type: object
additionalProperties: false additionalProperties: false
description: A definition of what exactly to build for a given child rule. description: A definition of what exactly to build for a given child rule.
oneOf: oneOf:
- $ref: "#/$defs/BuildSingleTypeChild"
- $ref: "#/$defs/BuildBooleanChild" - $ref: "#/$defs/BuildBooleanChild"
- $ref: "#/$defs/BuildStringChild"
- $ref: "#/$defs/BuildDoubleChild"
- $ref: "#/$defs/BuildIntChild"
- $ref: "#/$defs/BuildLongChild"
BuildSingleTypeChild:
type: object
additionalProperties: false
description: A definition of a single-type child to build.
properties:
or_else:
type: string
description: The method name to call upon the built-type if the rule is not found. Takes precedence over "or_else_default".
or_else_default:
type: boolean
description: Whether to call the default method on the built-type if the rule is not found.
BuildBooleanChild: BuildBooleanChild:
type: object type: object
additionalProperties: false additionalProperties: false
@ -151,54 +103,6 @@ $defs:
type: string type: string
enum: enum:
- rule_present - rule_present
from:
type: string
enum:
- parse_whole_pair
BuildStringChild:
type: object
additionalProperties: false
description: A definition for building a string child.
properties:
type:
const: string
from:
type: string
enum:
- whole_pair
BuildDoubleChild:
type: object
additionalProperties: false
description: A definition for building a Double child.
properties:
type:
const: f64
from:
type: string
enum:
- parse_whole_pair
BuildIntChild:
type: object
additionalProperties: false
description: A definition for building an Int child.
properties:
type:
const: i32
from:
type: string
enum:
- parse_number_base
BuildLongChild:
type: object
additionalProperties: false
description: A definition for building a Long child.
properties:
type:
const: i64
from:
type: string
enum:
- parse_number_base
EnumChildDefinition: EnumChildDefinition:
description: A definition of an enum node's child. Either a bare rule (string) in Pascal case, or an object. description: A definition of an enum node's child. Either a bare rule (string) in Pascal case, or an object.
oneOf: oneOf:
@ -217,28 +121,3 @@ $defs:
required: required:
- rule - rule
- build - build
LeafEnumChildDefinition:
description: A definition of a leaf-enum node's child. Either a bare rule-string in Pascal case, or an object.
oneOf:
- type: string
description: Shorthand where the rule name maps onto an empty enum rule.
- $ref: "#/$defs/LongLeafEnumChildDefinitionWrapper"
LongLeafEnumChildDefinitionWrapper:
type: object
description: Single-key object mapping the child-name to its spec.
minProperties: 1
maxProperties: 1
additionalProperties: false
patternProperties:
"^([A-Z][a-z0-9]*)*$":
$ref: "#/$defs/LongLeafEnumChildDefinition"
LongLeafEnumChildDefinition:
type: object
additionalProperties: false
description: A format for specifying more specific information about a leaf-enum child.
properties:
child:
type: boolean
description: If true, a node of the same name is built as the lone member of the enum child.
required:
- child

View File

@ -1,35 +1,19 @@
# $schema: ./ast.schema.yaml # $schema: ./ast.schema.yaml
# Names
Identifier:
children:
- literal:
build:
type: string
from: parse_whole_pair
FullyQualifiedName:
children:
- identifiers:
rule: Identifier
vec: true
# Top-level constructs
CompilationUnit: CompilationUnit:
children: children:
- parent_mod - namespace
- use_statements: - use_statements:
rule: UseStatement rule: UseStatement
vec: true vec: true
- module_level_declarations: - module_level_declarations:
rule: ModuleLevelDeclaration rule: ModuleLevelDeclaration
vec: true Namespace:
ParentMod:
children: children:
- mod_kw: - ns_kw:
rule: Mod rule: Ns
skip: true skip: true
- fqn: - fqn:
rule: FullyQualifiedName rule: Fqn
UseStatement: UseStatement:
children: children:
- use_kw: - use_kw:
@ -40,49 +24,17 @@ UseStatement:
vec: true vec: true
- suffix: - suffix:
rule: UseStatementSuffix rule: UseStatementSuffix
UseStatementPrefix:
children:
- identifier
UseStatementSuffix:
rules:
- Identifier
- rule: Star
build: UseStatementStarSuffix
- UseList
UseList:
children:
- identifiers:
rule: Identifier
vec: true
# Level declarations
ModuleLevelDeclaration: ModuleLevelDeclaration:
rules: rules:
- Module - rule: Module
- Interface build: ModuleDeclaration
- Class - rule: Interface
- Function build: InterfaceDeclaration
- rule: Class
build: ClassDeclaration
- FunctionDefinition
- PlatformFunction - PlatformFunction
InterfaceLevelDeclaration: ModuleDeclaration:
rules:
- CompanionModule
- Interface
- Class
- InterfaceFunction
- InterfaceDefaultFunction
- InterfaceOperatorFunction
- InterfaceDefaultOperatorFunction
ClassLevelDeclaration:
children:
- CompanionModule
- Interface
- Class
- Function
- OperatorFunction
- PlatformFunction
# Main organizational constructs
Module:
children: children:
- is_public: - is_public:
rule: Pub rule: Pub
@ -97,47 +49,7 @@ Module:
- declarations: - declarations:
rule: ModuleLevelDeclaration rule: ModuleLevelDeclaration
vec: true vec: true
- end_kw: ClassDeclaration:
rule: End
skip: true
CompanionModule:
children:
- companion_kw:
rule: Companion
skip: true
- mod_kw:
rule: Mod
skip: true
- declarations:
rule: ModuleLevelDeclaration
vec: true
- end_kw:
rule: End
skip: true
Interface:
children:
- is_public:
rule: Pub
build:
type: boolean
on: rule_present
- int_kw:
rule: IntKw
skip: true
- identifier
- generic_parameters:
build:
or_else_default: true
- implements_list:
build:
or_else_default: true
- declarations:
rule: InterfaceLevelDeclaration
vec: true
- end_kw:
rule: End
skip: true
Class:
children: children:
- is_public: - is_public:
rule: Pub rule: Pub
@ -148,27 +60,22 @@ Class:
rule: ClassKw rule: ClassKw
skip: true skip: true
- identifier - identifier
- generic_parameters: - generic_parameters
build: - class_constructor
or_else_default: true - implements_list
- class_constructor:
build:
or_else_default: true
- implements_list:
build:
or_else_default: true
- class_level_declarations: - class_level_declarations:
rule: ClassLevelDeclaration rule: ClassLevelDeclaration
vec: true vec: true
FunctionDeclaration:
# Function constructs
Function:
children: children:
- is_public: - is_public:
rule: Pub rule: Pub
build: build:
type: boolean type: boolean
on: rule_present on: rule_present
- modifier:
rule: Modifier
build: FunctionModifier
- fn_kw: - fn_kw:
rule: Fn rule: Fn
skip: true skip: true
@ -176,561 +83,5 @@ Function:
rule: GenericParameters rule: GenericParameters
- identifier - identifier
- parameters - parameters
- return_type:
build:
or_else: void
- function_body
OperatorFunction:
children:
- is_public:
rule: Pub
build:
type: boolean
on: rule_present
- op_kw:
rule: Op
skip: true
- generics:
rule: GenericParameters
build:
or_else_default: true
- operator
- parameters
- return_type:
build:
or_else: void
- function_body
PlatformFunction:
children:
- is_public:
rule: Pub
build:
type: boolean
on: rule_present
- platform_kw:
rule: Platform
skip: true
- fn_kw:
rule: Fn
skip: true
- generics:
rule: GenericParameters
build:
or_else_default: true
- identifier
- parameters
- return_type - return_type
InterfaceFunction:
children:
- fn_kw:
rule: Fn
skip: true
- generics:
rule: GenericParameters
build:
or_else_default: true
- identifier
- parameters
- return_type
InterfaceDefaultFunction:
children:
- def_kw:
rule: Def
skip: true
- fn_kw:
rule: Fn
skip: true
- generics:
rule: GenericParameters
build:
or_else_default: true
- identifier
- parameters
- return_type:
build:
or_else: void
- function_body - function_body
InterfaceOperatorFunction:
children:
- op_kw:
rule: Op
skip: true
- generics:
rule: GenericParameters
build:
or_else_default: true
- operator
- parameters
- return_type
InterfaceDefaultOperatorFunction:
children:
- def_kw:
rule: Def
skip: true
- op_kw:
rule: Op
skip: true
- generics:
rule: GenericParameters
build:
or_else_default: true
- operator
- parameters
- return_type:
build:
or_else: void
- function_body
# Function Bodies
FunctionBody:
rules:
- FunctionAliasBody
- FunctionEqualsBody
- FunctionBlockBody
FunctionEqualsBody:
children:
- expression
FunctionAliasBody:
children:
- alias_kw:
rule: Alias
skip: true
- identifier
FunctionBlockBody:
children:
- statements:
rule: Statement
vec: true
- end_kw:
rule: End
skip: true
# Class constructs
ClassConstructor:
children:
- members:
rule: Member
vec: true
Member:
children:
- is_public:
rule: Pub
build:
type: boolean
on: rule_present
- is_mut:
rule: Mut
build:
type: boolean
on: rule_present
- identifier
- type_use
# Statements
Statement:
rules:
- VariableDeclaration
- AssignmentStatement
- ExpressionStatement
- UseStatement
- IfElseStatement
- IfStatementStatement
- WhileStatement
- ForStatement
VariableDeclaration:
children:
- let_kw:
rule: Let
skip: true
- is_mut:
rule: Mut
build:
type: boolean
on: rule_present
- identifier
- type_use:
optional: true
- expression:
optional: true
AssignmentStatement:
children:
- left:
rule: Expression
- right:
rule: Expression
ExpressionStatement:
children:
- expression
IfStatement:
children:
- if_clause
- if_else_ifs:
rule: IfElseIf
vec: true
- if_else
- end_kw:
rule: End
skip: true
IfClause:
children:
- if_kw:
rule: If
skip: true
- expression
- then_kw:
rule: Then
skip: true
- statements:
rule: Statement
vec: true
IfElseIf:
children:
- else_kw:
rule: Else
skip: true
- if_clause
IfElse:
children:
- else_kw:
rule: Else
skip: true
- statements:
rule: Statement
vec: true
WhileStatement:
children:
- while_kw:
rule: While
skip: true
- expression
- do_kw:
rule: Do
skip: true
- statements:
rule: Statement
vec: true
- end_kw:
rule: End
skip: true
ForStatement:
children:
- for_kw:
rule: For
skip: true
- identifier
- in_kw:
rule: In
skip: true
- expression
- do_kw:
rule: Do
skip: true
- statement:
rule: Statement
vec: true
- end_kw:
rule: End
vec: true
# Expressions
Expression:
children:
- ternary_expression
TernaryExpression:
children:
- or_expression
- ternary_alternatives:
optional: true
TernaryAlternatives:
children:
- ternary_true_alternative
- ternary_false_alternative
TernaryTrueAlternative:
children:
- expression
TernaryFalseAlternative:
children:
- expression
OrExpression:
children:
- left:
rule: AndExpression
- or_sym:
rule: Or
skip: true
- right:
rule: Expression
optional: true
AndExpression:
children:
- left:
rule: ComparisonExpression
- and_sym:
rule: And
skip: true
- right:
rule: Expression
optional: true
ComparisonExpression:
children:
- left:
rule: ShiftExpression
- operator:
rule: ComparisonOperator
optional: true
- right:
rule: Expression
optional: true
ComparisonOperator:
rules:
- Greater
- Less
- GreaterEqual
- LessEqual
- EqualTo
- NotEqualTo
ShiftExpression:
children:
- left:
rule: AdditiveExpression
- operator:
rule: ShiftOperator
optional: true
- right:
rule: Expression
ShiftOperator:
rules:
- LeftShift
- RightShift
AdditiveExpression:
children:
- left:
rule: MultiplicativeExpression
- operator:
rule: AdditiveOperator
optional: true
- right:
rule: Expression
optional: true
MultiplicativeExpression:
children:
- left:
rule: PrefixExpression
- operator:
rule: MultiplicativeOperator
optional: true
- right:
rule: Expression
MultiplicativeOperator:
type: leaf_enum
rules:
- Multiply
- Divide
- Modulo
PrefixExpression:
children:
- operators:
rule: PrefixOperator
vec: true
PrefixOperator:
type: leaf_enum
rules:
- Spread
- Not
- Negative
SuffixExpression:
children:
- left:
rule: PrimaryExpression
- operators:
rule: SuffixOperator
vec: true
SuffixOperator:
type: leaf_enum
rules:
- PlusPlus
- MinusMinus
- ObjectProperty:
child: true
- ObjectIndex:
child: true
- Call:
child: true
ObjectProperty:
children:
- identifier
ObjectIndex:
children:
- expression
PrimaryExpression:
rules:
- Literal
- FullyQualifiedName
- Closure
- ParenthesizedExpression
ParenthesizedExpression:
children:
- expression
# Calls
Call:
rules:
- ParenthesesCall
- NonParenthesesCall
ParenthesesCall:
children:
- turbo_fish:
optional: true
- expression_list:
optional: true
- closure:
optional: true
NonParenthesesCall:
children:
- turbo_fish:
optional: true
- expression_list:
optional: true
- closure:
optional: true
TurboFish:
children:
- generic_arguments
ExpressionList:
children:
- expressions:
rule: Expression
vec: true
# Closure
Closure:
children:
- closure_parameters:
build:
or_else_default: true
- statements:
rule: Statement
vec: true
ClosureParameters:
children:
- parameters:
rule: ClosureParameters
vec: true
ClosureParameter:
children:
- identifier
- type_use:
optional: true
# Literals
Literal:
rules:
- NumberLiteral
- StringLiteral
- BooleanLiteral
NumberLiteral:
rules:
- DoubleLiteral
- LongLiteral
- IntLiteral
IntLiteral:
children:
- number_base
- literal:
build:
type: i32
from: parse_number_base
LongLiteral:
children:
- number_base
- literal:
build:
type: i64
from: parse_number_base
DoubleLiteral:
children:
- literal:
build:
type: f64
from: parse_whole_pair
NumberBase:
rules:
- BinaryBase
- HexadecimalBase
- DecimalBase
DecimalBase:
children:
- literal:
build:
type: string
from: whole_pair
BinaryBase:
children:
- binary_digits
BinaryDigits:
children:
- literal:
build:
type: string
from: whole_pair
HexadecimalBase:
children:
- hexadecimal_digits
HexadecimalDigits:
children:
- literal:
build:
type: string
from: whole_pair
StringLiteral:
rules:
- SingleQuoteString
- DoubleQuoteString
- BacktickString
SingleQuoteString:
children:
- string_inner:
optional: true
DoubleQuoteString:
children:
- inners:
rule: DStringInner
vec: true
- expressions:
rule: DStringExpression
vec: true
StringInner:
children:
- literal:
build:
type: string
from: whole_pair
DStringInner:
children:
- literal:
build:
type: string
from: whole_pair
DStringExpression:
children:
- expression
BacktickString:
children:
- inners:
rule: BacktickInner
vec: true
- expressions:
rule: DStringExpression
vec: true
BacktickInner:
children:
- literal:
build:
type: string
from: whole_pair
BooleanLiteral:
children:
- literal:
build:
type: boolean
from: parse_whole_pair

View File

@ -30,10 +30,6 @@ Alias = { "alias" }
True = { "true" } True = { "true" }
False = { "false" } False = { "false" }
Use = { "use" } Use = { "use" }
Then = { "then" }
Do = { "do" }
End = { "end" }
Companion = { "comp" }
// Keywords: primitive types // Keywords: primitive types
Byte = { "Byte" } Byte = { "Byte" }
@ -81,10 +77,6 @@ Keyword = {
| True | True
| False | False
| Use | Use
| Then
| Do
| End
| Companion
| Byte | Byte
| Short | Short
| Char | Char
@ -330,31 +322,22 @@ RefList = {
CompilationUnit = { CompilationUnit = {
SOI SOI
~ ParentMod? ~ ( Namespace ~ Semicolon )?
~ ( UseStatement | ModuleLevelDeclaration )* ~ ( UseStatement ~ Semicolon )*
~ ModuleLevelDeclaration*
~ EOI ~ EOI
} }
ParentMod = { Namespace = {
Mod Ns
~ FullyQualifiedName ~ FullyQualifiedName
} }
UseStatement = { UseStatement = {
Use Use
~ UseStatementPrefix* ~ Identifier
~ UseStatementSuffix ~ ( "::" ~ Identifier )*
} ~ ( "::" ~ ( Star | UseList ) )?
UseStatementPrefix = {
Identifier
~ "::"
}
UseStatementSuffix = {
Identifier
| Star
| UseList
} }
UseList = { UseList = {
@ -370,12 +353,12 @@ ModuleLevelDeclaration = {
Module Module
| Interface | Interface
| Class | Class
| Function | FunctionDefinition
| PlatformFunction | PlatformFunction
} }
InterfaceLevelDeclaration = { InterfaceLevelDeclaration = {
CompanionModule Module
| Interface | Interface
| Class | Class
| InterfaceFunction | InterfaceFunction
@ -385,12 +368,14 @@ InterfaceLevelDeclaration = {
} }
ClassLevelDeclaration = { ClassLevelDeclaration = {
CompanionModule Module
| Interface | Interface
| Class | Class
| Function | FunctionDefinition
| OperatorFunction | OperatorFunctionDefinition
| PlatformFunction | PlatformFunction
| Property
| Field
} }
// Main organizational constructs // Main organizational constructs
@ -399,15 +384,7 @@ Module = {
Pub? Pub?
~ Mod ~ Mod
~ Identifier ~ Identifier
~ ModuleLevelDeclaration* ~ "{" ~ ModuleLevelDeclaration* ~ "}"
~ End
}
CompanionModule = {
Companion
~ Mod
~ ModuleLevelDeclaration*
~ End
} }
Interface = { Interface = {
@ -416,8 +393,7 @@ Interface = {
~ Identifier ~ Identifier
~ GenericParameters? ~ GenericParameters?
~ ImplementsList? ~ ImplementsList?
~ InterfaceLevelDeclaration* ~ ( "{" ~ InterfaceLevelDeclaration* ~ "}" )?
~ End
} }
Class = { Class = {
@ -427,14 +403,14 @@ Class = {
~ GenericParameters? ~ GenericParameters?
~ ClassConstructor? ~ ClassConstructor?
~ ImplementsList? ~ ImplementsList?
~ ClassLevelDeclaration* ~ ( "{" ~ ClassLevelDeclaration* ~ "}" )?
~ End
} }
// Function constructs // Function constructs
Function = { FunctionDefinition = {
Pub? Pub?
~ FunctionModifier?
~ Fn ~ Fn
~ GenericParameters? ~ GenericParameters?
~ Identifier ~ Identifier
@ -443,8 +419,9 @@ Function = {
~ FunctionBody ~ FunctionBody
} }
OperatorFunction = { OperatorFunctionDefinition = {
Pub? Pub?
~ FunctionModifier?
~ Op ~ Op
~ GenericParameters? ~ GenericParameters?
~ Operator ~ Operator
@ -455,16 +432,19 @@ OperatorFunction = {
PlatformFunction = { PlatformFunction = {
Pub? Pub?
~ FunctionModifier?
~ Platform ~ Platform
~ Fn ~ Fn
~ GenericParameters? ~ GenericParameters?
~ Identifier ~ Identifier
~ Parameters ~ Parameters
~ ReturnType ~ ReturnType
~ ";"
} }
InterfaceFunction = { InterfaceFunction = {
Fn FunctionModifier?
~ Fn
~ GenericParameters? ~ GenericParameters?
~ Identifier ~ Identifier
~ Parameters ~ Parameters
@ -473,16 +453,18 @@ InterfaceFunction = {
InterfaceDefaultFunction = { InterfaceDefaultFunction = {
Def Def
~ FunctionModifier?
~ Fn ~ Fn
~ GenericParameters? ~ GenericParameters?
~ Identifier ~ Identifier
~ Parameters ~ Parameters
~ ReturnType? ~ ReturnType
~ FunctionBody ~ FunctionBody
} }
InterfaceOperatorFunction = { InterfaceOperatorFunction = {
Op FunctionModifier?
~ Op
~ GenericParameters? ~ GenericParameters?
~ Operator ~ Operator
~ Parameters ~ Parameters
@ -491,20 +473,27 @@ InterfaceOperatorFunction = {
InterfaceDefaultOperatorFunction = { InterfaceDefaultOperatorFunction = {
Def Def
~ FunctionModifier?
~ Op ~ Op
~ GenericParameters? ~ GenericParameters?
~ Operator ~ Operator
~ Parameters ~ Parameters
~ ReturnType? ~ ReturnType
~ FunctionBody ~ FunctionBody
} }
// Function Components FunctionModifier = {
Static
| Cons
| Mut ~ Ref
| Mut
| Ref
}
FunctionBody = { FunctionBody = {
FunctionAliasBody FunctionAliasBody
| FunctionEqualsBody | FunctionEqualsBody
| FunctionBlockBody | BlockStatement
} }
FunctionEqualsBody = { FunctionEqualsBody = {
@ -517,23 +506,30 @@ FunctionAliasBody = {
~ Identifier ~ Identifier
} }
FunctionBlockBody = {
Statement*
~ End
}
// Class constructs // Class constructs
ClassConstructor = { ClassConstructor = {
"(" "("
~ Member ~ DataMember
~ ( "," ~ Member )* ~ ( "," ~ DataMember )*
~ ")" ~ ")"
} }
Member = { DataMember = {
Pub? Property
~ Mut? | Field
}
Property = {
Mut?
~ Identifier
~ ":"
~ TypeUse
}
Field = {
Mut?
~ Fld
~ Identifier ~ Identifier
~ ":" ~ ":"
~ TypeUse ~ TypeUse
@ -541,14 +537,29 @@ Member = {
// Statements // Statements
BlockStatement = {
"{"
~ Statement*
~ Expression?
~ "}"
}
Statement = { Statement = {
VariableDeclaration (
| AssignmentStatement VariableDeclaration
| ExpressionStatement | AssignmentStatement
| UseStatement | CallStatement
| IfStatement | ReturnStatement
| WhileStatement | UseStatement
| ForStatement )
~ Semicolon
| (
BlockStatement
| IfElseStatement
| IfStatement
| WhileStatement
| ForStatement
)
} }
VariableDeclaration = { VariableDeclaration = {
@ -565,50 +576,63 @@ AssignmentStatement = {
~ Expression ~ Expression
} }
ExpressionStatement = { CallStatement = {
Expression PrimaryExpression
~ ObjectAccess?
~ ParenthesesCall
~ (
ObjectAccess
| ParenthesesCall
| PlusPlus
| MinusMinus
)*
}
ReturnStatement = {
Return
~ Expression?
} }
IfStatement = { IfStatement = {
IfClause
~ IfElseIf*
~ IfElse?
~ End
}
IfClause = {
If If
~ "("
~ Expression ~ Expression
~ Then ~ ")"
~ Statement* ~ BlockStatement
} }
IfElseIf = { IfElseStatement = {
Else IfStatement
~ IfClause ~ ElseIf*
~ ElseBlock?
} }
IfElse = { ElseIf = {
Else Else
~ Statement* ~ IfStatement
}
ElseBlock = {
Else
~ BlockStatement
} }
WhileStatement = { WhileStatement = {
While While
~ "("
~ Expression ~ Expression
~ Do ~ ")"
~ Statement* ~ BlockStatement
~ End
} }
ForStatement = { ForStatement = {
For For
~ "("
~ Identifier ~ Identifier
~ In ~ In
~ Expression ~ Expression
~ Do ~ ")"
~ Statement* ~ BlockStatement
~ End
} }
// Expressions // Expressions
@ -619,22 +643,12 @@ Expression = {
TernaryExpression = { TernaryExpression = {
OrExpression OrExpression
~ ( TernaryAlternatives )? ~ (
} "?"
~ Expression
TernaryAlternatives = { ~ ":"
TernaryTrueAlternative ~ Expression
~ TernaryFalseAlternative )?
}
TernaryTrueAlternative = {
"?"
~ Expression
}
TernaryFalseAlternative = {
":"
~ Expression
} }
OrExpression = { OrExpression = {
@ -650,93 +664,52 @@ AndExpression = {
ComparisonExpression = { ComparisonExpression = {
ShiftExpression ShiftExpression
~ ( ~ (
ComparisonOperator ( Greater | Less | GreaterEqual | LessEqual | EqualTo | NotEqualTo )
~ Expression ~ Expression
)? )?
} }
ComparisonOperator = {
Greater
| Less
| GreaterEqual
| LessEqual
| EqualTo
| NotEqualTo
}
ShiftExpression = { ShiftExpression = {
AdditiveExpression AdditiveExpression
~ ( ~ ( ( LeftShift | RightShift ) ~ Expression )?
ShiftOperator
~ Expression
)?
}
ShiftOperator = {
LeftShift
| RightShift
} }
AdditiveExpression = { AdditiveExpression = {
MultiplicativeExpression MultiplicativeExpression
~ ( ~ (
AdditiveOperator ( Add | Subtract )
~ Expression ~ Expression
)? )?
} }
AdditiveOperator = {
Add
| Subtract
}
MultiplicativeExpression = { MultiplicativeExpression = {
PrefixExpression PrefixExpression
~ ( ~ (
MultiplicativeOperator ( Multiply | Divide | Modulo )
~ Expression ~ Expression
)? )?
} }
MultiplicativeOperator = {
Multiply
| Divide
| Modulo
}
PrefixExpression = { PrefixExpression = {
PrefixOperator* (
Spread
| BorrowMut
| Borrow
| Mut
| Not
| Negative
)*
~ SuffixExpression ~ SuffixExpression
} }
PrefixOperator = {
Spread
| Not
| Negative
}
SuffixExpression = { SuffixExpression = {
PrimaryExpression PrimaryExpression
~ SuffixOperator* ~ (
} ObjectAccess
| ParenthesesCall
SuffixOperator = { | PlusPlus
PlusPlus | MinusMinus
| MinusMinus )*
| ObjectProperty
| ObjectIndex
| Call
}
ObjectProperty = {
"."
~ Identifier
}
ObjectIndex = {
"["
~ Expression
~ "]"
} }
PrimaryExpression = { PrimaryExpression = {
@ -752,13 +725,23 @@ ParenthesizedExpression = {
~ ")" ~ ")"
} }
// Calls ObjectAccess = {
( ObjectProperty | ObjectIndex )+
Call = {
ParenthesesCall
| NonParenthesesCall
} }
ObjectProperty = {
"."
~ Identifier
}
ObjectIndex = {
"["
~ Expression
~ "]"
}
// Calls
ParenthesesCall = { ParenthesesCall = {
TurboFish? TurboFish?
~ "(" ~ "("
@ -767,15 +750,6 @@ ParenthesesCall = {
~ Closure? ~ Closure?
} }
NonParenthesesCall = {
TurboFish?
~ (
Closure
| ExpressionList
| ExpressionList ~ Closure
)
}
TurboFish = { TurboFish = {
"::" "::"
~ GenericArguments ~ GenericArguments
@ -789,9 +763,13 @@ ExpressionList = {
// Closure // Closure
Closure = { Closure = {
"{" ( Cons | Mut )?
~ Move?
~ ClosureCaptures?
~ "{"
~ ( ClosureParameters? ~ "->" )? ~ ( ClosureParameters? ~ "->" )?
~ Statement* ~ Statement*
~ Expression?
~ "}" ~ "}"
} }
@ -805,6 +783,19 @@ ClosureParameter = {
~ ( ":" ~ TypeUse )? ~ ( ":" ~ TypeUse )?
} }
ClosureCaptures = {
"|"
~ ClosureCapture
~ ( "," ~ ClosureCapture )*
~ "|"
}
ClosureCapture = {
Borrow*
~ Mut?
~ Identifier
}
// Literals // Literals
Literal = { Literal = {
@ -823,7 +814,7 @@ IntLiteral = { NumberBase }
LongLiteral = ${ NumberBase ~ "L" } LongLiteral = ${ NumberBase ~ "L" }
DoubleLiteral = @{ DecimalBase ~ "." ~ DecimalBase} DoubleLiteral = ${ DecimalBase ~ "." ~ Digit+ }
NumberBase = { NumberBase = {
BinaryBase BinaryBase
@ -831,17 +822,18 @@ NumberBase = {
| DecimalBase | DecimalBase
} }
DecimalBase = @{ '0'..'9'+ } DecimalBase = @{
"0"
| DecimalStartDigit ~ Digit*
}
BinaryBase = { "0b" ~ BinaryDigits } BinaryBase = @{ "0b" ~ Digit+ }
BinaryDigits = @{ BinaryDigit+ } DecimalStartDigit = { '1'..'9' }
BinaryDigit = { "0" | "1" } Digit = @{ '0'..'9'+ }
HexadecimalBase = { "0x" ~ HexadecimalDigits } HexadecimalBase = @{ "0x" ~ HexadecimalDigit+ }
HexadecimalDigits = @{ HexadecimalDigit+ }
HexadecimalDigit = { '0'..'9' | 'a'..'f' } HexadecimalDigit = { '0'..'9' | 'a'..'f' }
@ -873,7 +865,7 @@ DStringInner = @{ DStringChar+ }
DStringChar = { DStringChar = {
!( "\"" | "\\" | "${" ) ~ ANY !( "\"" | "\\" | "${" ) ~ ANY
| "\\" ~ ( "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" | "$" ) | "\\" ~ ( "\"" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" | "$" )
| "\\" ~ "u" ~ ASCII_HEX_DIGIT{4} | "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} )
} }
DStringExpression = { DStringExpression = {
@ -892,9 +884,9 @@ BacktickString = {
BacktickInner = @{ BacktickStringChar+ } BacktickInner = @{ BacktickStringChar+ }
BacktickStringChar = { BacktickStringChar = {
!( "`" | "\\" | "${" ) ~ ANY !( "\\`" | "\\" | "${" ) ~ ANY
| "\\" ~ ( "`" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" | "$" ) | "\\" ~ ( "`" | "\\" | "/" | "b" | "f" | "n" | "r" | "t" | "$" )
| "\\" ~ "u" ~ ASCII_HEX_DIGIT{4} | "\\" ~ ( "u" ~ ASCII_HEX_DIGIT{4} )
} }
BooleanLiteral = { True | False } BooleanLiteral = { True | False }