little bits of progress

This commit is contained in:
JT 2021-07-01 18:09:55 +12:00
parent 43fd0b6ae9
commit 4f89ed5d66
4 changed files with 118 additions and 59 deletions

View File

@ -8,5 +8,5 @@ mod span;
pub use lex::{lex, LexMode, Token, TokenContents}; pub use lex::{lex, LexMode, Token, TokenContents};
pub use lite_parse::{lite_parse, LiteBlock, LiteCommand, LiteStatement}; pub use lite_parse::{lite_parse, LiteBlock, LiteCommand, LiteStatement};
pub use parse_error::ParseError; pub use parse_error::ParseError;
pub use parser_state::{ParserState, ParserWorkingSet, VarLocation}; pub use parser_state::{ParserState, ParserWorkingSet};
pub use span::Span; pub use span::Span;

View File

@ -7,4 +7,5 @@ pub enum ParseError {
UnknownStatement(Span), UnknownStatement(Span),
Mismatch(String, Span), Mismatch(String, Span),
VariableNotFound(Span), VariableNotFound(Span),
UnknownCommand(Span),
} }

View File

@ -6,9 +6,16 @@ use crate::{
LiteBlock, LiteCommand, LiteStatement, ParseError, ParserWorkingSet, Span, LiteBlock, LiteCommand, LiteStatement, ParseError, ParserWorkingSet, Span,
}; };
pub struct Signature {
pub name: String,
pub mandatory_positional: Vec<SyntaxShape>,
}
/// The syntactic shapes that values must match to be passed into a command. You can think of this as the type-checking that occurs when you call a function. /// The syntactic shapes that values must match to be passed into a command. You can think of this as the type-checking that occurs when you call a function.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Clone)]
pub enum SyntaxShape { pub enum SyntaxShape {
/// A specific match to a word or symbol
Word(Vec<u8>),
/// Any syntactic form is allowed /// Any syntactic form is allowed
Any, Any,
/// Strings and string-like bare words are allowed /// Strings and string-like bare words are allowed
@ -154,39 +161,26 @@ fn span(spans: &[Span]) -> Span {
} }
impl ParserWorkingSet { impl ParserWorkingSet {
/* pub fn parse_external_call(&mut self, spans: &[Span]) -> (Expression, Option<ParseError>) {
fn parse_let(&mut self, command: &LiteCommand) -> (Statement, Option<ParseError>) { // TODO: add external parsing
(Expression::garbage(spans[0]), None)
}
fn parse_special_command(&mut self, command: &LiteCommand) -> (Statement, Option<ParseError>) {
let command_name = self.get_span_contents(command.parts[0]);
println!("{:?}", command_name);
match command_name {
b"let" => self.parse_let(command),
b"def" => self.parse_def(command),
b"source" => self.parse_source(command),
_ => (
Statement::None,
Some(ParseError::UnknownStatement(command.parts[0])),
),
}
} }
fn parse_statement( pub fn parse_call(&mut self, spans: &[Span]) -> (Expression, Option<ParseError>) {
&mut self, // assume spans.len() > 0?
block: &mut Block, let name = self.get_span_contents(spans[0]);
lite_pipeline: &LiteStatement,
) -> Option<ParseError> { if let Some(decl_id) = self.find_decl(name) {
match lite_pipeline.commands.len() { let sig = self.get_decl(decl_id).expect("internal error: bad DeclId");
0 => None,
1 => None, let mut positional_idx = 0;
_ => { let mut arg_offset = 1;
// pipeline
None (Expression::garbage(spans[0]), None)
} } else {
self.parse_external_call(spans)
} }
} }
*/
pub fn parse_int(&mut self, token: &str, span: Span) -> (Expression, Option<ParseError>) { pub fn parse_int(&mut self, token: &str, span: Span) -> (Expression, Option<ParseError>) {
if let Some(token) = token.strip_prefix("0x") { if let Some(token) = token.strip_prefix("0x") {
@ -272,7 +266,10 @@ impl ParserWorkingSet {
) -> (Expression, Option<ParseError>) { ) -> (Expression, Option<ParseError>) {
let bytes = self.get_span_contents(span); let bytes = self.get_span_contents(span);
if !bytes.is_empty() && bytes[0] == b'$' { if !bytes.is_empty() && bytes[0] == b'$' {
if let Some((var_id, _, ty)) = self.find_variable(bytes) { if let Some(var_id) = self.find_variable(bytes) {
let ty = *self
.get_variable(var_id)
.expect("internal error: invalid VarId");
return ( return (
Expression { Expression {
expr: Expr::Var(var_id), expr: Expr::Var(var_id),
@ -316,7 +313,7 @@ impl ParserWorkingSet {
let bytes = self.get_span_contents(span); let bytes = self.get_span_contents(span);
if is_variable(bytes) { if is_variable(bytes) {
if let Some((var_id, _, _)) = self.find_variable(bytes) { if let Some(var_id) = self.find_variable(bytes) {
(Some(var_id), None) (Some(var_id), None)
} else { } else {
(None, None) (None, None)

View File

@ -1,13 +1,11 @@
use crate::{ParseError, Span}; use crate::{parser::Signature, ParseError, Span};
use core::num;
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, sync::Arc};
pub struct ParserState { pub struct ParserState {
files: Vec<(String, Vec<u8>)>, files: Vec<(String, Vec<u8>)>,
} vars: Vec<Type>,
decls: Vec<Signature>,
pub enum VarLocation {
CurrentScope,
OuterScope,
} }
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
@ -17,26 +15,22 @@ pub enum Type {
} }
pub type VarId = usize; pub type VarId = usize;
pub type DeclId = usize;
struct ScopeFrame { struct ScopeFrame {
vars: HashMap<Vec<u8>, VarId>, vars: HashMap<Vec<u8>, VarId>,
decls: HashMap<Vec<u8>, DeclId>,
} }
impl ScopeFrame { impl ScopeFrame {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
vars: HashMap::new(), vars: HashMap::new(),
decls: HashMap::new(),
} }
} }
} }
pub struct ParserWorkingSet {
files: Vec<(String, Vec<u8>)>,
vars: HashMap<VarId, Type>,
permanent_state: Option<Arc<ParserState>>,
scope: Vec<ScopeFrame>,
}
impl Default for ParserState { impl Default for ParserState {
fn default() -> Self { fn default() -> Self {
Self::new() Self::new()
@ -45,7 +39,11 @@ impl Default for ParserState {
impl ParserState { impl ParserState {
pub fn new() -> Self { pub fn new() -> Self {
Self { files: vec![] } Self {
files: vec![],
vars: vec![],
decls: vec![],
}
} }
pub fn merge_working_set(this: &mut Arc<ParserState>, mut working_set: ParserWorkingSet) { pub fn merge_working_set(this: &mut Arc<ParserState>, mut working_set: ParserWorkingSet) {
@ -64,6 +62,22 @@ impl ParserState {
self.files.len() self.files.len()
} }
pub fn num_vars(&self) -> usize {
self.vars.len()
}
pub fn num_decls(&self) -> usize {
self.decls.len()
}
pub fn get_var(&self, var_id: VarId) -> Option<&Type> {
self.vars.get(var_id)
}
pub fn get_decl(&self, decl_id: VarId) -> Option<&Signature> {
self.decls.get(decl_id)
}
pub(crate) fn add_file(&mut self, filename: String, contents: Vec<u8>) -> usize { pub(crate) fn add_file(&mut self, filename: String, contents: Vec<u8>) -> usize {
self.files.push((filename, contents)); self.files.push((filename, contents));
@ -75,11 +89,20 @@ impl ParserState {
} }
} }
pub struct ParserWorkingSet {
files: Vec<(String, Vec<u8>)>,
vars: Vec<Type>, // indexed by VarId
decls: Vec<Signature>, // indexed by DeclId
permanent_state: Option<Arc<ParserState>>,
scope: Vec<ScopeFrame>,
}
impl ParserWorkingSet { impl ParserWorkingSet {
pub fn new(permanent_state: Option<Arc<ParserState>>) -> Self { pub fn new(permanent_state: Option<Arc<ParserState>>) -> Self {
Self { Self {
files: vec![], files: vec![],
vars: HashMap::new(), vars: vec![],
decls: vec![],
permanent_state, permanent_state,
scope: vec![], scope: vec![],
} }
@ -122,17 +145,29 @@ impl ParserWorkingSet {
self.scope.push(ScopeFrame::new()); self.scope.push(ScopeFrame::new());
} }
pub fn find_variable(&self, name: &[u8]) -> Option<(VarId, VarLocation, Type)> { pub fn find_decl(&self, name: &[u8]) -> Option<DeclId> {
for scope in self.scope.iter().rev().enumerate() {
if let Some(decl_id) = scope.1.decls.get(name) {
return Some(*decl_id);
}
}
None
}
pub fn next_var_id(&self) -> VarId {
if let Some(permanent_state) = &self.permanent_state {
let num_permanent_vars = permanent_state.num_vars();
num_permanent_vars + self.vars.len()
} else {
self.vars.len()
}
}
pub fn find_variable(&self, name: &[u8]) -> Option<VarId> {
for scope in self.scope.iter().rev().enumerate() { for scope in self.scope.iter().rev().enumerate() {
if let Some(var_id) = scope.1.vars.get(name) { if let Some(var_id) = scope.1.vars.get(name) {
if let Some(result) = self.vars.get(var_id) { return Some(*var_id);
if scope.0 == 0 {
// Top level
return Some((*var_id, VarLocation::CurrentScope, *result));
} else {
return Some((*var_id, VarLocation::OuterScope, *result));
}
}
} }
} }
@ -140,19 +175,45 @@ impl ParserWorkingSet {
} }
pub fn add_variable(&mut self, name: Vec<u8>, ty: Type) -> VarId { pub fn add_variable(&mut self, name: Vec<u8>, ty: Type) -> VarId {
let next_id = self.next_var_id();
let last = self let last = self
.scope .scope
.last_mut() .last_mut()
.expect("internal error: missing stack frame"); .expect("internal error: missing stack frame");
let next_id = self.vars.len();
last.vars.insert(name, next_id); last.vars.insert(name, next_id);
self.vars.insert(next_id, ty); self.vars.insert(next_id, ty);
next_id next_id
} }
pub fn get_variable(&self, var_id: VarId) -> Option<&Type> {
if let Some(permanent_state) = &self.permanent_state {
let num_permanent_vars = permanent_state.num_vars();
if var_id < num_permanent_vars {
permanent_state.get_var(var_id)
} else {
self.vars.get(var_id - num_permanent_vars)
}
} else {
self.vars.get(var_id)
}
}
pub fn get_decl(&self, decl_id: DeclId) -> Option<&Signature> {
if let Some(permanent_state) = &self.permanent_state {
let num_permanent_decls = permanent_state.num_decls();
if decl_id < num_permanent_decls {
permanent_state.get_decl(decl_id)
} else {
self.decls.get(decl_id - num_permanent_decls)
}
} else {
self.decls.get(decl_id)
}
}
} }
#[cfg(test)] #[cfg(test)]