ltcc: parsing of double quoted strings
use double quotes in examples
This commit is contained in:
parent
f5984e0b08
commit
08f592ad60
6 changed files with 78 additions and 23 deletions
|
@ -41,10 +41,14 @@ pub type TypeTag = Result<laddertypes::TypeTerm, TypeError>;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum LTExpr {
|
pub enum LTExpr {
|
||||||
Literal {
|
WordLiteral {
|
||||||
typ: Option<TypeTag>,
|
typ: Option<TypeTag>,
|
||||||
val: tisc::VM_Word,
|
val: tisc::VM_Word,
|
||||||
},
|
},
|
||||||
|
StringLiteral {
|
||||||
|
region: InputRegionTag,
|
||||||
|
value: String,
|
||||||
|
},
|
||||||
Symbol {
|
Symbol {
|
||||||
region: InputRegionTag,
|
region: InputRegionTag,
|
||||||
typ: Option<TypeTag>,
|
typ: Option<TypeTag>,
|
||||||
|
@ -82,7 +86,7 @@ impl LTExpr {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
pub fn lit_uint(val: u64) -> Self {
|
pub fn lit_uint(val: u64) -> Self {
|
||||||
LTExpr::Literal {
|
LTExpr::WordLiteral {
|
||||||
typ: None, //typectx.write().unwrap().parse("ℤ_2^64~machine::UInt64~machine::Word").expect("parse typeterm"),
|
typ: None, //typectx.write().unwrap().parse("ℤ_2^64~machine::UInt64~machine::Word").expect("parse typeterm"),
|
||||||
val: val as tisc::VM_Word,
|
val: val as tisc::VM_Word,
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ pub enum LTIRToken {
|
||||||
Num(i64),
|
Num(i64),
|
||||||
|
|
||||||
// SingleQuote(String),
|
// SingleQuote(String),
|
||||||
// DoubleQuote(String),
|
DoubleQuote(String),
|
||||||
// TripleQuote(String),
|
// TripleQuote(String),
|
||||||
Lambda,
|
Lambda,
|
||||||
MapsTo,
|
MapsTo,
|
||||||
|
@ -25,6 +25,7 @@ pub enum LTIRToken {
|
||||||
pub enum LexError {
|
pub enum LexError {
|
||||||
InvalidDigit,
|
InvalidDigit,
|
||||||
InvalidChar,
|
InvalidChar,
|
||||||
|
UnexpectedEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
|
@ -35,6 +36,7 @@ pub enum LexerState {
|
||||||
Sym(String),
|
Sym(String),
|
||||||
Num(i64),
|
Num(i64),
|
||||||
Char(Option<char>),
|
Char(Option<char>),
|
||||||
|
DoubleQuote(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LexerState {
|
impl LexerState {
|
||||||
|
@ -46,6 +48,7 @@ impl LexerState {
|
||||||
LexerState::Sym(s) => Some(LTIRToken::Symbol(s)),
|
LexerState::Sym(s) => Some(LTIRToken::Symbol(s)),
|
||||||
LexerState::Num(n) => Some(LTIRToken::Num(n)),
|
LexerState::Num(n) => Some(LTIRToken::Num(n)),
|
||||||
LexerState::Char(c) => Some(LTIRToken::Char(c?)),
|
LexerState::Char(c) => Some(LTIRToken::Char(c?)),
|
||||||
|
LexerState::DoubleQuote(s) => Some(LTIRToken::DoubleQuote(s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,6 +199,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
'\"' => {
|
||||||
|
self.chars.next();
|
||||||
|
self.position += 1;
|
||||||
|
region.end += 1;
|
||||||
|
state = LexerState::DoubleQuote(String::new());
|
||||||
|
}
|
||||||
c => {
|
c => {
|
||||||
if c.is_whitespace() {
|
if c.is_whitespace() {
|
||||||
self.chars.next();
|
self.chars.next();
|
||||||
|
@ -242,6 +251,36 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LexerState::DoubleQuote(val) => {
|
||||||
|
match self.chars.next() {
|
||||||
|
Some('\"') => {
|
||||||
|
self.position += 1;
|
||||||
|
region.end +=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Some('\\') => {
|
||||||
|
match self.chars.next() {
|
||||||
|
Some('0') => {
|
||||||
|
val.push('\0');
|
||||||
|
}
|
||||||
|
Some('n') => {
|
||||||
|
val.push('\n');
|
||||||
|
}
|
||||||
|
Some('\\') => {
|
||||||
|
val.push('\\');
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(c) => {
|
||||||
|
val.push(c);
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
return Some((region, Err(LexError::UnexpectedEnd)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LexerState::Char(val) => {
|
LexerState::Char(val) => {
|
||||||
self.position += 2;
|
self.position += 2;
|
||||||
region.end += 2;
|
region.end += 2;
|
||||||
|
@ -325,7 +364,6 @@ where
|
||||||
return Some((region, Err(LexError::InvalidDigit)));
|
return Some((region, Err(LexError::InvalidDigit)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,3 +401,4 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -345,6 +345,12 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
|
||||||
Ok(LTIRToken::StatementSep) => {
|
Ok(LTIRToken::StatementSep) => {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Ok(LTIRToken::DoubleQuote(s)) => {
|
||||||
|
let region = region.clone();
|
||||||
|
let value = s.clone();
|
||||||
|
tokens.next();
|
||||||
|
children.push(LTExpr::StringLiteral{ region, value });
|
||||||
|
}
|
||||||
Ok(LTIRToken::Symbol(name)) => match name.as_str() {
|
Ok(LTIRToken::Symbol(name)) => match name.as_str() {
|
||||||
"if" => {
|
"if" => {
|
||||||
tokens.next();
|
tokens.next();
|
||||||
|
@ -404,6 +410,7 @@ where It: Iterator<Item = (InputRegionTag, Result<LTIRToken, LexError>)>
|
||||||
|
|
||||||
|
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use crate::parser::LTExpr;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -421,6 +428,19 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse_double_quote() {
|
||||||
|
let mut lexer = crate::lexer::LTIRLexer::from("\"test\"".chars()).peekable();
|
||||||
|
let typectx = Arc::new(RwLock::new(laddertypes::dict::TypeDict::new()));
|
||||||
|
let expr = crate::parser::parse_expr( &typectx, &mut lexer );
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
expr,
|
||||||
|
Ok(LTExpr::DoubleQuote("testlo".into()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_typed_atomic_binding() {
|
fn test_parse_typed_atomic_binding() {
|
||||||
let mut lexer = crate::lexer::LTIRLexer::from("x:T".chars()).peekable();
|
let mut lexer = crate::lexer::LTIRLexer::from("x:T".chars()).peekable();
|
||||||
|
|
|
@ -225,7 +225,13 @@ impl ProcedureCompiler {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
LTExpr::Literal { typ, val } => {
|
LTExpr::StringLiteral { region, value } => {
|
||||||
|
self.asm = self.asm.lit(0);
|
||||||
|
for c in value.chars().rev() {
|
||||||
|
self.asm = self.asm.lit(c as i64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LTExpr::WordLiteral { typ, val } => {
|
||||||
self.asm = self.asm.lit(*val);
|
self.asm = self.asm.lit(*val);
|
||||||
}
|
}
|
||||||
LTExpr::Application { typ, head, body } => {
|
LTExpr::Application { typ, head, body } => {
|
||||||
|
|
|
@ -16,19 +16,3 @@ export {
|
||||||
let int-max = λ{ a:ℤ~machine.Int64; b:ℤ~machine.Int64; } ↦ if( int-gt a b ) { a; } else { b; };
|
let int-max = λ{ a:ℤ~machine.Int64; b:ℤ~machine.Int64; } ↦ if( int-gt a b ) { a; } else { b; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* syntax ambiguity */
|
|
||||||
|
|
||||||
let f'0 = λx:A -> B ↦ { ... };
|
|
||||||
|
|
||||||
/* could be interpreted as .. */
|
|
||||||
let f'1 = λ{x: A -> B} ↦ {};
|
|
||||||
/* ..or.. */
|
|
||||||
let f'2 = λx:A ↦ B:{};
|
|
||||||
|
|
||||||
|
|
||||||
do {
|
|
||||||
!a 10;
|
|
||||||
!b 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
6
main.lt
6
main.lt
|
@ -1,5 +1,6 @@
|
||||||
{
|
export {
|
||||||
print-nullterm 'H''e''l''l''o'' ''W''o''r''l''d''!''\n''\0';
|
let main = λ{} ↦ {
|
||||||
|
print-nullterm "Hello World!\n";
|
||||||
|
|
||||||
/* test ratio
|
/* test ratio
|
||||||
*/
|
*/
|
||||||
|
@ -32,5 +33,6 @@
|
||||||
'\n''\0';
|
'\n''\0';
|
||||||
|
|
||||||
uint-machine-to-posint 16 256;
|
uint-machine-to-posint 16 256;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue