Added bindings
This commit is contained in:
parent
7a2c19af66
commit
b814c57355
18 changed files with 370 additions and 264 deletions
|
@ -544,8 +544,7 @@ impl RegexRule for CodeRule {
|
|||
reports
|
||||
}
|
||||
|
||||
// TODO
|
||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> {
|
||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> {
|
||||
let mut bindings = vec![];
|
||||
bindings.push((
|
||||
"push_inline".to_string(),
|
||||
|
@ -647,7 +646,7 @@ impl RegexRule for CodeRule {
|
|||
.unwrap(),
|
||||
));
|
||||
|
||||
bindings
|
||||
Some(bindings)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,5 +80,5 @@ impl RegexRule for CommentRule {
|
|||
return reports;
|
||||
}
|
||||
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] }
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
||||
}
|
||||
|
|
|
@ -371,5 +371,5 @@ impl RegexRule for GraphRule {
|
|||
}
|
||||
|
||||
// TODO
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] }
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
||||
}
|
||||
|
|
|
@ -178,5 +178,5 @@ impl RegexRule for ImportRule {
|
|||
return result;
|
||||
}
|
||||
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] }
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
||||
}
|
||||
|
|
|
@ -171,5 +171,5 @@ impl RegexRule for LinkRule {
|
|||
}
|
||||
|
||||
// TODO
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] }
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
||||
}
|
||||
|
|
|
@ -337,5 +337,5 @@ impl Rule for ListRule
|
|||
}
|
||||
|
||||
// TODO
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] }
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
||||
}
|
||||
|
|
|
@ -7,6 +7,8 @@ use ariadne::Fmt;
|
|||
use ariadne::Label;
|
||||
use ariadne::Report;
|
||||
use ariadne::ReportKind;
|
||||
use mlua::Function;
|
||||
use mlua::Lua;
|
||||
use regex::Captures;
|
||||
use regex::Match;
|
||||
use regex::Regex;
|
||||
|
@ -518,9 +520,7 @@ impl RegexRule for MediaRule {
|
|||
reports
|
||||
}
|
||||
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua mlua::Lua) -> Vec<(String, mlua::Function<'lua>)> {
|
||||
vec![]
|
||||
}
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -150,5 +150,5 @@ impl Rule for ParagraphRule {
|
|||
}
|
||||
|
||||
// TODO
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] }
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
||||
}
|
||||
|
|
|
@ -231,7 +231,7 @@ impl RegexRule for RawRule {
|
|||
reports
|
||||
}
|
||||
|
||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> {
|
||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> {
|
||||
let mut bindings = vec![];
|
||||
|
||||
bindings.push((
|
||||
|
@ -270,7 +270,7 @@ impl RegexRule for RawRule {
|
|||
.unwrap(),
|
||||
));
|
||||
|
||||
bindings
|
||||
Some(bindings)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ use ariadne::Fmt;
|
|||
use ariadne::Label;
|
||||
use ariadne::Report;
|
||||
use ariadne::ReportKind;
|
||||
use mlua::Function;
|
||||
use mlua::Lua;
|
||||
use regex::Captures;
|
||||
use regex::Match;
|
||||
use regex::Regex;
|
||||
|
@ -205,7 +207,5 @@ impl RegexRule for ReferenceRule {
|
|||
reports
|
||||
}
|
||||
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua mlua::Lua) -> Vec<(String, mlua::Function<'lua>)> {
|
||||
vec![]
|
||||
}
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
||||
}
|
||||
|
|
|
@ -275,5 +275,5 @@ impl RegexRule for ScriptRule {
|
|||
}
|
||||
|
||||
// TODO
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] }
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
||||
}
|
||||
|
|
|
@ -235,7 +235,7 @@ impl RegexRule for SectionRule {
|
|||
return result;
|
||||
}
|
||||
|
||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> {
|
||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> {
|
||||
let mut bindings = vec![];
|
||||
|
||||
bindings.push((
|
||||
|
@ -280,6 +280,6 @@ impl RegexRule for SectionRule {
|
|||
.unwrap(),
|
||||
));
|
||||
|
||||
bindings
|
||||
Some(bindings)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,5 +183,5 @@ impl RegexRule for StyleRule
|
|||
}
|
||||
|
||||
// TODO
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] }
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
||||
}
|
||||
|
|
|
@ -430,7 +430,7 @@ impl RegexRule for TexRule {
|
|||
}
|
||||
|
||||
// TODO
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] }
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -61,7 +61,7 @@ impl Rule for TextRule {
|
|||
panic!("Text cannot match");
|
||||
}
|
||||
|
||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> {
|
||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> {
|
||||
let mut bindings = vec![];
|
||||
bindings.push((
|
||||
"push".to_string(),
|
||||
|
@ -83,6 +83,6 @@ impl Rule for TextRule {
|
|||
.unwrap(),
|
||||
));
|
||||
|
||||
bindings
|
||||
Some(bindings)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,41 @@
|
|||
use mlua::{Function, Lua};
|
||||
use crate::document::document::Document;
|
||||
use crate::document::variable::BaseVariable;
|
||||
use crate::document::variable::PathVariable;
|
||||
use crate::document::variable::Variable;
|
||||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::parser::Parser;
|
||||
use crate::parser::parser::ReportColors;
|
||||
use crate::parser::rule::RegexRule;
|
||||
use crate::parser::source::Source;
|
||||
use crate::parser::source::Token;
|
||||
use ariadne::Fmt;
|
||||
use ariadne::Label;
|
||||
use ariadne::Report;
|
||||
use ariadne::ReportKind;
|
||||
use mlua::Function;
|
||||
use mlua::Lua;
|
||||
use regex::Regex;
|
||||
use crate::{document::document::Document, parser::{parser::{Parser, ReportColors}, rule::RegexRule, source::{Source, Token}}};
|
||||
use ariadne::{Report, Fmt, Label, ReportKind};
|
||||
use crate::document::variable::{BaseVariable, PathVariable, Variable};
|
||||
use std::{ops::Range, rc::Rc};
|
||||
use std::ops::Range;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum VariableKind {
|
||||
Regular,
|
||||
Path,
|
||||
}
|
||||
|
||||
impl FromStr for VariableKind {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"regular" | "" => Ok(VariableKind::Regular),
|
||||
"path" | "'" => Ok(VariableKind::Path),
|
||||
_ => Err(format!("Uknnown variable kind: `{s}`")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VariableRule {
|
||||
re: [Regex; 1],
|
||||
|
@ -14,20 +46,20 @@ impl VariableRule {
|
|||
pub fn new() -> Self {
|
||||
Self {
|
||||
re: [Regex::new(r"(?:^|\n)@([^[:alpha:]])?(.*?)=((?:\\\n|.)*)").unwrap()],
|
||||
kinds: vec![
|
||||
("".into(), "Regular".into()),
|
||||
("'".into(), "Path".into())
|
||||
]
|
||||
kinds: vec![("".into(), "Regular".into()), ("'".into(), "Path".into())],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_variable(&self, colors: &ReportColors, location: Token, kind: usize, name: String, value: String) -> Result<Rc<dyn Variable>, String>
|
||||
{
|
||||
match self.kinds[kind].0.as_str()
|
||||
{
|
||||
"" => {
|
||||
Ok(Rc::new(BaseVariable::new(location, name, value)))
|
||||
}
|
||||
pub fn make_variable(
|
||||
&self,
|
||||
colors: &ReportColors,
|
||||
location: Token,
|
||||
kind: usize,
|
||||
name: String,
|
||||
value: String,
|
||||
) -> Result<Rc<dyn Variable>, String> {
|
||||
match self.kinds[kind].0.as_str() {
|
||||
"" => Ok(Rc::new(BaseVariable::new(location, name, value))),
|
||||
"'" => {
|
||||
match std::fs::canonicalize(value.as_str()) // TODO: not canonicalize
|
||||
{
|
||||
|
@ -37,42 +69,41 @@ impl VariableRule {
|
|||
e.to_string()))
|
||||
}
|
||||
}
|
||||
_ => panic!("Unhandled variable kind")
|
||||
_ => panic!("Unhandled variable kind"),
|
||||
}
|
||||
}
|
||||
|
||||
// Trim and check variable name for validity
|
||||
pub fn validate_name<'a>(colors: &ReportColors, original_name: &'a str) -> Result<&'a str, String>
|
||||
{
|
||||
pub fn validate_name<'a>(
|
||||
colors: &ReportColors,
|
||||
original_name: &'a str,
|
||||
) -> Result<&'a str, String> {
|
||||
let name = original_name.trim_start().trim_end();
|
||||
if name.contains("%")
|
||||
{
|
||||
return Err(format!("Name cannot contain '{}'",
|
||||
"%".fg(colors.info)));
|
||||
if name.contains("%") {
|
||||
return Err(format!("Name cannot contain '{}'", "%".fg(colors.info)));
|
||||
}
|
||||
return Ok(name);
|
||||
}
|
||||
|
||||
pub fn validate_value(_colors: &ReportColors, original_value: &str) -> Result<String, String>
|
||||
{
|
||||
pub fn validate_value(_colors: &ReportColors, original_value: &str) -> Result<String, String> {
|
||||
let mut escaped = 0usize;
|
||||
let mut result = String::new();
|
||||
for c in original_value.trim_start().trim_end().chars() {
|
||||
if c == '\\' { escaped += 1 }
|
||||
else if c == '\n' {
|
||||
if c == '\\' {
|
||||
escaped += 1
|
||||
} else if c == '\n' {
|
||||
match escaped {
|
||||
0 => return Err("Unknown error wile capturing variable".to_string()),
|
||||
// Remove '\n'
|
||||
1 => {},
|
||||
1 => {}
|
||||
// Insert '\n'
|
||||
_ => {
|
||||
result.push(c);
|
||||
(0..escaped-2).for_each(|_| result.push('\\'));
|
||||
(0..escaped - 2).for_each(|_| result.push('\\'));
|
||||
}
|
||||
}
|
||||
escaped = 0;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
(0..escaped).for_each(|_| result.push('\\'));
|
||||
escaped = 0;
|
||||
result.push(c);
|
||||
|
@ -89,35 +120,54 @@ impl RegexRule for VariableRule {
|
|||
|
||||
fn regexes(&self) -> &[Regex] { &self.re }
|
||||
|
||||
fn on_regex_match<'a>(&self, _: usize, parser: &dyn Parser, document: &'a dyn Document, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>
|
||||
{
|
||||
fn on_regex_match<'a>(
|
||||
&self,
|
||||
_: usize,
|
||||
parser: &dyn Parser,
|
||||
document: &'a dyn Document,
|
||||
token: Token,
|
||||
matches: regex::Captures,
|
||||
) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
||||
let mut result = vec![];
|
||||
// [Optional] variable kind
|
||||
let var_kind = match matches.get(1)
|
||||
{
|
||||
let var_kind = match matches.get(1) {
|
||||
Some(kind) => {
|
||||
// Find kind
|
||||
let r = self.kinds.iter().enumerate().find(|(_i, (ref char, ref _name))| {
|
||||
char == kind.as_str() });
|
||||
let r = self
|
||||
.kinds
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find(|(_i, (ref char, ref _name))| char == kind.as_str());
|
||||
|
||||
// Unknown kind specified
|
||||
if r.is_none()
|
||||
{
|
||||
if r.is_none() {
|
||||
result.push(
|
||||
Report::build(ReportKind::Error, token.source(), kind.start())
|
||||
.with_message("Unknown variable kind")
|
||||
.with_label(
|
||||
Label::new((token.source(), kind.range()))
|
||||
.with_message(format!("Variable kind `{}` is unknown",
|
||||
kind.as_str().fg(parser.colors().highlight)))
|
||||
.with_color(parser.colors().error))
|
||||
.with_help(format!("Leave empty for regular variables. Available variable kinds:{}",
|
||||
self.kinds.iter().skip(1).fold("".to_string(), |acc, (char, name)| {
|
||||
acc + format!("\n - `{}` : {}",
|
||||
.with_message(format!(
|
||||
"Variable kind `{}` is unknown",
|
||||
kind.as_str().fg(parser.colors().highlight)
|
||||
))
|
||||
.with_color(parser.colors().error),
|
||||
)
|
||||
.with_help(format!(
|
||||
"Leave empty for regular variables. Available variable kinds:{}",
|
||||
self.kinds.iter().skip(1).fold(
|
||||
"".to_string(),
|
||||
|acc, (char, name)| {
|
||||
acc + format!(
|
||||
"\n - `{}` : {}",
|
||||
char.fg(parser.colors().highlight),
|
||||
name.fg(parser.colors().info)).as_str()
|
||||
})))
|
||||
.finish());
|
||||
name.fg(parser.colors().info)
|
||||
)
|
||||
.as_str()
|
||||
}
|
||||
)
|
||||
))
|
||||
.finish(),
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -127,11 +177,8 @@ impl RegexRule for VariableRule {
|
|||
None => 0,
|
||||
};
|
||||
|
||||
let var_name = match matches.get(2)
|
||||
{
|
||||
Some(name) => {
|
||||
match VariableRule::validate_name(&parser.colors(), name.as_str())
|
||||
{
|
||||
let var_name = match matches.get(2) {
|
||||
Some(name) => match VariableRule::validate_name(&parser.colors(), name.as_str()) {
|
||||
Ok(var_name) => var_name,
|
||||
Err(msg) => {
|
||||
result.push(
|
||||
|
@ -139,44 +186,52 @@ impl RegexRule for VariableRule {
|
|||
.with_message("Invalid variable name")
|
||||
.with_label(
|
||||
Label::new((token.source(), name.range()))
|
||||
.with_message(format!("Variable name `{}` is not allowed. {msg}",
|
||||
name.as_str().fg(parser.colors().highlight)))
|
||||
.with_color(parser.colors().error))
|
||||
.finish());
|
||||
.with_message(format!(
|
||||
"Variable name `{}` is not allowed. {msg}",
|
||||
name.as_str().fg(parser.colors().highlight)
|
||||
))
|
||||
.with_color(parser.colors().error),
|
||||
)
|
||||
.finish(),
|
||||
);
|
||||
|
||||
return result;
|
||||
},
|
||||
}
|
||||
},
|
||||
_ => panic!("Unknown variable name")
|
||||
_ => panic!("Unknown variable name"),
|
||||
};
|
||||
|
||||
let var_value = match matches.get(3)
|
||||
{
|
||||
Some(value) => {
|
||||
match VariableRule::validate_value(&parser.colors(), value.as_str())
|
||||
{
|
||||
let var_value = match matches.get(3) {
|
||||
Some(value) => match VariableRule::validate_value(&parser.colors(), value.as_str()) {
|
||||
Ok(var_value) => var_value,
|
||||
Err(msg ) => {
|
||||
Err(msg) => {
|
||||
result.push(
|
||||
Report::build(ReportKind::Error, token.source(), value.start())
|
||||
.with_message("Invalid variable value")
|
||||
.with_label(
|
||||
Label::new((token.source(), value.range()))
|
||||
.with_message(format!("Variable value `{}` is not allowed. {msg}",
|
||||
value.as_str().fg(parser.colors().highlight)))
|
||||
.with_color(parser.colors().error))
|
||||
.finish());
|
||||
.with_message(format!(
|
||||
"Variable value `{}` is not allowed. {msg}",
|
||||
value.as_str().fg(parser.colors().highlight)
|
||||
))
|
||||
.with_color(parser.colors().error),
|
||||
)
|
||||
.finish(),
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => panic!("Invalid variable value")
|
||||
},
|
||||
_ => panic!("Invalid variable value"),
|
||||
};
|
||||
|
||||
match self.make_variable(&parser.colors(), token.clone(), var_kind, var_name.to_string(), var_value)
|
||||
{
|
||||
match self.make_variable(
|
||||
&parser.colors(),
|
||||
token.clone(),
|
||||
var_kind,
|
||||
var_name.to_string(),
|
||||
var_value,
|
||||
) {
|
||||
Ok(variable) => document.add_variable(variable),
|
||||
Err(msg) => {
|
||||
let m = matches.get(0).unwrap();
|
||||
|
@ -184,12 +239,16 @@ impl RegexRule for VariableRule {
|
|||
Report::build(ReportKind::Error, token.source(), m.start())
|
||||
.with_message("Unable to create variable")
|
||||
.with_label(
|
||||
Label::new((token.source(), m.start()+1 .. m.end() ))
|
||||
.with_message(format!("Unable to create variable `{}`. {}",
|
||||
Label::new((token.source(), m.start() + 1..m.end()))
|
||||
.with_message(format!(
|
||||
"Unable to create variable `{}`. {}",
|
||||
var_name.fg(parser.colors().highlight),
|
||||
msg))
|
||||
.with_color(parser.colors().error))
|
||||
.finish());
|
||||
msg
|
||||
))
|
||||
.with_color(parser.colors().error),
|
||||
)
|
||||
.finish(),
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -198,12 +257,45 @@ impl RegexRule for VariableRule {
|
|||
return result;
|
||||
}
|
||||
|
||||
// TODO
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] }
|
||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> {
|
||||
let mut bindings = vec![];
|
||||
bindings.push((
|
||||
"insert".to_string(),
|
||||
lua.create_function(|_, (name, value): (String, String)| {
|
||||
CTX.with_borrow(|ctx| {
|
||||
ctx.as_ref().map(|ctx| {
|
||||
let var = Rc::new(BaseVariable::new(ctx.location.clone(), name, value));
|
||||
ctx.document.add_variable(var);
|
||||
})
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.unwrap(),
|
||||
));
|
||||
bindings.push((
|
||||
"get".to_string(),
|
||||
lua.create_function(|_, name: String| {
|
||||
let mut value: Option<String> = None;
|
||||
CTX.with_borrow(|ctx| {
|
||||
ctx.as_ref().map(|ctx| {
|
||||
if let Some(var) = ctx.document.get_variable(name.as_str())
|
||||
{
|
||||
value = Some(var.to_string());
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
Ok(value)
|
||||
})
|
||||
.unwrap(),
|
||||
));
|
||||
|
||||
Some(bindings)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct VariableSubstitutionRule
|
||||
{
|
||||
pub struct VariableSubstitutionRule {
|
||||
re: [Regex; 1],
|
||||
}
|
||||
|
||||
|
@ -215,100 +307,113 @@ impl VariableSubstitutionRule {
|
|||
}
|
||||
}
|
||||
|
||||
impl RegexRule for VariableSubstitutionRule
|
||||
{
|
||||
impl RegexRule for VariableSubstitutionRule {
|
||||
fn name(&self) -> &'static str { "Variable Substitution" }
|
||||
|
||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||
|
||||
fn on_regex_match<'a>(&self, _index: usize, parser: &dyn Parser, document: &'a dyn Document<'a>, token: Token, matches: regex::Captures) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
||||
fn on_regex_match<'a>(
|
||||
&self,
|
||||
_index: usize,
|
||||
parser: &dyn Parser,
|
||||
document: &'a dyn Document<'a>,
|
||||
token: Token,
|
||||
matches: regex::Captures,
|
||||
) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>> {
|
||||
let mut result = vec![];
|
||||
|
||||
let variable = match matches.get(1)
|
||||
{
|
||||
let variable = match matches.get(1) {
|
||||
Some(name) => {
|
||||
// Empty name
|
||||
if name.as_str().is_empty()
|
||||
{
|
||||
if name.as_str().is_empty() {
|
||||
result.push(
|
||||
Report::build(ReportKind::Error, token.source(), name.start())
|
||||
.with_message("Empty variable name")
|
||||
.with_label(
|
||||
Label::new((token.source(), matches.get(0).unwrap().range()))
|
||||
.with_message(format!("Missing variable name for substitution"))
|
||||
.with_color(parser.colors().error))
|
||||
.finish());
|
||||
.with_color(parser.colors().error),
|
||||
)
|
||||
.finish(),
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
// Leading spaces
|
||||
else if name.as_str().trim_start() != name.as_str()
|
||||
{
|
||||
else if name.as_str().trim_start() != name.as_str() {
|
||||
result.push(
|
||||
Report::build(ReportKind::Error, token.source(), name.start())
|
||||
.with_message("Invalid variable name")
|
||||
.with_label(
|
||||
Label::new((token.source(), name.range()))
|
||||
.with_message(format!("Variable names contains leading spaces"))
|
||||
.with_color(parser.colors().error))
|
||||
.with_color(parser.colors().error),
|
||||
)
|
||||
.with_help("Remove leading spaces")
|
||||
.finish());
|
||||
.finish(),
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
// Trailing spaces
|
||||
else if name.as_str().trim_end() != name.as_str()
|
||||
{
|
||||
else if name.as_str().trim_end() != name.as_str() {
|
||||
result.push(
|
||||
Report::build(ReportKind::Error, token.source(), name.start())
|
||||
.with_message("Invalid variable name")
|
||||
.with_label(
|
||||
Label::new((token.source(), name.range()))
|
||||
.with_message(format!("Variable names contains trailing spaces"))
|
||||
.with_color(parser.colors().error))
|
||||
.with_message(format!(
|
||||
"Variable names contains trailing spaces"
|
||||
))
|
||||
.with_color(parser.colors().error),
|
||||
)
|
||||
.with_help("Remove trailing spaces")
|
||||
.finish());
|
||||
.finish(),
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
// Invalid name
|
||||
match VariableRule::validate_name(&parser.colors(), name.as_str())
|
||||
{
|
||||
Err(msg) =>
|
||||
{
|
||||
match VariableRule::validate_name(&parser.colors(), name.as_str()) {
|
||||
Err(msg) => {
|
||||
result.push(
|
||||
Report::build(ReportKind::Error, token.source(), name.start())
|
||||
.with_message("Invalid variable name")
|
||||
.with_label(
|
||||
Label::new((token.source(), name.range()))
|
||||
.with_message(msg)
|
||||
.with_color(parser.colors().error))
|
||||
.finish());
|
||||
.with_color(parser.colors().error),
|
||||
)
|
||||
.finish(),
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
_ => {},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
// Get variable
|
||||
match document.get_variable(name.as_str())
|
||||
{
|
||||
match document.get_variable(name.as_str()) {
|
||||
None => {
|
||||
result.push(
|
||||
Report::build(ReportKind::Error, token.source(), name.start())
|
||||
.with_message("Unknown variable name")
|
||||
.with_label(
|
||||
Label::new((token.source(), name.range()))
|
||||
.with_message(format!("Unable to find variable with name: `{}`",
|
||||
name.as_str().fg(parser.colors().highlight)))
|
||||
.with_color(parser.colors().error))
|
||||
.finish());
|
||||
.with_message(format!(
|
||||
"Unable to find variable with name: `{}`",
|
||||
name.as_str().fg(parser.colors().highlight)
|
||||
))
|
||||
.with_color(parser.colors().error),
|
||||
)
|
||||
.finish(),
|
||||
);
|
||||
return result;
|
||||
}
|
||||
Some(var) => var,
|
||||
}
|
||||
},
|
||||
_ => panic!("Unknown error")
|
||||
}
|
||||
_ => panic!("Unknown error"),
|
||||
};
|
||||
|
||||
variable.parse(token, parser, document);
|
||||
|
@ -316,6 +421,5 @@ impl RegexRule for VariableSubstitutionRule
|
|||
return result;
|
||||
}
|
||||
|
||||
// TODO
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)> { vec![] }
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> { None }
|
||||
}
|
||||
|
|
|
@ -33,17 +33,20 @@ impl Kernel {
|
|||
let nml_table = lua.create_table().unwrap();
|
||||
|
||||
for rule in parser.rules()
|
||||
{
|
||||
if let Some(bindings) = rule.lua_bindings(&lua)
|
||||
{
|
||||
let table = lua.create_table().unwrap();
|
||||
let name = rule.name().to_lowercase();
|
||||
|
||||
for (fun_name, fun) in rule.lua_bindings(&lua)
|
||||
for (fun_name, fun) in bindings
|
||||
{
|
||||
table.set(fun_name, fun).unwrap();
|
||||
}
|
||||
|
||||
nml_table.set(name, table).unwrap();
|
||||
}
|
||||
}
|
||||
lua.globals().set("nml", nml_table).unwrap();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ pub trait Rule {
|
|||
match_data: Option<Box<dyn Any>>,
|
||||
) -> (Cursor, Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>);
|
||||
/// Export bindings to lua
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)>;
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>>;
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for dyn Rule {
|
||||
|
@ -89,7 +89,7 @@ pub trait RegexRule {
|
|||
matches: regex::Captures,
|
||||
) -> Vec<Report<'_, (Rc<dyn Source>, Range<usize>)>>;
|
||||
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Vec<(String, Function<'lua>)>;
|
||||
fn lua_bindings<'lua>(&self, _lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>>;
|
||||
}
|
||||
|
||||
impl<T: RegexRule> Rule for T {
|
||||
|
@ -144,7 +144,7 @@ impl<T: RegexRule> Rule for T {
|
|||
);
|
||||
}
|
||||
|
||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> {
|
||||
fn lua_bindings<'lua>(&self, lua: &'lua Lua) -> Option<Vec<(String, Function<'lua>)>> {
|
||||
self.lua_bindings(lua)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue