Compare commits
3 Commits
8b310ad5d4
...
e79c22db72
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e79c22db72 | ||
![]() |
3ca488b76d | ||
![]() |
673a008e16 |
@ -15,7 +15,7 @@ fn get_vec(vec: &Yaml) -> bool {
|
|||||||
vec.as_bool().unwrap_or_else(|| false)
|
vec.as_bool().unwrap_or_else(|| false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_vec_child_to_build(build: &Yaml, rule: &str) -> VecChildToBuild {
|
fn get_vec_child_to_build(build: &Yaml, name: &str, rule: &str) -> VecChildToBuild {
|
||||||
if build.is_hash() {
|
if build.is_hash() {
|
||||||
let build_type = build["build"].as_str().unwrap();
|
let build_type = build["build"].as_str().unwrap();
|
||||||
let var_name = build["var"]
|
let var_name = build["var"]
|
||||||
@ -32,7 +32,7 @@ fn get_vec_child_to_build(build: &Yaml, rule: &str) -> VecChildToBuild {
|
|||||||
let build_as_str = build.as_str().unwrap_or(rule);
|
let build_as_str = build.as_str().unwrap_or(rule);
|
||||||
VecChildToBuild::Type(VecTypeChildToBuild::new(
|
VecChildToBuild::Type(VecTypeChildToBuild::new(
|
||||||
build_as_str,
|
build_as_str,
|
||||||
build_as_str.to_case(Case::Snake).as_str(),
|
name,
|
||||||
make_build_fn_name(build_as_str).as_str(),
|
make_build_fn_name(build_as_str).as_str(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ fn get_vec_child(name: &str, rule: &str, build: &Yaml) -> ChildSpec {
|
|||||||
ChildSpec::VecChild(VecChild::new(
|
ChildSpec::VecChild(VecChild::new(
|
||||||
name,
|
name,
|
||||||
rule,
|
rule,
|
||||||
get_vec_child_to_build(build, rule),
|
get_vec_child_to_build(build, name, rule),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,10 +86,11 @@ fn get_child_specs(children: &Yaml) -> Vec<ChildSpec> {
|
|||||||
.map(|child_spec| {
|
.map(|child_spec| {
|
||||||
if child_spec.is_hash() {
|
if child_spec.is_hash() {
|
||||||
let as_hash = child_spec.as_hash().unwrap();
|
let as_hash = child_spec.as_hash().unwrap();
|
||||||
let only_pair = as_hash.iter().next().unwrap();
|
let (name, props) = as_hash
|
||||||
|
.iter()
|
||||||
let name = only_pair.0.as_str().unwrap();
|
.next()
|
||||||
let props = only_pair.1;
|
.map(|(name, props)| (name.as_str().unwrap(), props))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let rule = props["rule"].as_str().unwrap();
|
let rule = props["rule"].as_str().unwrap();
|
||||||
|
|
||||||
|
@ -31,20 +31,25 @@ fn handle_vec_child(
|
|||||||
annotated_members: &mut Vec<TokenStream>,
|
annotated_members: &mut Vec<TokenStream>,
|
||||||
accessors: &mut Vec<TokenStream>,
|
accessors: &mut Vec<TokenStream>,
|
||||||
) {
|
) {
|
||||||
let (child_ident, child_type_ident) = match vec_child.build() {
|
let (child_ident, child_ident_mut, child_type_ident) = match vec_child.build() {
|
||||||
VecChildToBuild::Type(vec_type_child) => (
|
VecChildToBuild::Type(vec_type_child) => (
|
||||||
format_ident!("{}", vec_type_child.var_name()),
|
format_ident!("{}", vec_type_child.var_name()),
|
||||||
|
format_ident!("{}_mut", vec_type_child.var_name()),
|
||||||
format_ident!("{}", vec_type_child.build()),
|
format_ident!("{}", vec_type_child.build()),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
member_names.push(child_ident.clone());
|
member_names.push(child_ident.clone());
|
||||||
annotated_members.push(quote! {
|
annotated_members.push(quote! {
|
||||||
#child_ident: Vec<#child_type_ident>
|
#child_ident: Vec<Box<#child_type_ident>>
|
||||||
});
|
});
|
||||||
accessors.push(quote! {
|
accessors.push(quote! {
|
||||||
pub fn #child_ident(&self) -> &[#child_type_ident] {
|
pub fn #child_ident(&self) -> impl Iterator<Item = &#child_type_ident> {
|
||||||
&self.#child_ident
|
self.#child_ident.iter().map(Box::as_ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn #child_ident_mut(&mut self) -> impl Iterator<Item = &mut #child_type_ident> {
|
||||||
|
self.#child_ident.iter_mut().map(Box::as_mut)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -56,14 +61,19 @@ fn handle_single_type_child(
|
|||||||
accessors: &mut Vec<TokenStream>,
|
accessors: &mut Vec<TokenStream>,
|
||||||
) {
|
) {
|
||||||
let child_ident = format_ident!("{}", single_type_child.var_name());
|
let child_ident = format_ident!("{}", 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());
|
||||||
annotated_members.push(quote! {
|
annotated_members.push(quote! {
|
||||||
#child_ident: #child_type_ident
|
#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
|
self.#child_ident.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn #child_ident_mut(&mut self) -> &mut #child_type_ident {
|
||||||
|
self.#child_ident.as_mut()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
123
src/parser/ast.schema.yaml
Normal file
123
src/parser/ast.schema.yaml
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
$schema: https://json-schema.org/draft/2020-12/schema
|
||||||
|
title: Deimos AST generation spec
|
||||||
|
type: object
|
||||||
|
description: Top level is a map of node names in Pascal case (e.g., CompilationUnit) to node definitions.
|
||||||
|
additionalProperties:
|
||||||
|
$ref: "#/$defs/NodeDefinition"
|
||||||
|
$defs:
|
||||||
|
NodeDefinition:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: A definition of a node type.
|
||||||
|
properties:
|
||||||
|
children:
|
||||||
|
type: array
|
||||||
|
description: Ordered child fields for this node.
|
||||||
|
items:
|
||||||
|
$ref: "#/$defs/StructChildDefinition"
|
||||||
|
rules:
|
||||||
|
type: array
|
||||||
|
description: Alternative parse rules that build this node.
|
||||||
|
items:
|
||||||
|
$ref: "#/$defs/EnumChildDefinition"
|
||||||
|
oneOf:
|
||||||
|
- required:
|
||||||
|
- "children"
|
||||||
|
- required:
|
||||||
|
- "rules"
|
||||||
|
StructChildDefinition:
|
||||||
|
description: A definition of a node's child. Either a bare child name (string) in snake case, or an object.
|
||||||
|
oneOf:
|
||||||
|
- type: string
|
||||||
|
description: Shorthand where child name, var, build, and with are inferred from the given snake-case child name.
|
||||||
|
- $ref: "#/$defs/ChildDefinitionWrapper"
|
||||||
|
ChildDefinitionWrapper:
|
||||||
|
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/ChildDefinition"
|
||||||
|
ChildDefinition:
|
||||||
|
type: object
|
||||||
|
description: One of skip/vec/single child specs.
|
||||||
|
oneOf:
|
||||||
|
- $ref: "#/$defs/SkipChildDefinition"
|
||||||
|
- $ref: "#/$defs/VecChildDefinition"
|
||||||
|
- $ref: "#/$defs/SingleChildDefinition"
|
||||||
|
SkipChildDefinition:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: A definition for a child rule that does nothing, i.e., is skipped.
|
||||||
|
properties:
|
||||||
|
rule:
|
||||||
|
type: string
|
||||||
|
skip:
|
||||||
|
type: boolean # note: must be true
|
||||||
|
required:
|
||||||
|
- rule
|
||||||
|
- skip
|
||||||
|
VecChildDefinition:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: A definition for a child rule that can be matched multiple times.
|
||||||
|
properties:
|
||||||
|
rule:
|
||||||
|
type: string
|
||||||
|
vec:
|
||||||
|
type: boolean
|
||||||
|
required:
|
||||||
|
- rule
|
||||||
|
- vec
|
||||||
|
SingleChildDefinition:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: A definition for a child rule that builds one item.
|
||||||
|
properties:
|
||||||
|
rule:
|
||||||
|
type: string
|
||||||
|
build:
|
||||||
|
oneOf:
|
||||||
|
- type: string
|
||||||
|
- $ref: "#/$defs/SingleChildBuildDefinition"
|
||||||
|
required:
|
||||||
|
- rule
|
||||||
|
SingleChildBuildDefinition:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: A definition of what exactly to build for a given child rule.
|
||||||
|
oneOf:
|
||||||
|
- $ref: "#/$defs/BuildBooleanChild"
|
||||||
|
BuildBooleanChild:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: A definition for building a boolean child.
|
||||||
|
properties:
|
||||||
|
type:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- boolean
|
||||||
|
on:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- rule_present
|
||||||
|
EnumChildDefinition:
|
||||||
|
description: A definition of an enum node's child. Either a bare rule (string) in Pascal case, or an object.
|
||||||
|
oneOf:
|
||||||
|
- type: string
|
||||||
|
description: Shorthand where child name, var, build, and with are inferred from the given Pascal-case rule name.
|
||||||
|
- $ref: "#/$defs/LongEnumChildDefinition"
|
||||||
|
LongEnumChildDefinition:
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
description: A format for specifying more specific information for an enum child.
|
||||||
|
properties:
|
||||||
|
rule:
|
||||||
|
type: string
|
||||||
|
build:
|
||||||
|
type: string
|
||||||
|
required:
|
||||||
|
- rule
|
||||||
|
- build
|
@ -1,3 +1,4 @@
|
|||||||
|
# $schema: ./ast.schema.yaml
|
||||||
CompilationUnit:
|
CompilationUnit:
|
||||||
children:
|
children:
|
||||||
- namespace
|
- namespace
|
||||||
@ -29,6 +30,8 @@ ModuleLevelDeclaration:
|
|||||||
build: ModuleDeclaration
|
build: ModuleDeclaration
|
||||||
- rule: Interface
|
- rule: Interface
|
||||||
build: InterfaceDeclaration
|
build: InterfaceDeclaration
|
||||||
|
- rule: Class
|
||||||
|
build: ClassDeclaration
|
||||||
- FunctionDefinition
|
- FunctionDefinition
|
||||||
- PlatformFunction
|
- PlatformFunction
|
||||||
ModuleDeclaration:
|
ModuleDeclaration:
|
||||||
@ -46,7 +49,7 @@ ModuleDeclaration:
|
|||||||
- declarations:
|
- declarations:
|
||||||
rule: ModuleLevelDeclaration
|
rule: ModuleLevelDeclaration
|
||||||
vec: true
|
vec: true
|
||||||
Class:
|
ClassDeclaration:
|
||||||
children:
|
children:
|
||||||
- is_public:
|
- is_public:
|
||||||
rule: Pub
|
rule: Pub
|
||||||
@ -63,3 +66,22 @@ Class:
|
|||||||
- class_level_declarations:
|
- class_level_declarations:
|
||||||
rule: ClassLevelDeclaration
|
rule: ClassLevelDeclaration
|
||||||
vec: true
|
vec: true
|
||||||
|
FunctionDeclaration:
|
||||||
|
children:
|
||||||
|
- is_public:
|
||||||
|
rule: Pub
|
||||||
|
build:
|
||||||
|
type: boolean
|
||||||
|
on: rule_present
|
||||||
|
- modifier:
|
||||||
|
rule: Modifier
|
||||||
|
build: FunctionModifier
|
||||||
|
- fn_kw:
|
||||||
|
rule: Fn
|
||||||
|
skip: true
|
||||||
|
- generics:
|
||||||
|
rule: GenericParameters
|
||||||
|
- identifier
|
||||||
|
- parameters
|
||||||
|
- return_type
|
||||||
|
- function_body
|
||||||
|
Loading…
Reference in New Issue
Block a user