Tholp's bespoke website generator

Refactor tokens to be chars instead of strings

-1
src/macros/simple_blocks.rs
···
use crate::{
console::{error_skid, warn_skid},
-
macros::template::SkidTemplate,
project::ProjectContext,
stringtools::{find_pattern, split_to_tokens, TokenTools},
types::{SkidContext, Token},
+11 -6
src/macros/template.rs
···
project::ProjectContext,
reservednames::{RESERVED_NAMES_HTML, RESERVED_NAMES_MISC},
stringtools::{find_pattern, split_to_tokens, WhitespaceChecks},
-
types::{SkidContext, Token},
+
types::{IsScoped, SkidContext, Token},
};
use super::MACRO_LIST;
···
allows_trailing_args: trailing,
}
}
-
pub fn expand(
&self,
//_file: &mut InputFile,
origin_index: usize,
origin_line: usize,
-
project_context: &mut ProjectContext,
+
proj_context: &mut ProjectContext,
args: &Vec<String>,
scope: &[Token],
) -> Vec<Token> {
···
if !self.allows_trailing_args && args.len() != self.args.len() {
error_skid(
-
project_context,
+
proj_context,
origin_index,
origin_line,
&format!(
···
}
if self.allows_trailing_args && args.len() < self.args.len() {
error_skid(
-
project_context,
+
proj_context,
origin_index,
origin_line,
&format!(
···
let mut output = self.tokens.clone();
for tok in &mut output {
-
tok.origin_file = origin_index;
+
tok.origin_index = origin_index;
}
let mut args_index: usize = 0;
···
}
output
+
}
+
}
+
+
impl IsScoped for SkidTemplate {
+
fn is_scoped(&self) -> bool {
+
self.has_scope
}
}
+234 -215
src/main.rs
···
mod types;
use crate::{
-
args::ProgramArgs,
-
closures::CLOSURE_LIST,
-
macros::template::SkidTemplate,
-
project::FileGroup,
reservednames::RESERVED_NAMES_MISC,
-
types::{Expand, SkidContext},
+
stringtools::TokenTools,
+
types::{IsScoped, MacroExpand, SkidContext},
};
-
use clap::Parser;
+
use console::*;
use macros::MACRO_LIST;
use markdown::{CompileOptions, Constructs, Options, ParseOptions};
···
env,
fs::{self},
path::PathBuf,
-
task::Context,
};
-
use stringtools::{collect_arguments, collect_block, split_to_tokens, trim_whitespace_tokens};
+
use stringtools::{collect_arguments, collect_block, split_to_tokens};
use types::{InputFile, Token};
// really need to change this whole thing to work with characters rather than
···
' ', '\n', '\t', '(', ')', '{', '}', '[', ']', '<', '>', '\\', '\'', '\"', ';', '?', '^', '-',
];
+
#[derive(PartialEq)]
+
enum EphemeralType {
+
Normal,
+
Ephemeral,
+
InverseEphemeral,
+
}
+
fn main() {
// let args = ProgramArgs::parse();
···
// }
for group in &mut project.filegroups {
+
if !group.process {
+
continue;
+
}
for infile in &mut group.files {
let contents =
fs::read_to_string(&infile.file_input).expect("File unreadable or missing");
-
infile.tokens =
+
let tokens =
split_to_tokens(contents, project.context.index_of_file(&infile.file_input));
-
let mut skid_context = SkidContext::new();
-
process_skid(
-
&mut infile.tokens,
-
project.context.index_of_file(&infile.file_input),
-
&mut project.context,
-
&mut skid_context,
+
let mut skid_context =
+
SkidContext::new(project.context.index_of_file(&infile.file_input));
+
write_file(
+
infile,
+
group.convert_html,
+
&process_skid(&tokens, &mut project.context, &mut skid_context),
);
}
}
}
-
fn process_skid(
-
tokens_in: &mut [Token],
-
file_index: usize,
-
context: &mut ProjectContext,
+
fn find_and_run_macro(
+
tokens_in: &[Token],
+
proj_context: &mut ProjectContext,
skid_context: &mut SkidContext,
-
) -> Vec<Token> {
-
//}, context: &mut ProjectContext) {
-
//println!("{}\n {}", f.filename_out, contents);
+
) -> Option<(Vec<Token>, usize)> {
+
// (Output, to be consumed size)
-
//file.tokens = strings_to_tokens(split_keep_delimiters(contents), file.filename_input.clone());
+
// At this point we think its a macro (starts with ! or &) so check which, we have the rest of the file
+
let ephemeral_type: EphemeralType;
+
if tokens_in.len() < 2 {
+
return None;
+
}
+
+
if tokens_in[0] == '!' && tokens_in[1] == '&' {
+
ephemeral_type = EphemeralType::InverseEphemeral;
+
} else if tokens_in[0] == '!' {
+
ephemeral_type = EphemeralType::Normal;
+
} else if tokens_in[0] == '&' {
+
ephemeral_type = EphemeralType::Ephemeral;
+
} else {
+
return None;
+
}
-
//let mut escaped = false;
-
let mut tokens = tokens_in.to_vec();
-
let mut starting_template_count = skid_context.templates.len();
+
let mut chars_consumed = if ephemeral_type == EphemeralType::InverseEphemeral {
+
2
+
} else {
+
1
+
};
+
// Look for name
+
let mut symbol: String = "".into();
+
for tok in &tokens_in[chars_consumed..] {
+
if tok.contents.is_whitespace() || DELIMITERS.contains(&tok.contents) {
+
break;
+
}
+
symbol.push(tok.contents);
+
chars_consumed += 1;
+
}
-
let mut working_index = 0;
+
if symbol.is_empty() {
+
return None;
+
}
-
while working_index < tokens.len() {
-
//look for macros or blocks
-
//println!(">\"{}\"<", tokens[working_index].contents);
+
let args;
+
let block;
-
if tokens[working_index].contents.len() == 0 {
-
working_index += 1;
-
continue;
+
{
+
let mut expander: &dyn IsScoped = &MACRO_LIST[0]; // assinging because it complains about possibly being empty later even if not the case
+
let mut found = false;
+
// Check if its a macro
+
for m in MACRO_LIST {
+
if m.symbol == symbol {
+
found = true;
+
expander = m;
+
break;
+
}
}
-
if tokens[working_index].contents == "\\" {
-
tokens[working_index].contents = "".into();
-
working_index += 2;
-
//println!("Hit backslash");
-
continue;
+
// Not a macro check templates
+
if !found {
+
for t in &skid_context.templates {
+
if t.symbol == symbol {
+
found = true;
+
expander = t;
+
break;
+
}
+
}
}
-
let mut matched_macro: bool = false;
-
if tokens[working_index].contents.starts_with(['!', '&']) {
-
let mut prefix_len = 1;
-
let mut symbol = tokens[working_index].contents.clone();
-
symbol = symbol.trim().to_string();
-
-
if symbol.len() > 2 {
-
let mut ephemeral = false;
-
let same_file = tokens[working_index].origin_file != file_index;
+
// Not a template either, see if its reserved or not to see if we should say something
+
if !found {
+
let name = symbol.to_lowercase();
+
let mut dont_error = false;
-
// Inversely Ephemeral
-
if symbol.starts_with("!&") {
-
prefix_len = 2;
-
ephemeral = !same_file;
+
for reserved in RESERVED_NAMES_HTML {
+
if name.starts_with(reserved) {
+
dont_error = true;
+
break;
}
-
// Ephemeral
-
else if symbol.starts_with("&") {
-
ephemeral = same_file;
+
}
+
+
if !dont_error {
+
for reserved in RESERVED_NAMES_MISC {
+
if name.starts_with(reserved) {
+
dont_error = true;
+
break;
+
}
}
+
}
-
// Check if its a macro
-
for m in MACRO_LIST {
-
if &symbol[prefix_len..] == m.symbol {
-
matched_macro = true;
-
//println!("Found a macro ({})", m.symbol);
+
if !dont_error {
+
warn_skid(
+
&proj_context,
+
tokens_in[0].origin_index,
+
tokens_in[0].origin_line,
+
&format!("No such macro or defined template \"{symbol}\""),
+
);
+
}
+
return None;
+
}
-
let (args, args_tokcount) = collect_arguments(&tokens[working_index..]);
-
let expansion: Vec<Token>;
-
let block_tokcount: usize;
-
if m.has_scope {
-
//println!("is scoped.");
+
let args_result = collect_arguments(&tokens_in[chars_consumed..]);
+
if args_result.is_none() {
+
error_skid(
+
proj_context,
+
tokens_in[0].origin_index,
+
tokens_in[0].origin_line,
+
&format!("Didnt find any arguments for macro \"{symbol}\"."),
+
);
+
return None;
+
}
-
let block_opt =
-
collect_block(&tokens[(working_index + args_tokcount)..]);
-
if block_opt.is_none() {
-
error_skid(
-
context,
-
tokens[working_index].template_origin,
-
tokens[working_index].line_number,
-
&"Malformed Block".into(),
-
);
-
}
-
let block: Vec<Token>;
-
(block, block_tokcount) = block_opt.unwrap();
+
let consumed_by_args;
+
(args, consumed_by_args) = args_result.unwrap();
+
chars_consumed += consumed_by_args;
-
if ephemeral {
-
expansion = Vec::new();
-
} else {
-
expansion = m.expand(
-
tokens[working_index].origin_file,
-
tokens[working_index].line_number,
-
context,
-
skid_context,
-
&args,
-
&block,
-
);
-
}
-
} else {
-
block_tokcount = 0;
+
if expander.is_scoped() {
+
let block_result = collect_block(&tokens_in[chars_consumed..]);
+
if block_result.is_none() {
+
error_skid(
+
proj_context,
+
tokens_in[0].origin_index,
+
tokens_in[0].origin_line,
+
&format!("Didnt find a block for macro \"{symbol}\"."),
+
);
+
return None;
+
}
+
let consumed_by_block;
+
(block, consumed_by_block) = block_result.unwrap();
+
chars_consumed += consumed_by_block;
+
} else {
+
block = Vec::new();
+
}
+
}
-
if ephemeral {
-
expansion = Vec::new();
-
} else {
-
expansion = m.expand(
-
tokens[working_index].origin_file,
-
tokens[working_index].line_number,
-
context,
-
skid_context,
-
&args,
-
&Vec::new()[..],
-
);
-
}
-
}
-
-
let trimmed = trim_whitespace_tokens(&expansion);
-
-
tokens.remove(working_index);
-
tokens.splice(
-
working_index..(working_index + args_tokcount + block_tokcount - 1),
-
trimmed.iter().cloned(),
-
);
-
if expansion.len() == 0 && working_index > 0 {
-
working_index -= 1;
-
}
-
}
-
}
+
let return_empty: bool;
-
// check for templates
-
// todo maybe deduplicate this
-
for t in &skid_context.templates {
-
if &symbol[prefix_len..] == t.symbol {
-
matched_macro = true;
-
//println!("Found a macro ({})", m.symbol);
+
match ephemeral_type {
+
EphemeralType::Normal => return_empty = false,
+
EphemeralType::Ephemeral => {
+
return_empty = skid_context.file_index != tokens_in[0].origin_index
+
}
+
EphemeralType::InverseEphemeral => {
+
return_empty = skid_context.file_index == tokens_in[0].origin_index
+
}
+
}
-
let (args, args_tokcount) = collect_arguments(&tokens[working_index..]);
-
let expansion: Vec<Token>;
-
let block_tokcount: usize;
+
if return_empty {
+
return Some((Vec::new(), chars_consumed));
+
} else {
+
// we have to find it again because of borrower
+
for m in MACRO_LIST {
+
if m.symbol == symbol {
+
return Some((
+
m.expand(
+
tokens_in[0].origin_index,
+
tokens_in[0].origin_line,
+
proj_context,
+
skid_context,
+
&args,
+
&block,
+
)
+
.trim_whitespace()
+
.to_vec(),
+
chars_consumed,
+
));
+
}
+
}
+
let mut i = 0;
+
while i < skid_context.templates.len() {
+
if skid_context.templates[i].symbol == symbol {
+
return Some((
+
skid_context.templates[i]
+
.expand(
+
tokens_in[0].origin_index,
+
tokens_in[0].origin_line,
+
proj_context,
+
&args,
+
&block,
+
)
+
.trim_whitespace()
+
.to_vec(),
+
chars_consumed,
+
));
+
}
+
i += 1;
+
}
+
}
+
None
+
}
-
if t.has_scope {
-
//println!("is scoped.");
-
let block: Vec<Token>;
-
let block_opt =
-
collect_block(&tokens[(working_index + args_tokcount)..]);
-
if block_opt.is_none() {
-
error_skid(
-
context,
-
tokens[working_index].template_origin,
-
tokens[working_index].line_number,
-
&"Malformed Block".into(),
-
);
-
}
+
fn process_skid(
+
tokens_in: &[Token],
+
proj_context: &mut ProjectContext,
+
skid_context: &mut SkidContext,
+
) -> Vec<Token> {
+
//}, context: &mut ProjectContext) {
+
//println!("{}\n {}", f.filename_out, contents);
-
(block, block_tokcount) = block_opt.unwrap();
+
//file.tokens = strings_to_tokens(split_keep_delimiters(contents), file.filename_input.clone());
-
if ephemeral {
-
expansion = Vec::new();
-
} else {
-
expansion = t.expand(
-
//file,
-
tokens[working_index].origin_file,
-
tokens[working_index].line_number,
-
context,
-
&args,
-
&block,
-
);
-
}
-
} else {
-
block_tokcount = 0;
+
//let mut escaped = false;
+
let mut tokens = tokens_in.to_vec();
+
let starting_template_count = skid_context.templates.len();
-
if ephemeral {
-
expansion = Vec::new();
-
} else {
-
expansion = t.expand(
-
//file,
-
tokens[working_index].origin_file,
-
tokens[working_index].line_number,
-
context,
-
&args,
-
&Vec::new()[..],
-
);
-
}
-
}
+
let mut escaped = false;
+
let mut working_index = 0;
-
let trimmed = trim_whitespace_tokens(&expansion);
+
while working_index < tokens.len() {
+
if tokens[working_index] == '\\' && !escaped {
+
tokens[working_index].contents = '\0'; // skip over this later when outputting to avoid shifting memory rn
+
escaped = true;
+
working_index += 1;
-
tokens.remove(working_index);
-
tokens.splice(
-
working_index..(working_index + args_tokcount + block_tokcount - 1),
-
trimmed.iter().cloned(),
-
);
-
if expansion.len() == 0 && working_index > 0 {
-
working_index -= 1;
-
}
-
}
-
}
+
// bit of a hack for reverse ephemeral escaping behavior to be the same as previously
+
if tokens.len() > working_index + 1
+
&& tokens[working_index] == '!'
+
&& tokens[working_index + 1] == '&'
+
{
+
working_index += 1;
}
-
if !matched_macro {
-
let name = tokens[working_index].contents.trim().to_lowercase();
-
let mut dont_error = name.len() <= 1;
-
{
-
if !dont_error {
-
for reserved in RESERVED_NAMES_HTML {
-
if name[1..].starts_with(reserved) {
-
dont_error = true;
-
break;
-
}
-
}
-
}
+
continue;
+
}
-
if !dont_error {
-
for reserved in RESERVED_NAMES_MISC {
-
if name[1..].starts_with(reserved) {
-
dont_error = true;
-
break;
-
}
-
}
-
}
-
}
-
if !dont_error {
-
warn_skid(
-
context,
-
tokens[working_index].origin_file,
-
tokens[working_index].line_number,
-
&format!(
-
"Token written as a function but no such function exists \"{}\"",
-
tokens[working_index].contents.trim()
-
),
-
);
-
}
+
if (tokens[working_index] == '!' || tokens[working_index] == '&') && !escaped {
+
let expansion =
+
find_and_run_macro(&tokens[working_index..], proj_context, skid_context);
+
if expansion.is_some() {
+
tokens.splice(
+
working_index..working_index + expansion.as_ref().unwrap().1,
+
expansion.unwrap().0,
+
);
+
continue;
}
}
···
// }
// }
-
if !matched_macro {
-
working_index += 1;
-
}
+
working_index += 1;
+
+
escaped = false;
}
skid_context.templates.truncate(starting_template_count);
+
+
tokens.retain(|t| t.contents != '\0');
+
return tokens;
}
-
fn write_file(file: InputFile, convert_html: bool) {
+
fn write_file(file: &InputFile, convert_html: bool, tokens: &[Token]) {
//println!("{:?}", tokens);
let mut skid_output: String = "".to_string();
-
for t in &file.tokens {
-
skid_output += &t.contents;
+
for t in tokens {
+
skid_output.push(t.contents);
}
let mut folder = file.file_skidout.clone();
-2
src/project.rs
···
pub post_insert: PathBuf,
pub process: bool,
pub convert_html: bool,
-
pub output_extention: String,
}
pub struct ProjectContext {
···
post_insert: post_insert.into(),
process,
convert_html,
-
output_extention: extention.into(),
};
if filegroup_def.contains_key("files") {
+55 -46
src/stringtools.rs
···
use super::DELIMITERS;
use crate::types::Token;
-
pub fn collect_arguments(tokens: &[Token]) -> (Vec<String>, usize) {
-
// Arguments vec and number of tokens consumed
+
pub fn collect_arguments(tokens: &[Token]) -> Option<(Vec<String>, usize)> {
+
// Returns arguments vec and number of tokens to be consumed
//let mut output = Vec::new();
-
let mut split_tokens = Vec::new();
-
for tok in tokens {
-
for s in split_keep_delimiters(tok.contents.clone()) {
-
split_tokens.push(s);
-
}
-
}
let mut quoted: bool = false;
+
let mut escaped: bool = false;
let mut entered: bool = false;
let mut arg = "".to_string();
let mut args: Vec<String> = Vec::new();
let mut in_token_count = 0;
+
let mut exited_cleanly = false;
-
for tok in split_tokens {
-
in_token_count += 1; // This could be a problem if it something got split above..
-
if tok.starts_with([' ', '\t']) && !quoted {
+
for tok in tokens {
+
let c = tok.contents;
+
+
in_token_count += 1;
+
if c.is_whitespace() && !entered {
continue;
}
-
if !entered && tok.starts_with('(') {
+
if !entered && c == '(' {
entered = true;
continue;
}
if !entered {
-
continue;
+
break;
}
-
if !quoted && tok.starts_with(')') {
+
if !quoted && tok.contents == ')' {
+
exited_cleanly = true;
+
if !arg.is_empty() {
+
args.push(arg.clone());
+
arg.clear();
+
}
break;
}
-
for c in tok.chars() {
-
if c == '\"' {
-
quoted = !quoted;
-
continue;
-
}
+
if c == '\"' && !escaped {
+
quoted = !quoted;
+
continue;
+
}
-
arg.push(c);
+
if c == '\\' && !escaped {
+
escaped = true;
+
continue;
}
-
if !quoted {
-
args.push(arg.clone());
-
arg.clear();
+
if c.is_whitespace() && !quoted {
+
if !arg.is_empty() {
+
args.push(arg.clone());
+
arg.clear();
+
}
+
continue;
}
+
arg.push(c);
}
-
return (args, in_token_count);
+
if !entered || !exited_cleanly {
+
return None;
+
}
+
return Some((args, in_token_count));
}
pub fn collect_block(tokens: &[Token]) -> Option<(Vec<Token>, usize)> {
···
// We dont really care about doing anything that in the block right now
// maybe have the Token struct contain scope level later?
-
let mut escaped_tok: Token = Token::new("\\".into(), 0, 0);
+
let mut escaped_tok: Token = Token::new('\\', 0, 0);
for tok in tokens {
tokens_consumed += 1;
if !entered {
-
if tok.contents.is_only_whitespace() {
+
if tok.contents.is_whitespace() {
continue;
}
-
if tok.contents != "{"
+
if tok.contents != '{'
// Expected block start, got garbage
{
// println!("Expected block start, got {}",tok.contents);
···
let mut escaped_used = false;
// Scope Start
-
if tok.contents == "{" && !escaped {
+
if tok.contents == '{' && !escaped {
entering_bracket_count += 1;
if entering_bracket_count == 3 {
···
}
}
// Scope End
-
if tok.contents == "}" && !escaped {
+
if tok.contents == '}' && !escaped {
exiting_bracket_count += 1;
if exiting_bracket_count == 3 {
scope_count -= 1;
···
block.push(escaped_tok.clone());
}
-
if tok.contents == "\\" {
+
if tok.contents == '\\' {
escaped = true;
escaped_tok = tok.clone();
} else {
···
let mut line_count = 1;
for str in in_strings {
-
if str.len() == 0 {
-
continue;
-
}
-
-
let current_line = line_count;
-
for char in str.chars() {
-
if char == '\n' {
-
line_count += 1;
+
for c in str.chars() {
+
let current_line = line_count;
+
for char in str.chars() {
+
if char == '\n' {
+
line_count += 1;
+
}
}
+
let token: Token = Token::new(c, origin_file, current_line);
+
tokens.push(token);
}
-
let token: Token = Token::new(str, origin_file, current_line);
-
tokens.push(token);
}
return tokens;
···
return strings_to_tokens(new_split, origin_file);
}
-
pub fn next_nonwhitespace_token(tokens: &Vec<Token>, index: usize) -> (bool, usize) {
+
pub fn next_nonwhitespace_token(tokens: &Vec<Token>, index: usize) -> Option<usize> {
while index < tokens.len() {
-
if tokens[index].contents.is_only_whitespace() {
+
if tokens[index].contents.is_whitespace() {
continue;
}
-
return (true, index);
+
return Some(index);
}
-
return (false, 0);
+
return None;
}
//trim whitespace from the ends
···
let mut start: usize = 0;
let mut end: usize = tokens.len();
for tok in tokens {
-
if !tok.contents.is_only_whitespace() {
+
if !tok.contents.is_whitespace() {
break;
}
start = start + 1;
}
for tok in tokens.iter().rev() {
-
if !tok.contents.is_only_whitespace() {
+
if !tok.contents.is_whitespace() {
break;
}
end = end - 1;
+49 -33
src/types.rs
···
-
use boa_engine::Context;
use std::path::PathBuf;
use crate::{
···
};
pub struct Token {
-
pub contents: String,
-
pub origin_file: usize,
+
//pub contents: String,
+
pub contents: char,
+
pub origin_index: usize,
pub template_origin: usize,
-
pub line_number: usize,
+
pub origin_line: usize,
pub section_name_index: usize,
}
+
impl PartialEq<char> for Token {
+
fn eq(&self, other: &char) -> bool {
+
self.contents == *other
+
}
+
}
+
pub struct InputFile {
pub file_input: PathBuf,
pub file_skidout: PathBuf,
pub file_out: PathBuf,
-
pub tokens: Vec<Token>,
}
pub struct SkidContext {
pub templates: Vec<SkidTemplate>,
+
pub file_index: usize,
}
impl SkidContext {
-
pub fn new() -> SkidContext {
+
pub fn new(file_index: usize) -> SkidContext {
SkidContext {
templates: Vec::new(),
+
file_index,
}
}
}
···
pub max_args: usize,
}
-
pub trait Expand {
+
pub trait MacroExpand {
fn expand(
&self,
origin_index: usize,
···
args: &Vec<String>,
scope: &[Token],
) -> Vec<Token>;
+
}
-
fn default() -> Macro;
+
pub trait IsScoped {
+
fn is_scoped(&self) -> bool;
}
-
impl Expand for Macro {
+
impl Macro {
+
fn default() -> Macro {
+
Macro {
+
symbol: "default_symbol",
+
expansion: macro_comment,
+
has_scope: true,
+
min_args: 0,
+
max_args: usize::max_value(),
+
}
+
}
+
}
+
+
impl MacroExpand for Macro {
fn expand(
&self,
origin_index: usize,
origin_line: usize,
-
context: &mut ProjectContext,
+
proj_context: &mut ProjectContext,
skid_context: &mut SkidContext,
args: &Vec<String>,
-
scope: &[Token],
+
block: &[Token],
) -> Vec<Token> {
if (args.len() > self.max_args) || (args.len() < self.min_args) {
-
error_skid(context, origin_index, origin_line, &format!("Macro \'{}\' was given a number of arguments ({}) not in its acceptable range ({}-{})",
+
error_skid(proj_context, origin_index, origin_line, &format!("Macro \'{}\' was given a number of arguments ({}) not in its acceptable range ({}-{})",
self.symbol, args.len(), self.min_args, if self.max_args == usize::max_value() {"No Limit".to_string()} else {format!("{}", self.max_args)}));
Vec::new()
} else {
(self.expansion)(
origin_index,
origin_line,
-
context,
+
proj_context,
skid_context,
args,
-
scope,
+
block,
)
}
}
+
}
-
fn default() -> Macro {
-
Macro {
-
symbol: "default_symbol",
-
expansion: macro_comment,
-
has_scope: true,
-
min_args: 0,
-
max_args: usize::max_value(),
-
}
+
impl IsScoped for Macro {
+
fn is_scoped(&self) -> bool {
+
self.has_scope
}
}
···
file_input: "".into(),
file_skidout: "".into(),
file_out: "".into(),
-
tokens: Vec::new(),
}
}
}
impl Token {
-
pub fn new(contents: String, origin_file: usize, line_number: usize) -> Token {
+
pub fn new(contents: char, origin_file: usize, line_number: usize) -> Token {
Token {
contents: contents,
-
origin_file: origin_file,
+
origin_index: origin_file,
template_origin: origin_file,
-
line_number: line_number,
+
origin_line: line_number,
section_name_index: 0,
}
}
}
-
impl ToString for Token {
-
fn to_string(&self) -> String {
-
return self.contents.clone();
-
}
-
}
+
// impl ToString for Token {
+
// fn to_string(&self) -> String {
+
// return self.contents.clone();
+
// }
+
// }
impl Clone for Token {
fn clone(&self) -> Self {
let mut t = Token::new(
self.contents.clone(),
-
self.origin_file.clone(),
-
self.line_number,
+
self.origin_index.clone(),
+
self.origin_line,
);
t.template_origin = self.template_origin;
return t;