authorgravatar for 11367844+lino-levan@users.noreply.github.comLino Le Van <11367844+lino-levan@users.noreply.github.com> 2024-02-03 05:35:35+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-02-02 20:35:35-08:00
logb417db0d1e1f2ce026092e1b310e2c98e7de265f
tree4c7bb64084c4459c10264cf2a00fa4ca9069ef4a
parent4d577446b981a403ff6131f0b15451f125316af0
signature Signed by PGP key B5690EEEBB952194

feat(parser): track the location of source tokens (#8)

* feat: add loc * chore: start working on transition parser to include loc * chore: fix everything related to TokenType * feat: add loc to parser

16 files changed, 513 insertions(+), 421 deletions(-)

crates/ast/operators.rs+23-23
......@@ -1,4 +1,4 @@
1use tokenizer::Token;
1use tokenizer::TokenType;
22
33use crate::Literal;
44
......@@ -94,28 +94,28 @@ impl BinaryOperator {
9494 String::from(self.to_str())
9595 }
9696
97 pub fn from_token(token: &Token) -> Option<BinaryOperator> {
98 match token {
99 Token::And => Some(Self::BitAnd),
100 Token::AndAnd => Some(Self::And),
101 Token::BangEqual => Some(Self::NotEq),
102 Token::Caret => Some(Self::BitXor),
103 Token::EqualEqual => Some(Self::Eq),
104 Token::Gt => Some(Self::Gt),
105 Token::GtEqual => Some(Self::Gte),
106 Token::GtGt => Some(Self::Rshift),
107 Token::GtGtGt => Some(Self::RshiftUnsigned),
108 Token::Lt => Some(Self::Lt),
109 Token::LtEqual => Some(Self::Lte),
110 Token::LtLt => Some(Self::Lshift),
111 Token::Minus => Some(Self::Sub),
112 Token::Or => Some(Self::BitOr),
113 Token::OrOr => Some(Self::Or),
114 Token::Percent => Some(Self::Mod),
115 Token::Plus => Some(Self::Add),
116 Token::Slash => Some(Self::Div),
117 Token::Star => Some(Self::Mul),
118 Token::StarStar => Some(Self::Pow),
97 pub fn from_token(token: &TokenType) -> Option<BinaryOperator> {
98 match &token {
99 TokenType::And => Some(Self::BitAnd),
100 TokenType::AndAnd => Some(Self::And),
101 TokenType::BangEqual => Some(Self::NotEq),
102 TokenType::Caret => Some(Self::BitXor),
103 TokenType::EqualEqual => Some(Self::Eq),
104 TokenType::Gt => Some(Self::Gt),
105 TokenType::GtEqual => Some(Self::Gte),
106 TokenType::GtGt => Some(Self::Rshift),
107 TokenType::GtGtGt => Some(Self::RshiftUnsigned),
108 TokenType::Lt => Some(Self::Lt),
109 TokenType::LtEqual => Some(Self::Lte),
110 TokenType::LtLt => Some(Self::Lshift),
111 TokenType::Minus => Some(Self::Sub),
112 TokenType::Or => Some(Self::BitOr),
113 TokenType::OrOr => Some(Self::Or),
114 TokenType::Percent => Some(Self::Mod),
115 TokenType::Plus => Some(Self::Add),
116 TokenType::Slash => Some(Self::Div),
117 TokenType::Star => Some(Self::Mul),
118 TokenType::StarStar => Some(Self::Pow),
119119 _ => None,
120120 }
121121 }
crates/js_ast/convert/convert_valid_block.rs+1
......@@ -26,6 +26,7 @@ pub fn convert_valid_block(ctx: &mut BlockConvertContext, block: Block, loc: Loc
2626 }
2727 JsExpr::new(JsExprData::Comma { items }, loc.clone(), None)
2828 }
29 _ => todo!(),
2930 };
3031
3132 // a block without implicit return is to be type void, so we wrap in a void expression
crates/parser/parse_block.rs+5-5
......@@ -1,12 +1,12 @@
11use crate::{parse_statement::parse_statement, Parser};
22use ast::Block;
33use miette::Result;
4use tokenizer::Token;
4use tokenizer::TokenType;
55
66/// Precondition: The first token exists and is '{'
77pub fn parse_block(p: &mut Parser) -> Result<Block> {
88 match p.next() {
9 Some(Token::OpenBrace) => (),
9 Some(TokenType::OpenBrace) => (),
1010 _ => unreachable!(),
1111 }
1212
......@@ -30,10 +30,10 @@ pub fn parse_block(p: &mut Parser) -> Result<Block> {
3030 statements.push(statement.clone());
3131
3232 match p.peek() {
33 Some(Token::Semicolon) => loop {
33 Some(TokenType::Semicolon) => loop {
3434 p.next();
3535 match p.peek() {
36 Some(Token::ClosedBrace) => {
36 Some(TokenType::ClosedBrace) => {
3737 p.next();
3838 p.is_top_level = was_top_level;
3939 return Ok(Block {
......@@ -44,7 +44,7 @@ pub fn parse_block(p: &mut Parser) -> Result<Block> {
4444 _ => continue 'outer,
4545 }
4646 },
47 Some(Token::ClosedBrace) => {
47 Some(TokenType::ClosedBrace) => {
4848 p.next();
4949 p.is_top_level = was_top_level;
5050
crates/parser/parse_call_arguments.rs+4-4
......@@ -1,6 +1,6 @@
11use ast::Expr;
22use miette::Result;
3use tokenizer::Token;
3use tokenizer::TokenType;
44
55use crate::{parse_expr::parse_expr, Parser};
66
......@@ -8,7 +8,7 @@ use crate::{parse_expr::parse_expr, Parser};
88pub fn parse_call_arguments(p: &mut Parser) -> Result<Vec<Expr>> {
99 let mut args = Vec::new();
1010
11 if let Some(Token::ClosedParen) = p.peek() {
11 if let Some(TokenType::ClosedParen) = p.peek() {
1212 _ = p.next();
1313 return Ok(args);
1414 }
......@@ -18,11 +18,11 @@ pub fn parse_call_arguments(p: &mut Parser) -> Result<Vec<Expr>> {
1818 args.push(arg);
1919
2020 match p.peek() {
21 Some(Token::Comma) => {
21 Some(TokenType::Comma) => {
2222 _ = p.next();
2323 continue;
2424 }
25 Some(Token::ClosedParen) => {
25 Some(TokenType::ClosedParen) => {
2626 _ = p.next();
2727 return Ok(args);
2828 }
crates/parser/parse_declaration.rs+8-8
......@@ -1,6 +1,6 @@
11use ast::{DocComment, Type, VarDecl};
22use miette::Result;
3use tokenizer::Token;
3use tokenizer::{Loc, TokenType};
44
55use crate::parse_expr::parse_expr;
66use crate::parse_type::parse_type;
......@@ -12,26 +12,26 @@ pub fn parse_declaration(
1212 is_pub: bool,
1313 comment: Option<DocComment>,
1414) -> Result<VarDecl> {
15 let loc = p.loc();
15 let start = p.index;
1616 let is_constant = match p.next() {
17 Some(Token::Var) => false,
18 Some(Token::Let) => true,
17 Some(TokenType::Var) => false,
18 Some(TokenType::Let) => true,
1919 _ => unreachable!(),
2020 };
2121 let name = match p.next() {
22 Some(Token::Identifier(name)) => name,
22 Some(TokenType::Identifier(name)) => name,
2323 Some(tok) => return Err(p.error(format!("Unexpected {}", tok)).into()),
2424 None => return Err(p.error(format!("Unexpected end of file")).into()),
2525 };
2626 let return_type = match p.peek() {
27 Some(Token::Colon) => {
27 Some(TokenType::Colon) => {
2828 p.next();
2929 parse_type(p)?
3030 }
3131 _ => Type::Infer,
3232 };
3333 let init = match p.next() {
34 Some(Token::Equal) => parse_expr(p)?,
34 Some(TokenType::Equal) => parse_expr(p)?,
3535 _ => {
3636 return Err(p
3737 .error("Variable must have an initializer".to_string())
......@@ -45,6 +45,6 @@ pub fn parse_declaration(
4545 is_constant,
4646 is_pub,
4747 comment,
48 loc,
48 loc: Loc::new(start, p.index - start),
4949 })
5050}
crates/parser/parse_doc_comment.rs+7-4
......@@ -1,14 +1,17 @@
11use ast::DocComment;
2use tokenizer::Token;
2use tokenizer::{Loc, TokenType};
33
44use crate::Parser;
55
66pub fn maybe_read_doc_comment(p: &mut Parser) -> Option<DocComment> {
77 match p.peek() {
8 Some(Token::DocComment(data)) => {
9 let loc = p.loc();
8 Some(TokenType::DocComment(data)) => {
9 let start = p.index;
1010 p.next();
11 Some(DocComment { data, loc })
11 Some(DocComment {
12 data,
13 loc: Loc::new(start, p.index - start),
14 })
1215 }
1316 _ => None,
1417 }
crates/parser/parse_expr.rs+3-2
......@@ -1,6 +1,7 @@
11use ast::Associativity::*;
22use ast::{BinaryOperator, Expr, ExprData, OperatorLevel};
33use miette::Result;
4use tokenizer::Loc;
45
56use crate::parse_expr_basic::parse_expr_basic;
67use crate::Parser;
......@@ -53,7 +54,7 @@ fn parse_expr_binary(
5354 left: Expr,
5455 level: OperatorLevel,
5556) -> Result<Expr> {
56 let loc = p.loc();
57 let start = p.index;
5758 let mut right = parse_expr_basic(p)?;
5859
5960 loop {
......@@ -93,7 +94,7 @@ fn parse_expr_binary(
9394 left: Box::new(left),
9495 right: Box::new(right),
9596 },
96 loc,
97 Loc::new(start, p.index - start),
9798 None,
9899 ))
99100}
crates/parser/parse_expr_basic.rs+85-43
......@@ -1,6 +1,6 @@
11use ast::{BuiltinId, Expr, ExprData, Literal, UnaryOperator};
22use miette::Result;
3use tokenizer::Token;
3use tokenizer::{Loc, TokenType};
44
55use crate::{
66 parse_block::parse_block, parse_call_arguments::parse_call_arguments, parse_expr::parse_expr,
......@@ -8,61 +8,87 @@ use crate::{
88};
99
1010pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> {
11 let loc = p.loc();
11 let start = p.index;
1212 let comments = p.take_comments();
1313 let mut expr = match p.peek() {
14 Some(Token::Number(number)) => {
14 Some(TokenType::Number(number)) => {
1515 _ = p.next();
1616 Expr::new(
1717 ExprData::Literal(Literal::Number(number.clone())),
18 loc,
18 Loc::new(start, p.index - start),
1919 comments,
2020 )
2121 }
22 Some(Token::String(string)) => {
22 Some(TokenType::String(string)) => {
2323 _ = p.next();
2424 Expr::new(
2525 ExprData::Literal(Literal::String(string.clone())),
26 loc,
26 Loc::new(start, p.index - start),
2727 comments,
2828 )
2929 }
30 Some(Token::True) => {
30 Some(TokenType::True) => {
3131 _ = p.next();
32 Expr::new(ExprData::Literal(Literal::Bool(true)), loc, comments)
32 Expr::new(
33 ExprData::Literal(Literal::Bool(true)),
34 Loc::new(start, p.index - start),
35 comments,
36 )
3337 }
34 Some(Token::False) => {
38 Some(TokenType::False) => {
3539 _ = p.next();
36 Expr::new(ExprData::Literal(Literal::Bool(false)), loc, comments)
40 Expr::new(
41 ExprData::Literal(Literal::Bool(false)),
42 Loc::new(start, p.index - start),
43 comments,
44 )
3745 }
38 Some(Token::Void) => {
46 Some(TokenType::Void) => {
3947 _ = p.next();
40 Expr::new(ExprData::Literal(Literal::Void), loc, comments)
48 Expr::new(
49 ExprData::Literal(Literal::Void),
50 Loc::new(start, p.index - start),
51 comments,
52 )
4153 }
42 Some(Token::Identifier(name)) => {
43 let loc = p.loc();
54 Some(TokenType::Identifier(name)) => {
55 let identifier_start = p.index;
4456 _ = p.next();
4557 if name.starts_with("@") {
4658 if let Some(id) = BuiltinId::from_str(name.as_str()) {
47 if let Some(Token::OpenParen) = p.next() {
59 if let Some(TokenType::OpenParen) = p.next() {
4860 let arguments = parse_call_arguments(p)?;
49 Expr::new(ExprData::Builtin { id, arguments }, loc, comments)
61 Expr::new(
62 ExprData::Builtin { id, arguments },
63 Loc::new(identifier_start, p.index - identifier_start),
64 comments,
65 )
5066 } else {
5167 return Err(p
52 .error_at(format!("Built-in function '{}' must be called", name), loc)
68 .error_at(
69 format!("Built-in function '{}' must be called", name),
70 Loc::new(identifier_start, p.index - identifier_start),
71 )
5372 .into());
5473 }
5574 } else {
5675 return Err(p
57 .error_at(format!("Non-existant built-in: '{}'", name), loc)
76 .error_at(
77 format!("Non-existant built-in: '{}'", name),
78 Loc::new(identifier_start, p.index - identifier_start),
79 )
5880 .into());
5981 }
6082 } else {
61 Expr::new(ExprData::Identifier(name), loc, comments)
83 Expr::new(
84 ExprData::Identifier(name),
85 Loc::new(identifier_start, p.index - identifier_start),
86 comments,
87 )
6288 }
6389 }
6490
65 Some(Token::Return) => {
91 Some(TokenType::Return) => {
6692 if p.is_top_level {
6793 return Err(p
6894 .error("'return' cannot be used at top level".to_string())
......@@ -71,19 +97,31 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> {
7197 _ = p.next();
7298 let inner = maybe_parse_expr_basic(p)?.map(Box::new);
7399
74 return Ok(Some(Expr::new(ExprData::Return(inner), loc, comments)));
100 return Ok(Some(Expr::new(
101 ExprData::Return(inner),
102 Loc::new(start, p.index - start),
103 comments,
104 )));
75105 }
76106 }
77107
78 Some(Token::If) => Expr::new(ExprData::If(parse_expr_if(p)?), loc, comments),
108 Some(TokenType::If) => Expr::new(
109 ExprData::If(parse_expr_if(p)?),
110 Loc::new(start, p.index - start),
111 comments,
112 ),
79113
80 Some(Token::OpenBrace) => Expr::new(ExprData::Block(parse_block(p)?), loc, comments),
114 Some(TokenType::OpenBrace) => Expr::new(
115 ExprData::Block(parse_block(p)?),
116 Loc::new(start, p.index - start),
117 comments,
118 ),
81119
82 Some(Token::OpenParen) => {
120 Some(TokenType::OpenParen) => {
83121 _ = p.next();
84122 let expr = parse_expr(p)?;
85123 match p.next() {
86 Some(Token::ClosedParen) => (),
124 Some(TokenType::ClosedParen) => (),
87125 Some(token) => {
88126 return Err(p.error(format!("Expected ')', but got {:?}", token)).into())
89127 }
......@@ -92,19 +130,19 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> {
92130 expr
93131 }
94132
95 Some(t @ Token::Bang) | Some(t @ Token::Minus) | Some(t @ Token::Tilde) => {
133 Some(t @ TokenType::Bang) | Some(t @ TokenType::Minus) | Some(t @ TokenType::Tilde) => {
96134 _ = p.next();
97135 Expr::new(
98136 ExprData::Unary {
99137 op: match t {
100 Token::Bang => UnaryOperator::Not,
101 Token::Minus => UnaryOperator::Neg,
102 Token::Tilde => UnaryOperator::BitNot,
138 TokenType::Bang => UnaryOperator::Not,
139 TokenType::Minus => UnaryOperator::Neg,
140 TokenType::Tilde => UnaryOperator::BitNot,
103141 _ => unreachable!(),
104142 },
105143 value: Box::new(parse_expr_basic(p)?),
106144 },
107 loc,
145 Loc::new(start, p.index - start),
108146 comments,
109147 )
110148 }
......@@ -115,14 +153,18 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> {
115153 // Parse function calls and field accesses
116154 loop {
117155 match p.peek() {
118 Some(Token::Dot) => {
119 let loc = p.loc();
156 Some(TokenType::Dot) => {
157 let field_start = p.index;
120158 _ = p.next();
121159 let field = match p.peek() {
122 Some(Token::Identifier(name)) => {
123 let loc = p.loc();
160 Some(TokenType::Identifier(name)) => {
161 let field_start = p.index;
124162 p.next();
125 Expr::new(ExprData::Literal(Literal::String(name)), loc, None)
163 Expr::new(
164 ExprData::Literal(Literal::String(name)),
165 Loc::new(field_start, p.index - field_start),
166 None,
167 )
126168 }
127169 _ => {
128170 return Err(p.error("Expected identifier after dot".to_string()).into());
......@@ -133,12 +175,12 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> {
133175 base: Box::new(expr),
134176 field: Box::new(field),
135177 },
136 loc,
178 Loc::new(field_start, p.index - field_start),
137179 None,
138180 );
139181 }
140 Some(Token::OpenParen) => {
141 let loc = p.loc();
182 Some(TokenType::OpenParen) => {
183 let expr_start = p.index;
142184 _ = p.next();
143185 let arguments = parse_call_arguments(p)?;
144186 expr = Expr::new(
......@@ -146,21 +188,21 @@ pub fn maybe_parse_expr_basic(p: &mut Parser) -> Result<Option<Expr>> {
146188 base: Box::new(expr),
147189 arguments,
148190 },
149 loc,
191 Loc::new(expr_start, p.index - expr_start),
150192 None,
151193 );
152194 }
153 Some(Token::OpenBracket) => {
154 let loc = p.loc();
195 Some(TokenType::OpenBracket) => {
196 let expr_start = p.index;
155197 _ = p.next();
156198 let index = parse_expr(p)?;
157 if let Some(Token::ClosedBracket) = p.next() {
199 if let Some(TokenType::ClosedBracket) = p.next() {
158200 expr = Expr::new(
159201 ExprData::Field {
160202 base: Box::new(expr),
161203 field: Box::new(index),
162204 },
163 loc,
205 Loc::new(expr_start, p.index - expr_start),
164206 None,
165207 );
166208 } else {
crates/parser/parse_expr_if.rs+11-11
......@@ -1,6 +1,6 @@
11use ast::{BlockOrIf, BlockWithLoc, If};
22use miette::Result;
3use tokenizer::Token;
3use tokenizer::{Loc, TokenType};
44
55use crate::parse_block::parse_block;
66use crate::parse_expr::parse_expr;
......@@ -9,12 +9,12 @@ use crate::Parser;
99/// Precondition: the first token exists and is 'if'
1010pub fn parse_expr_if(p: &mut Parser) -> Result<If> {
1111 match p.next() {
12 Some(Token::If) => (),
12 Some(TokenType::If) => (),
1313 _ => unreachable!(),
1414 }
1515
1616 match p.peek() {
17 Some(Token::OpenBrace) => {
17 Some(TokenType::OpenBrace) => {
1818 return Err(p
1919 .error(
2020 "To use a block as the condition for an if statement, wrap it in parentheses"
......@@ -28,11 +28,11 @@ pub fn parse_expr_if(p: &mut Parser) -> Result<If> {
2828 let condition = Box::new(parse_expr(p)?);
2929
3030 let yes = match p.peek() {
31 Some(Token::OpenBrace) => {
32 let loc = p.loc();
31 Some(TokenType::OpenBrace) => {
32 let block_start = p.index;
3333 BlockWithLoc {
3434 block: parse_block(p)?,
35 loc,
35 loc: Loc::new(block_start, p.index - block_start),
3636 }
3737 }
3838 _ => {
......@@ -43,18 +43,18 @@ pub fn parse_expr_if(p: &mut Parser) -> Result<If> {
4343 };
4444
4545 let no = match p.peek() {
46 Some(Token::Else) => {
46 Some(TokenType::Else) => {
4747 _ = p.next();
4848 match p.peek() {
49 Some(Token::OpenBrace) => {
50 let loc = p.loc();
49 Some(TokenType::OpenBrace) => {
50 let block_start = p.index;
5151 // let comments = p.take_comments();
5252 Some(BlockOrIf::Block(BlockWithLoc {
5353 block: parse_block(p)?,
54 loc,
54 loc: Loc::new(block_start, p.index - block_start),
5555 }))
5656 }
57 Some(Token::If) => {
57 Some(TokenType::If) => {
5858 // TODO(@paperdave): Save location for the if
5959 // let loc = p.loc();
6060 // let comments = p.take_comments();
crates/parser/parse_fn_declaration.rs+20-16
......@@ -1,6 +1,6 @@
11use ast::{DocComment, Expr, ExprData, FnDecl, Type};
22use miette::Result;
3use tokenizer::Token;
3use tokenizer::{Loc, TokenType};
44
55use crate::parse_block::parse_block;
66use crate::parse_expr::parse_expr;
......@@ -14,19 +14,19 @@ pub fn parse_fn_declaration(
1414 is_pub: bool,
1515 comment: Option<DocComment>,
1616) -> Result<FnDecl> {
17 let loc = p.loc();
17 let start = p.index;
1818 match p.next() {
19 Some(Token::Fn) => (),
19 Some(TokenType::Fn) => (),
2020 _ => unreachable!(),
2121 }
2222
2323 let name = match p.next() {
24 Some(Token::Identifier(name)) => name,
24 Some(TokenType::Identifier(name)) => name,
2525 _ => return Err(p.error("Expected identifier after 'fn'".to_string()).into()),
2626 };
2727
2828 match p.peek() {
29 Some(Token::OpenParen) => p.next(),
29 Some(TokenType::OpenParen) => p.next(),
3030 _ => {
3131 return Err(p
3232 .error("Expected '(' after function name".to_string())
......@@ -38,22 +38,22 @@ pub fn parse_fn_declaration(
3838
3939 loop {
4040 match p.peek() {
41 Some(Token::ClosedParen) => {
41 Some(TokenType::ClosedParen) => {
4242 _ = p.next();
4343 break;
4444 }
45 Some(Token::Identifier(_)) => {
45 Some(TokenType::Identifier(_)) => {
4646 params.push(parse_param(p)?);
4747
4848 match p.peek() {
49 Some(Token::Comma) => {
49 Some(TokenType::Comma) => {
5050 p.next();
51 if let Some(Token::ClosedParen) = p.peek() {
51 if let Some(TokenType::ClosedParen) = p.peek() {
5252 p.next();
5353 break;
5454 }
5555 }
56 Some(Token::ClosedParen) => {
56 Some(TokenType::ClosedParen) => {
5757 p.next();
5858 break;
5959 }
......@@ -77,7 +77,7 @@ pub fn parse_fn_declaration(
7777 }
7878
7979 let return_type = match p.peek() {
80 Some(Token::RightArrow) => {
80 Some(TokenType::RightArrow) => {
8181 _ = p.next();
8282 parse_type(p)?
8383 }
......@@ -88,12 +88,16 @@ pub fn parse_fn_declaration(
8888 p.is_in_fn = true;
8989
9090 let body = match p.peek() {
91 Some(Token::OpenBrace) => {
92 let block_loc = p.loc();
91 Some(TokenType::OpenBrace) => {
92 let block_start = p.index;
9393 let block = parse_block(p)?;
94 Expr::new(ExprData::Block(block), block_loc, None)
94 Expr::new(
95 ExprData::Block(block),
96 Loc::new(block_start, p.index - block_start),
97 None,
98 )
9599 }
96 Some(Token::BigRightArrow) => {
100 Some(TokenType::BigRightArrow) => {
97101 _ = p.next();
98102 parse_expr(p)?
99103 }
......@@ -117,6 +121,6 @@ pub fn parse_fn_declaration(
117121 body,
118122 is_pub,
119123 comment,
120 loc,
124 loc: Loc::new(start, p.index - start),
121125 })
122126}
crates/parser/parse_module.rs+3-3
......@@ -3,7 +3,7 @@ use crate::parse_top_level_statement::parse_top_level_statement;
33use crate::Parser;
44use ast::Module;
55use miette::Result;
6use tokenizer::Token;
6use tokenizer::TokenType;
77
88pub fn parse_module(p: &mut Parser) -> Result<Module> {
99 let mut statements = Vec::new();
......@@ -18,8 +18,8 @@ pub fn parse_module(p: &mut Parser) -> Result<Module> {
1818 let statement = parse_top_level_statement(p)?;
1919
2020 match p.peek() {
21 Some(Token::Semicolon) => {
22 while let Some(Token::Semicolon) = p.peek() {
21 Some(TokenType::Semicolon) => {
22 while let Some(TokenType::Semicolon) = p.peek() {
2323 p.next();
2424 }
2525 }
crates/parser/parse_param.rs+3-3
......@@ -1,18 +1,18 @@
11use ast::Param;
22use miette::Result;
3use tokenizer::Token;
3use tokenizer::TokenType;
44
55use crate::{parse_type::parse_type, Parser};
66
77/// Precondition: A token exists and is an identifier
88pub fn parse_param(p: &mut Parser) -> Result<Param> {
99 let name = match p.next() {
10 Some(Token::Identifier(name)) => name.clone(),
10 Some(TokenType::Identifier(name)) => name.clone(),
1111 _ => unreachable!(),
1212 };
1313
1414 let param_type = match p.peek() {
15 Some(Token::Colon) => {
15 Some(TokenType::Colon) => {
1616 _ = p.next();
1717 parse_type(p)?
1818 }
crates/parser/parse_statement.rs+9-11
......@@ -1,6 +1,6 @@
11use ast::Statement;
22use miette::Result;
3use tokenizer::Token;
3use tokenizer::TokenType;
44
55use crate::parse_declaration::parse_declaration;
66use crate::parse_doc_comment::maybe_read_doc_comment;
......@@ -24,8 +24,8 @@ pub fn parse_statement(p: &mut Parser) -> Result<Statement> {
2424 }
2525
2626 match p.peek() {
27 Some(Token::DocComment(_)) => unreachable!(),
28 Some(Token::Pub) => {
27 Some(TokenType::DocComment(_)) => unreachable!(),
28 Some(TokenType::Pub) => {
2929 if !p.is_top_level {
3030 return Err(p
3131 .error("Public declarations are not allowed inside of functions".to_string())
......@@ -33,12 +33,10 @@ pub fn parse_statement(p: &mut Parser) -> Result<Statement> {
3333 }
3434 _ = p.next();
3535 match p.peek() {
36 Some(Token::Var) | Some(Token::Let) => Ok(Statement::VarDecl(parse_declaration(
37 p,
38 true,
39 m_doc_comment,
40 )?)),
41 Some(Token::Fn) => Ok(Statement::FnDecl(parse_fn_declaration(
36 Some(TokenType::Var) | Some(TokenType::Let) => Ok(Statement::VarDecl(
37 parse_declaration(p, true, m_doc_comment)?,
38 )),
39 Some(TokenType::Fn) => Ok(Statement::FnDecl(parse_fn_declaration(
4240 p,
4341 true,
4442 m_doc_comment,
......@@ -47,12 +45,12 @@ pub fn parse_statement(p: &mut Parser) -> Result<Statement> {
4745 None => Err(p.error("Unexpected end of file".to_string()).into()),
4846 }
4947 }
50 Some(Token::Var) | Some(Token::Let) => Ok(Statement::VarDecl(parse_declaration(
48 Some(TokenType::Var) | Some(TokenType::Let) => Ok(Statement::VarDecl(parse_declaration(
5149 p,
5250 false,
5351 m_doc_comment,
5452 )?)),
55 Some(Token::Fn) => Ok(Statement::FnDecl(parse_fn_declaration(
53 Some(TokenType::Fn) => Ok(Statement::FnDecl(parse_fn_declaration(
5654 p,
5755 false,
5856 m_doc_comment,
crates/parser/parse_type.rs+2-2
......@@ -1,13 +1,13 @@
11use ast::Type;
22use miette::Result;
33
4use tokenizer::Token;
4use tokenizer::TokenType;
55
66use crate::Parser;
77
88pub fn parse_type(p: &mut Parser) -> Result<Type> {
99 match p.next() {
10 Some(Token::Identifier(id)) => match id.as_str() {
10 Some(TokenType::Identifier(id)) => match id.as_str() {
1111 "int" => Ok(Type::Int),
1212 "float" => Ok(Type::Float),
1313 "bigint" => Ok(Type::BigInt),
crates/parser/parser.rs+13-10
......@@ -19,6 +19,7 @@ use miette::Result;
1919use parse_module::parse_module;
2020use thiserror::Error;
2121use tokenizer::tokenize;
22use tokenizer::TokenType;
2223use tokenizer::{Loc, Token};
2324
2425pub fn parse(tokens: Vec<Token>) -> Result<Module> {
......@@ -52,6 +53,9 @@ pub struct Parser {
5253 tokens: Vec<Token>,
5354 cursor: usize,
5455
56 /// Current index in the string
57 pub index: usize,
58
5559 /// Whether or not the parser is at the top level.
5660 /// Currently controls the validity of `pub` keywords.
5761 pub is_top_level: bool,
......@@ -67,6 +71,7 @@ impl Parser {
6771 Parser {
6872 tokens,
6973 cursor: 0,
74 index: 0,
7075 is_top_level: true,
7176 is_in_fn: false,
7277 comments: vec![],
......@@ -77,14 +82,16 @@ impl Parser {
7782 self.cursor == self.tokens.len()
7883 }
7984
80 pub fn next(&mut self) -> Option<Token> {
85 pub fn next(&mut self) -> Option<TokenType> {
8186 if self.cursor == self.tokens.len() {
8287 return None;
8388 }
8489
8590 loop {
86 match self.tokens[self.cursor].clone() {
87 Token::Comment(comment) => {
91 let token = self.tokens[self.cursor].clone();
92 self.index = token.loc.start;
93 match token.variant {
94 TokenType::Comment(comment) => {
8895 self.comments.push(comment);
8996 self.cursor += 1;
9097 continue;
......@@ -113,14 +120,14 @@ impl Parser {
113120 self.comments.len() > 0
114121 }
115122
116 pub fn peek(&mut self) -> Option<Token> {
123 pub fn peek(&mut self) -> Option<TokenType> {
117124 loop {
118125 if self.cursor == self.tokens.len() {
119126 return None;
120127 }
121128
122 match self.tokens[self.cursor].clone() {
123 Token::Comment(comment) => {
129 match self.tokens[self.cursor].clone().variant {
130 TokenType::Comment(comment) => {
124131 self.comments.push(comment);
125132 self.cursor += 1;
126133 continue;
......@@ -137,10 +144,6 @@ impl Parser {
137144 ParseError::new(error, None)
138145 }
139146
140 fn loc(&self) -> Loc {
141 return Loc {};
142 }
143
144147 fn error_at(&self, error: String, loc: Loc) -> ParseError {
145148 ParseError::new(error, Some(loc))
146149 }
crates/tokenizer/tokenizer.rs+316-276
......@@ -2,14 +2,24 @@ use miette::{Diagnostic, Result};
22use thiserror::Error;
33
44#[derive(Debug, PartialEq, Clone)]
5pub struct Loc {}
5pub struct Loc {
6 pub start: usize,
7 pub length: usize,
8}
69
710impl Loc {
811 /// TODO(@paperdave): Remove this. every usage of this is incorrect.
9 pub const EMPTY: Loc = Loc {};
12 pub const EMPTY: Loc = Loc {
13 start: 0,
14 length: 0,
15 };
16
17 pub fn new(start: usize, length: usize) -> Self {
18 Self { start, length }
19 }
1020
11 pub fn new() -> Self {
12 Self {}
21 pub fn len(&self) -> usize {
22 self.length
1323 }
1424}
1525
......@@ -20,8 +30,8 @@ struct UnknownCharacter {
2030 error: String,
2131}
2232
23#[derive(Debug, Clone)]
24pub enum Token {
33#[derive(Debug, Clone, PartialEq)]
34pub enum TokenType {
2535 // Literals
2636 Identifier(String),
2737 Number(f64),
......@@ -78,77 +88,92 @@ pub enum Token {
7888 Tilde, // ~
7989}
8090
81impl Token {
91impl TokenType {
8292 pub fn is_start_of_statement_like_expression(&self) -> bool {
8393 match &self {
84 Token::If | Token::OpenBrace => true,
94 TokenType::If | TokenType::OpenBrace => true,
8595 _ => false,
8696 }
8797 }
8898}
8999
90impl std::fmt::Display for Token {
100impl std::fmt::Display for TokenType {
91101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92 let token = match self {
93 Token::Identifier(_) => "identifier".to_string(),
102 let token = match &self {
103 TokenType::Identifier(_) => "identifier".to_string(),
94104
95 Token::Number(n) => n.to_string(),
96 Token::String(s) => format!("\"{}\"", s),
97 Token::Comment(_) => "comment".to_string(),
98 Token::DocComment(_) => "documentation comment".to_string(),
105 TokenType::Number(n) => n.to_string(),
106 TokenType::String(s) => format!("\"{}\"", s),
107 TokenType::Comment(_) => "comment".to_string(),
108 TokenType::DocComment(_) => "documentation comment".to_string(),
99109
100 Token::Else => "else".to_string(),
101 Token::False => "false".to_string(),
102 Token::Fn => "fn".to_string(),
103 Token::If => "if".to_string(),
104 Token::Let => "let".to_string(),
105 Token::Pub => "pub".to_string(),
106 Token::Return => "return".to_string(),
107 Token::True => "true".to_string(),
108 Token::Var => "var".to_string(),
109 Token::Void => "void".to_string(),
110 TokenType::Else => "else".to_string(),
111 TokenType::False => "false".to_string(),
112 TokenType::Fn => "fn".to_string(),
113 TokenType::If => "if".to_string(),
114 TokenType::Let => "let".to_string(),
115 TokenType::Pub => "pub".to_string(),
116 TokenType::Return => "return".to_string(),
117 TokenType::True => "true".to_string(),
118 TokenType::Var => "var".to_string(),
119 TokenType::Void => "void".to_string(),
110120
111 Token::And => "&".to_string(),
112 Token::AndAnd => "&&".to_string(),
113 Token::Bang => "!".to_string(),
114 Token::BangEqual => "!=".to_string(),
115 Token::BigRightArrow => "=>".to_string(),
116 Token::Caret => "^".to_string(),
117 Token::ClosedBrace => "}".to_string(),
118 Token::ClosedBracket => "]".to_string(),
119 Token::ClosedParen => ")".to_string(),
120 Token::Colon => ":".to_string(),
121 Token::Comma => ",".to_string(),
122 Token::Dot => ".".to_string(),
123 Token::Equal => "=".to_string(),
124 Token::EqualEqual => "==".to_string(),
125 Token::Gt => ">".to_string(),
126 Token::GtEqual => ">=".to_string(),
127 Token::GtGt => ">>".to_string(),
128 Token::GtGtGt => ">>>".to_string(),
129 Token::Lt => "<".to_string(),
130 Token::LtEqual => "<=".to_string(),
131 Token::LtLt => "<<".to_string(),
132 Token::Minus => "-".to_string(),
133 Token::OpenBrace => "{".to_string(),
134 Token::OpenBracket => "[".to_string(),
135 Token::OpenParen => "(".to_string(),
136 Token::Or => "|".to_string(),
137 Token::OrOr => "||".to_string(),
138 Token::Percent => "%".to_string(),
139 Token::Plus => "+".to_string(),
140 Token::RightArrow => "->".to_string(),
141 Token::Semicolon => ";".to_string(),
142 Token::Slash => "/".to_string(),
143 Token::Star => "*".to_string(),
144 Token::StarStar => "**".to_string(),
145 Token::Tilde => "~".to_string(),
121 TokenType::And => "&".to_string(),
122 TokenType::AndAnd => "&&".to_string(),
123 TokenType::Bang => "!".to_string(),
124 TokenType::BangEqual => "!=".to_string(),
125 TokenType::BigRightArrow => "=>".to_string(),
126 TokenType::Caret => "^".to_string(),
127 TokenType::ClosedBrace => "}".to_string(),
128 TokenType::ClosedBracket => "]".to_string(),
129 TokenType::ClosedParen => ")".to_string(),
130 TokenType::Colon => ":".to_string(),
131 TokenType::Comma => ",".to_string(),
132 TokenType::Dot => ".".to_string(),
133 TokenType::Equal => "=".to_string(),
134 TokenType::EqualEqual => "==".to_string(),
135 TokenType::Gt => ">".to_string(),
136 TokenType::GtEqual => ">=".to_string(),
137 TokenType::GtGt => ">>".to_string(),
138 TokenType::GtGtGt => ">>>".to_string(),
139 TokenType::Lt => "<".to_string(),
140 TokenType::LtEqual => "<=".to_string(),
141 TokenType::LtLt => "<<".to_string(),
142 TokenType::Minus => "-".to_string(),
143 TokenType::OpenBrace => "{".to_string(),
144 TokenType::OpenBracket => "[".to_string(),
145 TokenType::OpenParen => "(".to_string(),
146 TokenType::Or => "|".to_string(),
147 TokenType::OrOr => "||".to_string(),
148 TokenType::Percent => "%".to_string(),
149 TokenType::Plus => "+".to_string(),
150 TokenType::RightArrow => "->".to_string(),
151 TokenType::Semicolon => ";".to_string(),
152 TokenType::Slash => "/".to_string(),
153 TokenType::Star => "*".to_string(),
154 TokenType::StarStar => "**".to_string(),
155 TokenType::Tilde => "~".to_string(),
146156 };
147157
148158 write!(f, "{}", token)
149159 }
150160}
151161
162#[derive(Debug, Clone)]
163pub struct Token {
164 pub variant: TokenType,
165 pub loc: Loc,
166}
167
168impl Token {
169 pub fn new(variant: TokenType, start: usize, length: usize) -> Self {
170 Self {
171 variant,
172 loc: Loc::new(start, length),
173 }
174 }
175}
176
152177// TODO(@paperdave): rewrite this to not use a Vec<Token>. we probably dont need it. also store Loc
153178pub fn tokenize(content: String) -> Result<Vec<Token>> {
154179 let mut tokens: Vec<Token> = Vec::new();
......@@ -156,251 +181,266 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> {
156181
157182 loop {
158183 match chars.next() {
159 Some((_, c)) => match c {
160 'a'..='z' | 'A'..='Z' | '_' | '@' => {
161 let mut current_token = String::new();
162 current_token.push(c);
163 loop {
164 let c = chars.peek();
165 if c.is_none() {
166 break;
167 }
168 let (_, c) = c.unwrap();
169 match c {
170 'a'..='z' | 'A'..='Z' | '_' | '0'..='9' => {
171 current_token.push(*c);
172 chars.next();
184 Some((start, c)) => {
185 let token = match c {
186 'a'..='z' | 'A'..='Z' | '_' | '@' => {
187 let mut current_token = String::new();
188 current_token.push(c);
189 loop {
190 let c = chars.peek();
191 if c.is_none() {
192 break;
193 }
194 let (_, c) = c.unwrap();
195 match c {
196 'a'..='z' | 'A'..='Z' | '_' | '0'..='9' => {
197 current_token.push(*c);
198 chars.next();
199 }
200 _ => break,
173201 }
174 _ => break,
175202 }
176 }
177203
178 match current_token.as_str() {
179 "else" => tokens.push(Token::Else),
180 "false" => tokens.push(Token::False),
181 "fn" => tokens.push(Token::Fn),
182 "if" => tokens.push(Token::If),
183 "let" => tokens.push(Token::Let),
184 "pub" => tokens.push(Token::Pub),
185 "return" => tokens.push(Token::Return),
186 "true" => tokens.push(Token::True),
187 "var" => tokens.push(Token::Var),
188 "void" => tokens.push(Token::Void),
189 _ => tokens.push(Token::Identifier(current_token)),
204 let length = current_token.len();
205
206 let variant = match current_token.as_str() {
207 "else" => TokenType::Else,
208 "false" => TokenType::False,
209 "fn" => TokenType::Fn,
210 "if" => TokenType::If,
211 "let" => TokenType::Let,
212 "pub" => TokenType::Pub,
213 "return" => TokenType::Return,
214 "true" => TokenType::True,
215 "var" => TokenType::Var,
216 "void" => TokenType::Void,
217 _ => TokenType::Identifier(current_token),
218 };
219
220 Token::new(variant, start, length)
190221 }
191 }
192 '"' => {
193 let mut current_token = String::new();
194 loop {
195 let c = chars.next();
196 if c.is_none() {
197 break;
198 }
199 let (_, c) = c.unwrap();
200 match c {
201 '"' => break,
202 _ => current_token.push(c),
222 '"' => {
223 let mut length = 1;
224 let mut current_token = String::new();
225 loop {
226 let c = chars.next();
227 if c.is_none() {
228 break;
229 }
230 let (_, c) = c.unwrap();
231 length += 1;
232 match c {
233 '"' => break,
234 _ => current_token.push(c),
235 }
203236 }
237 Token::new(TokenType::String(current_token), start, length)
204238 }
205 tokens.push(Token::String(current_token));
206 }
207 '0'..='9' => {
208 let mut current_token = String::new();
209 current_token.push(c);
210 loop {
211 let c = chars.peek();
212 if c.is_none() {
213 break;
214 }
215 let (_, c) = c.unwrap();
216 match c {
217 '0'..='9' => {
218 current_token.push(*c);
219 chars.next();
239 '0'..='9' => {
240 let mut current_token = String::new();
241 current_token.push(c);
242 loop {
243 let c = chars.peek();
244 if c.is_none() {
245 break;
246 }
247 let (_, c) = c.unwrap();
248 match c {
249 '0'..='9' => {
250 current_token.push(*c);
251 chars.next();
252 }
253 _ => break,
220254 }
221 _ => break,
222255 }
223 }
224 match current_token.parse::<f64>() {
225 Ok(v) => tokens.push(Token::Number(v)),
226 Err(_) => {
227 return Err(UnknownCharacter {
228 error: format!("Unknown character: {}", current_token),
256 match current_token.parse::<f64>() {
257 Ok(v) => Token::new(TokenType::Number(v), start, current_token.len()),
258 Err(_) => {
259 return Err(UnknownCharacter {
260 error: format!("Unknown character: {}", current_token),
261 }
262 .into())
229263 }
230 .into())
231264 }
232265 }
233 }
234 ':' => tokens.push(Token::Colon),
235 '=' => match chars.peek() {
236 Some((_, '=')) => {
237 chars.next();
238 tokens.push(Token::EqualEqual);
239 }
240 Some((_, '>')) => {
241 chars.next();
242 tokens.push(Token::BigRightArrow);
243 }
244 _ => tokens.push(Token::Equal),
245 },
246 ';' => tokens.push(Token::Semicolon),
247 '>' => match chars.peek() {
248 Some((_, '=')) => {
249 chars.next();
250 tokens.push(Token::GtEqual);
251 }
252 Some((_, '>')) => {
253 chars.next();
254 match chars.peek() {
255 Some((_, '>')) => {
256 chars.next();
257 tokens.push(Token::GtGtGt);
266 ':' => Token::new(TokenType::Colon, start, 1),
267 '=' => match chars.peek() {
268 Some((_, '=')) => {
269 chars.next();
270 Token::new(TokenType::EqualEqual, start, 2)
271 }
272 Some((_, '>')) => {
273 chars.next();
274 Token::new(TokenType::BigRightArrow, start, 2)
275 }
276 _ => Token::new(TokenType::Equal, start, 1),
277 },
278 ';' => Token::new(TokenType::Semicolon, start, 1),
279 '>' => match chars.peek() {
280 Some((_, '=')) => {
281 chars.next();
282 Token::new(TokenType::GtEqual, start, 2)
283 }
284 Some((_, '>')) => {
285 chars.next();
286 match chars.peek() {
287 Some((_, '>')) => {
288 chars.next();
289 Token::new(TokenType::GtGtGt, start, 3)
290 }
291 _ => Token::new(TokenType::GtGt, start, 2),
258292 }
259 _ => tokens.push(Token::GtGt),
260293 }
261 }
262 _ => tokens.push(Token::Gt),
263 },
264 '<' => match chars.peek() {
265 Some((_, '=')) => {
266 chars.next();
267 tokens.push(Token::LtEqual);
268 }
269 Some((_, '<')) => {
270 chars.next();
271 tokens.push(Token::LtLt);
272 }
273 _ => tokens.push(Token::Lt),
274 },
275 '+' => tokens.push(Token::Plus),
276 '-' => match chars.peek() {
277 Some((_, '>')) => {
278 chars.next();
279 tokens.push(Token::RightArrow);
280 }
281 _ => tokens.push(Token::Minus),
282 },
283 '*' => match chars.peek() {
284 Some((_, '*')) => {
285 chars.next();
286 tokens.push(Token::StarStar);
287 }
288 _ => tokens.push(Token::Star),
289 },
290 '/' => {
291 match chars.peek() {
292 Some((_, '/')) => {
293 chars.next(); // Consume the second slash
294 _ => Token::new(TokenType::Gt, start, 1),
295 },
296 '<' => match chars.peek() {
297 Some((_, '=')) => {
298 chars.next();
299 Token::new(TokenType::LtEqual, start, 2)
300 }
301 Some((_, '<')) => {
302 chars.next();
303 Token::new(TokenType::LtLt, start, 2)
304 }
305 _ => Token::new(TokenType::Lt, start, 1),
306 },
307 '+' => Token::new(TokenType::Plus, start, 1),
308 '-' => match chars.peek() {
309 Some((_, '>')) => {
310 chars.next();
311 Token::new(TokenType::RightArrow, start, 2)
312 }
313 _ => Token::new(TokenType::Minus, start, 1),
314 },
315 '*' => match chars.peek() {
316 Some((_, '*')) => {
317 chars.next();
318 Token::new(TokenType::StarStar, start, 2)
319 }
320 _ => Token::new(TokenType::Star, start, 1),
321 },
322 '/' => {
323 match chars.peek() {
324 Some((_, '/')) => {
325 chars.next(); // Consume the second slash
326 let mut length = 2;
294327
295 let is_doc_comment = match chars.peek() {
296 Some((_, '/')) => {
297 chars.next(); // Consume the third slash
298 true
299 }
300 _ => false,
301 };
328 let is_doc_comment = match chars.peek() {
329 Some((_, '/')) => {
330 chars.next(); // Consume the third slash
331 length += 1;
332 true
333 }
334 _ => false,
335 };
302336
303 let mut comment = String::new();
304 loop {
305 // skip leading whitespace
306 while let Some((_, c)) = chars.peek() {
307 if !c.is_whitespace() {
308 break;
337 let mut comment = String::new();
338 loop {
339 // skip leading whitespace
340 while let Some((_, c)) = chars.peek() {
341 if !c.is_whitespace() {
342 break;
343 }
344 chars.next();
345 length += 1;
309346 }
310 chars.next();
311 }
312 // read the comment
313 while let Some((_, c)) = chars.next() {
314 if c == '\n' || c == '\r' {
315 break;
347 // read the comment
348 while let Some((_, c)) = chars.next() {
349 length += 1;
350 if c == '\n' || c == '\r' {
351 break;
352 }
353 comment.push(c);
316354 }
317 comment.push(c);
318 }
319 // trim trailing whitespace on line
320 comment = comment.trim_end().to_string();
321 // skip to next non-whitespace character
322 while let Some((_, c)) = chars.peek() {
323 if !c.is_whitespace() {
324 break;
355 // trim trailing whitespace on line
356 comment = comment.trim_end().to_string();
357 // skip to next non-whitespace character
358 while let Some((_, c)) = chars.peek() {
359 if !c.is_whitespace() {
360 break;
361 }
362 chars.next();
363 length += 1;
325364 }
326 chars.next();
327 }
328 // check if we've hit another comment
329 let mut tmp = chars.clone();
365 // check if we've hit another comment
366 let mut tmp = chars.clone();
330367
331 let is_another_comment = match tmp.peek() {
332 Some((_, '/')) => {
333 tmp.next(); // Consume the second slash
334 match tmp.peek() {
335 Some((_, '/')) => {
336 tmp.next(); // Consume the third slash
337 is_doc_comment
368 let is_another_comment = match tmp.peek() {
369 Some((_, '/')) => {
370 tmp.next(); // Consume the second slash
371 match tmp.peek() {
372 Some((_, '/')) => {
373 tmp.next(); // Consume the third slash
374 is_doc_comment
375 }
376 _ => !is_doc_comment,
338377 }
339 _ => !is_doc_comment,
340378 }
379 _ => false,
380 };
381
382 if is_another_comment {
383 // apply our temporary iterator to the main iterator
384 comment.push('\n');
385 chars = tmp;
386 chars.next();
387 length += 1;
388 } else {
389 break;
341390 }
342 _ => false,
343 };
391 }
344392
345 if is_another_comment {
346 // apply our temporary iterator to the main iterator
347 comment.push('\n');
348 chars = tmp;
349 chars.next();
393 if is_doc_comment {
394 Token::new(TokenType::DocComment(comment), start, length)
350395 } else {
351 break;
396 Token::new(TokenType::Comment(comment), start, length)
352397 }
353398 }
354
355 if is_doc_comment {
356 tokens.push(Token::DocComment(comment));
357 } else {
358 tokens.push(Token::Comment(comment));
359 }
399 _ => Token::new(TokenType::Slash, start, 1),
360400 }
361 _ => tokens.push(Token::Slash),
362 }
363 }
364 ',' => tokens.push(Token::Comma),
365 '(' => tokens.push(Token::OpenParen),
366 ')' => tokens.push(Token::ClosedParen),
367 '{' => tokens.push(Token::OpenBrace),
368 '}' => tokens.push(Token::ClosedBrace),
369 '[' => tokens.push(Token::OpenBracket),
370 ']' => tokens.push(Token::ClosedBracket),
371 '&' => match chars.peek() {
372 Some((_, '&')) => {
373 chars.next();
374 tokens.push(Token::AndAnd);
375 }
376 _ => tokens.push(Token::And),
377 },
378 '|' => match chars.peek() {
379 Some((_, '|')) => {
380 chars.next();
381 tokens.push(Token::OrOr);
382401 }
383 _ => tokens.push(Token::Or),
384 },
385 '!' => match chars.peek() {
386 Some((_, '=')) => {
387 chars.next();
388 tokens.push(Token::BangEqual);
389 }
390 _ => tokens.push(Token::Bang),
391 },
392 '^' => tokens.push(Token::Caret),
393 '%' => tokens.push(Token::Percent),
394 '~' => tokens.push(Token::Tilde),
395 '.' => tokens.push(Token::Dot),
396 s if s.is_whitespace() => (),
397 _ => {
398 return Err(UnknownCharacter {
399 error: format!("Unexpected '{}' while tokenizing", c),
402 ',' => Token::new(TokenType::Comma, start, 1),
403 '(' => Token::new(TokenType::OpenParen, start, 1),
404 ')' => Token::new(TokenType::ClosedParen, start, 1),
405 '{' => Token::new(TokenType::OpenBrace, start, 1),
406 '}' => Token::new(TokenType::ClosedBrace, start, 1),
407 '[' => Token::new(TokenType::OpenBracket, start, 1),
408 ']' => Token::new(TokenType::ClosedBracket, start, 1),
409 '&' => match chars.peek() {
410 Some((_, '&')) => {
411 chars.next();
412 Token::new(TokenType::AndAnd, start, 2)
413 }
414 _ => Token::new(TokenType::And, start, 1),
415 },
416 '|' => match chars.peek() {
417 Some((_, '|')) => {
418 chars.next();
419 Token::new(TokenType::OrOr, start, 2)
420 }
421 _ => Token::new(TokenType::Or, start, 1),
422 },
423 '!' => match chars.peek() {
424 Some((_, '=')) => {
425 chars.next();
426 Token::new(TokenType::BangEqual, start, 2)
427 }
428 _ => Token::new(TokenType::Bang, start, 1),
429 },
430 '^' => Token::new(TokenType::Caret, start, 1),
431 '%' => Token::new(TokenType::Percent, start, 1),
432 '~' => Token::new(TokenType::Tilde, start, 1),
433 '.' => Token::new(TokenType::Dot, start, 1),
434 s if s.is_whitespace() => continue,
435 _ => {
436 return Err(UnknownCharacter {
437 error: format!("Unexpected '{}' while tokenizing", c),
438 }
439 .into())
400440 }
401 .into())
402 }
403 },
441 };
442 tokens.push(token);
443 }
404444 None => break,
405445 }
406446 }