From a47dfd3d1417412f4d55ffa964d9fc98d8d53a9d Mon Sep 17 00:00:00 2001 From: johannst Date: Mon, 13 Sep 2021 22:26:20 +0000 Subject: deploy: 743f301eef632a41bd870529a9e838ce4974f9eb --- src/llvm_kaleidoscope_rs/parser.rs.html | 925 ++++++++++++++++++++++++++++++++ 1 file changed, 925 insertions(+) create mode 100644 src/llvm_kaleidoscope_rs/parser.rs.html (limited to 'src/llvm_kaleidoscope_rs/parser.rs.html') diff --git a/src/llvm_kaleidoscope_rs/parser.rs.html b/src/llvm_kaleidoscope_rs/parser.rs.html new file mode 100644 index 0000000..3bd0dc8 --- /dev/null +++ b/src/llvm_kaleidoscope_rs/parser.rs.html @@ -0,0 +1,925 @@ +parser.rs - source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+
+use crate::lexer::{Lexer, Token};
+
+#[derive(Debug, PartialEq)]
+pub enum ExprAST {
+    /// Number - Expression class for numeric literals like "1.0".
+    Number(f64),
+
+    /// Variable - Expression class for referencing a variable, like "a".
+    Variable(String),
+
+    /// Binary - Expression class for a binary operator.
+    Binary(char, Box<ExprAST>, Box<ExprAST>),
+
+    /// Call - Expression class for function calls.
+    Call(String, Vec<ExprAST>),
+}
+
+/// PrototypeAST - This class represents the "prototype" for a function,
+/// which captures its name, and its argument names (thus implicitly the number
+/// of arguments the function takes).
+#[derive(Debug, PartialEq)]
+pub struct PrototypeAST(pub String, pub Vec<String>);
+
+/// FunctionAST - This class represents a function definition itself.
+#[derive(Debug, PartialEq)]
+pub struct FunctionAST(pub PrototypeAST, pub ExprAST);
+
+/// Parse result with String as Error type (to be compliant with tutorial).
+type ParseResult<T> = Result<T, String>;
+
+/// Parser for the `kaleidoscope` language.
+pub struct Parser<I>
+where
+    I: Iterator<Item = char>,
+{
+    lexer: Lexer<I>,
+    cur_tok: Option<Token>,
+}
+
+impl<I> Parser<I>
+where
+    I: Iterator<Item = char>,
+{
+    pub fn new(lexer: Lexer<I>) -> Self {
+        Parser {
+            lexer,
+            cur_tok: None,
+        }
+    }
+
+    // -----------------------
+    //   Simple Token Buffer
+    // -----------------------
+
+    /// Implement the global variable `int CurTok;` from the tutorial.
+    ///
+    /// # Panics
+    /// Panics if the parser doesn't have a current token.
+    pub fn cur_tok(&self) -> &Token {
+        self.cur_tok.as_ref().expect("Parser: Expected cur_token!")
+    }
+
+    /// Advance the `cur_tok` by getting the next token from the lexer.
+    ///
+    /// Implement the fucntion `int getNextToken();` from the tutorial.
+    pub fn get_next_token(&mut self) {
+        self.cur_tok = Some(self.lexer.gettok());
+    }
+
+    // ----------------------------
+    //   Basic Expression Parsing
+    // ----------------------------
+
+    /// numberexpr ::= number
+    ///
+    /// Implement `std::unique_ptr<ExprAST> ParseNumberExpr();` from the tutorial.
+    fn parse_num_expr(&mut self) -> ParseResult<ExprAST> {
+        match *self.cur_tok() {
+            Token::Number(num) => {
+                // Consume the number token.
+                self.get_next_token();
+                Ok(ExprAST::Number(num))
+            }
+            _ => unreachable!(),
+        }
+    }
+
+    /// parenexpr ::= '(' expression ')'
+    ///
+    /// Implement `std::unique_ptr<ExprAST> ParseParenExpr();` from the tutorial.
+    fn parse_paren_expr(&mut self) -> ParseResult<ExprAST> {
+        // Eat '(' token.
+        assert_eq!(*self.cur_tok(), Token::Char('('));
+        self.get_next_token();
+
+        let v = self.parse_expression()?;
+
+        if *self.cur_tok() == Token::Char(')') {
+            // Eat ')' token.
+            self.get_next_token();
+            Ok(v)
+        } else {
+            Err("expected ')'".into())
+        }
+    }
+
+    /// identifierexpr
+    ///   ::= identifier
+    ///   ::= identifier '(' expression* ')'
+    ///
+    /// Implement `std::unique_ptr<ExprAST> ParseIdentifierExpr();` from the tutorial.
+    fn parse_identifier_expr(&mut self) -> ParseResult<ExprAST> {
+        let id_name = match self.cur_tok.take() {
+            Some(Token::Identifier(id)) => {
+                // Consume identifier.
+                self.get_next_token();
+                id
+            }
+            _ => unreachable!(),
+        };
+
+        if *self.cur_tok() != Token::Char('(') {
+            // Simple variable reference.
+            Ok(ExprAST::Variable(id_name))
+        } else {
+            // Call.
+
+            // Eat '(' token.
+            self.get_next_token();
+
+            let mut args: Vec<ExprAST> = Vec::new();
+
+            // If there are arguments collect them.
+            if *self.cur_tok() != Token::Char(')') {
+                loop {
+                    let arg = self.parse_expression()?;
+                    args.push(arg);
+
+                    if *self.cur_tok() == Token::Char(')') {
+                        // Eat ')' token.
+                        self.get_next_token();
+                        break;
+                    }
+
+                    if *self.cur_tok() != Token::Char(',') {
+                        return Err("Expected ')' or ',' in argument list".into());
+                    }
+
+                    self.get_next_token();
+                }
+            }
+
+            Ok(ExprAST::Call(id_name, args))
+        }
+    }
+
+    /// primary
+    ///   ::= identifierexpr
+    ///   ::= numberexpr
+    ///   ::= parenexpr
+    ///
+    /// Implement `std::unique_ptr<ExprAST> ParsePrimary();` from the tutorial.
+    fn parse_primary(&mut self) -> ParseResult<ExprAST> {
+        match *self.cur_tok() {
+            Token::Identifier(_) => self.parse_identifier_expr(),
+            Token::Number(_) => self.parse_num_expr(),
+            Token::Char('(') => self.parse_paren_expr(),
+            _ => Err("unknown token when expecting an expression".into()),
+        }
+    }
+
+    // -----------------------------
+    //   Binary Expression Parsing
+    // -----------------------------
+
+    /// /// expression
+    ///   ::= primary binoprhs
+    ///
+    /// Implement `std::unique_ptr<ExprAST> ParseExpression();` from the tutorial.
+    fn parse_expression(&mut self) -> ParseResult<ExprAST> {
+        let lhs = self.parse_primary()?;
+        self.parse_bin_op_rhs(0, lhs)
+    }
+
+    /// binoprhs
+    ///   ::= ('+' primary)*
+    ///
+    /// Implement `std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, std::unique_ptr<ExprAST> LHS);` from the tutorial.
+    fn parse_bin_op_rhs(&mut self, expr_prec: isize, mut lhs: ExprAST) -> ParseResult<ExprAST> {
+        loop {
+            let tok_prec = get_tok_precedence(self.cur_tok());
+
+            // Not a binary operator or precedence is too small.
+            if tok_prec < expr_prec {
+                return Ok(lhs);
+            }
+
+            let binop = match self.cur_tok.take() {
+                Some(Token::Char(c)) => {
+                    // Eat binary operator.
+                    self.get_next_token();
+                    c
+                }
+                _ => unreachable!(),
+            };
+
+            // lhs BINOP1 rhs BINOP2 remrhs
+            //     ^^^^^^     ^^^^^^
+            //     tok_prec   next_prec
+            //
+            // In case BINOP1 has higher precedence, we are done here and can build a 'Binary' AST
+            // node between 'lhs' and 'rhs'.
+            //
+            // In case BINOP2 has higher precedence, we take 'rhs' as 'lhs' and recurse into the
+            // 'remrhs' expression first.
+
+            // Parse primary expression after binary operator.
+            let mut rhs = self.parse_primary()?;
+
+            let next_prec = get_tok_precedence(self.cur_tok());
+            if tok_prec < next_prec {
+                // BINOP2 has higher precedence thatn BINOP1, recurse into 'remhs'.
+                rhs = self.parse_bin_op_rhs(tok_prec + 1, rhs)?
+            }
+
+            lhs = ExprAST::Binary(binop, Box::new(lhs), Box::new(rhs));
+        }
+    }
+
+    // --------------------
+    //   Parsing the Rest
+    // --------------------
+
+    /// prototype
+    ///   ::= id '(' id* ')'
+    ///
+    /// Implement `std::unique_ptr<PrototypeAST> ParsePrototype();` from the tutorial.
+    fn parse_prototype(&mut self) -> ParseResult<PrototypeAST> {
+        let id_name = match self.cur_tok.take() {
+            Some(Token::Identifier(id)) => {
+                // Consume the identifier.
+                self.get_next_token();
+                id
+            }
+            other => {
+                // Plug back current token.
+                self.cur_tok = other;
+                return Err("Expected function name in prototype".into());
+            }
+        };
+
+        if *self.cur_tok() != Token::Char('(') {
+            return Err("Expected '(' in prototype".into());
+        }
+
+        let mut args: Vec<String> = Vec::new();
+        loop {
+            self.get_next_token();
+
+            match self.cur_tok.take() {
+                Some(Token::Identifier(arg)) => args.push(arg),
+                Some(Token::Char(',')) => {}
+                other => {
+                    self.cur_tok = other;
+                    break;
+                }
+            }
+        }
+
+        if *self.cur_tok() != Token::Char(')') {
+            return Err("Expected ')' in prototype".into());
+        }
+
+        // Consume ')'.
+        self.get_next_token();
+
+        Ok(PrototypeAST(id_name, args))
+    }
+
+    /// definition ::= 'def' prototype expression
+    ///
+    /// Implement `std::unique_ptr<FunctionAST> ParseDefinition();` from the tutorial.
+    pub fn parse_definition(&mut self) -> ParseResult<FunctionAST> {
+        // Consume 'def' token.
+        assert_eq!(*self.cur_tok(), Token::Def);
+        self.get_next_token();
+
+        let proto = self.parse_prototype()?;
+        let expr = self.parse_expression()?;
+
+        Ok(FunctionAST(proto, expr))
+    }
+
+    /// external ::= 'extern' prototype
+    ///
+    /// Implement `std::unique_ptr<PrototypeAST> ParseExtern();` from the tutorial.
+    pub fn parse_extern(&mut self) -> ParseResult<PrototypeAST> {
+        // Consume 'extern' token.
+        assert_eq!(*self.cur_tok(), Token::Extern);
+        self.get_next_token();
+
+        self.parse_prototype()
+    }
+
+    /// toplevelexpr ::= expression
+    ///
+    /// Implement `std::unique_ptr<FunctionAST> ParseTopLevelExpr();` from the tutorial.
+    pub fn parse_top_level_expr(&mut self) -> ParseResult<FunctionAST> {
+        let e = self.parse_expression()?;
+        let proto = PrototypeAST("".into(), Vec::new());
+        Ok(FunctionAST(proto, e))
+    }
+}
+
+/// Get the binary operator precedence.
+///
+/// Implement `int GetTokPrecedence();` from the tutorial.
+fn get_tok_precedence(tok: &Token) -> isize {
+    match tok {
+        Token::Char('<') => 10,
+        Token::Char('+') => 20,
+        Token::Char('-') => 20,
+        Token::Char('*') => 40,
+        _ => -1,
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::{ExprAST, FunctionAST, Parser, PrototypeAST};
+    use crate::lexer::Lexer;
+
+    fn parser(input: &str) -> Parser<std::str::Chars> {
+        let l = Lexer::new(input.chars());
+        let mut p = Parser::new(l);
+
+        // Drop initial coin, initialize cur_tok.
+        p.get_next_token();
+
+        p
+    }
+
+    #[test]
+    fn parse_number() {
+        let mut p = parser("13.37");
+
+        assert_eq!(p.parse_num_expr(), Ok(ExprAST::Number(13.37f64)));
+    }
+
+    #[test]
+    fn parse_variable() {
+        let mut p = parser("foop");
+
+        assert_eq!(
+            p.parse_identifier_expr(),
+            Ok(ExprAST::Variable("foop".into()))
+        );
+    }
+
+    #[test]
+    fn parse_primary() {
+        let mut p = parser("1337 foop \n bla(123)");
+
+        assert_eq!(p.parse_primary(), Ok(ExprAST::Number(1337f64)));
+
+        assert_eq!(p.parse_primary(), Ok(ExprAST::Variable("foop".into())));
+
+        assert_eq!(
+            p.parse_primary(),
+            Ok(ExprAST::Call("bla".into(), vec![ExprAST::Number(123f64)]))
+        );
+    }
+
+    #[test]
+    fn parse_binary_op() {
+        // Operator before RHS has higher precedence, expected AST
+        //
+        //       -
+        //      / \
+        //     +     c
+        //    / \
+        //   a   b
+        let mut p = parser("a + b - c");
+
+        let binexpr_ab = ExprAST::Binary(
+            '+',
+            Box::new(ExprAST::Variable("a".into())),
+            Box::new(ExprAST::Variable("b".into())),
+        );
+
+        let binexpr_abc = ExprAST::Binary(
+            '-',
+            Box::new(binexpr_ab),
+            Box::new(ExprAST::Variable("c".into())),
+        );
+
+        assert_eq!(p.parse_expression(), Ok(binexpr_abc));
+    }
+
+    #[test]
+    fn parse_binary_op2() {
+        // Operator after RHS has higher precedence, expected AST
+        //
+        //       +
+        //      / \
+        //     a   *
+        //        / \
+        //       b   c
+        let mut p = parser("a + b * c");
+
+        let binexpr_bc = ExprAST::Binary(
+            '*',
+            Box::new(ExprAST::Variable("b".into())),
+            Box::new(ExprAST::Variable("c".into())),
+        );
+
+        let binexpr_abc = ExprAST::Binary(
+            '+',
+            Box::new(ExprAST::Variable("a".into())),
+            Box::new(binexpr_bc),
+        );
+
+        assert_eq!(p.parse_expression(), Ok(binexpr_abc));
+    }
+
+    #[test]
+    fn parse_prototype() {
+        let mut p = parser("foo(a,b)");
+
+        let proto = PrototypeAST("foo".into(), vec!["a".into(), "b".into()]);
+
+        assert_eq!(p.parse_prototype(), Ok(proto));
+    }
+
+    #[test]
+    fn parse_definition() {
+        let mut p = parser("def bar( arg0 , arg1 ) arg0 + arg1");
+
+        let proto = PrototypeAST("bar".into(), vec!["arg0".into(), "arg1".into()]);
+
+        let body = ExprAST::Binary(
+            '+',
+            Box::new(ExprAST::Variable("arg0".into())),
+            Box::new(ExprAST::Variable("arg1".into())),
+        );
+
+        let func = FunctionAST(proto, body);
+
+        assert_eq!(p.parse_definition(), Ok(func));
+    }
+
+    #[test]
+    fn parse_extern() {
+        let mut p = parser("extern baz()");
+
+        let proto = PrototypeAST("baz".into(), vec![]);
+
+        assert_eq!(p.parse_extern(), Ok(proto));
+    }
+}
+
+
\ No newline at end of file -- cgit v1.2.3