Skip to main content

libperl_macrogen/
pp_expr.rs

1//! プリプロセッサ条件式の評価
2//!
3//! #if / #elif ディレクティブの条件式を評価する。
4
5use crate::error::{CompileError, PPError};
6use crate::intern::{InternedStr, StringInterner};
7use crate::macro_def::MacroTable;
8use crate::source::SourceLocation;
9use crate::token::{Token, TokenKind};
10
11/// プリプロセッサ式評価器
12pub struct PPExprEvaluator<'a> {
13    tokens: &'a [Token],
14    pos: usize,
15    interner: &'a StringInterner,
16    macros: &'a MacroTable,
17    loc: SourceLocation,
18    /// "defined" キーワードのインターン済み文字列
19    defined_id: Option<InternedStr>,
20}
21
22impl<'a> PPExprEvaluator<'a> {
23    /// 新しい評価器を作成
24    pub fn new(
25        tokens: &'a [Token],
26        interner: &'a StringInterner,
27        macros: &'a MacroTable,
28        loc: SourceLocation,
29    ) -> Self {
30        // "defined" を検索
31        let defined_id = interner.lookup("defined");
32
33        Self {
34            tokens,
35            pos: 0,
36            interner,
37            macros,
38            loc,
39            defined_id,
40        }
41    }
42
43    /// 条件式を評価
44    pub fn evaluate(&mut self) -> Result<i64, CompileError> {
45        let result = self.expr()?;
46        Ok(result)
47    }
48
49    /// 現在のトークンを取得
50    fn current(&self) -> Option<&Token> {
51        self.tokens.get(self.pos)
52    }
53
54    /// 現在のトークン種別を取得
55    fn current_kind(&self) -> Option<&TokenKind> {
56        self.current().map(|t| &t.kind)
57    }
58
59    /// 次へ進む
60    fn advance(&mut self) {
61        if self.pos < self.tokens.len() {
62            self.pos += 1;
63        }
64    }
65
66    /// エラーを生成
67    fn error(&self, msg: &str) -> CompileError {
68        CompileError::Preprocess {
69            loc: self.loc.clone(),
70            kind: PPError::InvalidCondition(msg.to_string()),
71        }
72    }
73
74    /// 条件式 (ternary)
75    fn expr(&mut self) -> Result<i64, CompileError> {
76        let cond = self.logical_or()?;
77
78        if matches!(self.current_kind(), Some(TokenKind::Question)) {
79            self.advance();
80            let then_val = self.expr()?;
81            if !matches!(self.current_kind(), Some(TokenKind::Colon)) {
82                return Err(self.error("expected ':' in ternary expression"));
83            }
84            self.advance();
85            let else_val = self.expr()?;
86            Ok(if cond != 0 { then_val } else { else_val })
87        } else {
88            Ok(cond)
89        }
90    }
91
92    /// 論理OR
93    fn logical_or(&mut self) -> Result<i64, CompileError> {
94        let mut left = self.logical_and()?;
95
96        while matches!(self.current_kind(), Some(TokenKind::PipePipe)) {
97            self.advance();
98            let right = self.logical_and()?;
99            left = if left != 0 || right != 0 { 1 } else { 0 };
100        }
101
102        Ok(left)
103    }
104
105    /// 論理AND
106    fn logical_and(&mut self) -> Result<i64, CompileError> {
107        let mut left = self.bitwise_or()?;
108
109        while matches!(self.current_kind(), Some(TokenKind::AmpAmp)) {
110            self.advance();
111            let right = self.bitwise_or()?;
112            left = if left != 0 && right != 0 { 1 } else { 0 };
113        }
114
115        Ok(left)
116    }
117
118    /// ビットOR
119    fn bitwise_or(&mut self) -> Result<i64, CompileError> {
120        let mut left = self.bitwise_xor()?;
121
122        while matches!(self.current_kind(), Some(TokenKind::Pipe)) {
123            self.advance();
124            let right = self.bitwise_xor()?;
125            left |= right;
126        }
127
128        Ok(left)
129    }
130
131    /// ビットXOR
132    fn bitwise_xor(&mut self) -> Result<i64, CompileError> {
133        let mut left = self.bitwise_and()?;
134
135        while matches!(self.current_kind(), Some(TokenKind::Caret)) {
136            self.advance();
137            let right = self.bitwise_and()?;
138            left ^= right;
139        }
140
141        Ok(left)
142    }
143
144    /// ビットAND
145    fn bitwise_and(&mut self) -> Result<i64, CompileError> {
146        let mut left = self.equality()?;
147
148        while matches!(self.current_kind(), Some(TokenKind::Amp)) {
149            self.advance();
150            let right = self.equality()?;
151            left &= right;
152        }
153
154        Ok(left)
155    }
156
157    /// 等価比較
158    fn equality(&mut self) -> Result<i64, CompileError> {
159        let mut left = self.relational()?;
160
161        loop {
162            match self.current_kind() {
163                Some(TokenKind::EqEq) => {
164                    self.advance();
165                    let right = self.relational()?;
166                    left = if left == right { 1 } else { 0 };
167                }
168                Some(TokenKind::BangEq) => {
169                    self.advance();
170                    let right = self.relational()?;
171                    left = if left != right { 1 } else { 0 };
172                }
173                _ => break,
174            }
175        }
176
177        Ok(left)
178    }
179
180    /// 関係比較
181    fn relational(&mut self) -> Result<i64, CompileError> {
182        let mut left = self.shift()?;
183
184        loop {
185            match self.current_kind() {
186                Some(TokenKind::Lt) => {
187                    self.advance();
188                    let right = self.shift()?;
189                    left = if left < right { 1 } else { 0 };
190                }
191                Some(TokenKind::Gt) => {
192                    self.advance();
193                    let right = self.shift()?;
194                    left = if left > right { 1 } else { 0 };
195                }
196                Some(TokenKind::LtEq) => {
197                    self.advance();
198                    let right = self.shift()?;
199                    left = if left <= right { 1 } else { 0 };
200                }
201                Some(TokenKind::GtEq) => {
202                    self.advance();
203                    let right = self.shift()?;
204                    left = if left >= right { 1 } else { 0 };
205                }
206                _ => break,
207            }
208        }
209
210        Ok(left)
211    }
212
213    /// シフト演算
214    fn shift(&mut self) -> Result<i64, CompileError> {
215        let mut left = self.additive()?;
216
217        loop {
218            match self.current_kind() {
219                Some(TokenKind::LtLt) => {
220                    self.advance();
221                    let right = self.additive()?;
222                    left <<= right;
223                }
224                Some(TokenKind::GtGt) => {
225                    self.advance();
226                    let right = self.additive()?;
227                    left >>= right;
228                }
229                _ => break,
230            }
231        }
232
233        Ok(left)
234    }
235
236    /// 加減算
237    fn additive(&mut self) -> Result<i64, CompileError> {
238        let mut left = self.multiplicative()?;
239
240        loop {
241            match self.current_kind() {
242                Some(TokenKind::Plus) => {
243                    self.advance();
244                    let right = self.multiplicative()?;
245                    left = left.wrapping_add(right);
246                }
247                Some(TokenKind::Minus) => {
248                    self.advance();
249                    let right = self.multiplicative()?;
250                    left = left.wrapping_sub(right);
251                }
252                _ => break,
253            }
254        }
255
256        Ok(left)
257    }
258
259    /// 乗除算
260    fn multiplicative(&mut self) -> Result<i64, CompileError> {
261        let mut left = self.unary()?;
262
263        loop {
264            match self.current_kind() {
265                Some(TokenKind::Star) => {
266                    self.advance();
267                    let right = self.unary()?;
268                    left = left.wrapping_mul(right);
269                }
270                Some(TokenKind::Slash) => {
271                    self.advance();
272                    let right = self.unary()?;
273                    if right == 0 {
274                        return Err(self.error("division by zero"));
275                    }
276                    left /= right;
277                }
278                Some(TokenKind::Percent) => {
279                    self.advance();
280                    let right = self.unary()?;
281                    if right == 0 {
282                        return Err(self.error("modulo by zero"));
283                    }
284                    left %= right;
285                }
286                _ => break,
287            }
288        }
289
290        Ok(left)
291    }
292
293    /// 単項演算
294    fn unary(&mut self) -> Result<i64, CompileError> {
295        match self.current_kind() {
296            Some(TokenKind::Plus) => {
297                self.advance();
298                self.unary()
299            }
300            Some(TokenKind::Minus) => {
301                self.advance();
302                Ok(-self.unary()?)
303            }
304            Some(TokenKind::Bang) => {
305                self.advance();
306                let val = self.unary()?;
307                Ok(if val == 0 { 1 } else { 0 })
308            }
309            Some(TokenKind::Tilde) => {
310                self.advance();
311                Ok(!self.unary()?)
312            }
313            _ => self.primary(),
314        }
315    }
316
317    /// 一次式
318    fn primary(&mut self) -> Result<i64, CompileError> {
319        match self.current_kind().cloned() {
320            Some(TokenKind::IntLit(n)) => {
321                self.advance();
322                Ok(n)
323            }
324            Some(TokenKind::UIntLit(n)) => {
325                self.advance();
326                Ok(n as i64)
327            }
328            Some(TokenKind::CharLit(c)) => {
329                self.advance();
330                Ok(c as i64)
331            }
332            Some(TokenKind::WideCharLit(c)) => {
333                self.advance();
334                Ok(c as i64)
335            }
336            Some(TokenKind::LParen) => {
337                self.advance();
338                let val = self.expr()?;
339                if !matches!(self.current_kind(), Some(TokenKind::RParen)) {
340                    return Err(self.error("expected ')'"));
341                }
342                self.advance();
343                Ok(val)
344            }
345            Some(TokenKind::Ident(id)) => {
346                // defined演算子のチェック
347                if Some(id) == self.defined_id {
348                    self.advance();
349                    return self.parse_defined();
350                }
351
352                // 未定義の識別子は0として扱う(C標準)
353                self.advance();
354                Ok(0)
355            }
356            Some(_) => Err(self.error("unexpected token in preprocessor expression")),
357            None => Err(self.error("unexpected end of expression")),
358        }
359    }
360
361    /// defined演算子をパース
362    fn parse_defined(&mut self) -> Result<i64, CompileError> {
363        let has_paren = matches!(self.current_kind(), Some(TokenKind::LParen));
364        if has_paren {
365            self.advance();
366        }
367
368        // 識別子またはキーワードを受け入れる
369        // キーワードも #define で定義される可能性があるため
370        let name = match self.current_kind() {
371            Some(TokenKind::Ident(id)) => Some(*id),
372            Some(kind) if kind.is_keyword() => {
373                // キーワードの名前を取得して検索
374                // インターンされていなければマクロとして定義されていない
375                let kw_name = kind.format(self.interner);
376                self.interner.lookup(&kw_name)
377            }
378            _ => return Err(self.error("expected identifier after 'defined'")),
379        };
380        self.advance();
381
382        if has_paren {
383            if !matches!(self.current_kind(), Some(TokenKind::RParen)) {
384                return Err(self.error("expected ')' after identifier in 'defined'"));
385            }
386            self.advance();
387        }
388
389        // nameがNoneの場合、マクロは定義されていない
390        Ok(match name {
391            Some(n) if self.macros.is_defined(n) => 1,
392            _ => 0,
393        })
394    }
395}
396
397#[cfg(test)]
398mod tests {
399    use super::*;
400    use crate::macro_def::MacroDef;
401    use crate::source::FileId;
402
403    fn make_token(kind: TokenKind) -> Token {
404        Token::new(kind, SourceLocation::default())
405    }
406
407    fn eval_tokens(tokens: &[Token], interner: &StringInterner, macros: &MacroTable) -> i64 {
408        let loc = SourceLocation::new(FileId::default(), 1, 1);
409        let mut eval = PPExprEvaluator::new(tokens, interner, macros, loc);
410        eval.evaluate().unwrap()
411    }
412
413    #[test]
414    fn test_simple_number() {
415        let interner = StringInterner::new();
416        let macros = MacroTable::new();
417        let tokens = vec![make_token(TokenKind::IntLit(42))];
418
419        assert_eq!(eval_tokens(&tokens, &interner, &macros), 42);
420    }
421
422    #[test]
423    fn test_arithmetic() {
424        let interner = StringInterner::new();
425        let macros = MacroTable::new();
426
427        // 2 + 3
428        let tokens = vec![
429            make_token(TokenKind::IntLit(2)),
430            make_token(TokenKind::Plus),
431            make_token(TokenKind::IntLit(3)),
432        ];
433        assert_eq!(eval_tokens(&tokens, &interner, &macros), 5);
434
435        // 10 - 4 * 2
436        let tokens = vec![
437            make_token(TokenKind::IntLit(10)),
438            make_token(TokenKind::Minus),
439            make_token(TokenKind::IntLit(4)),
440            make_token(TokenKind::Star),
441            make_token(TokenKind::IntLit(2)),
442        ];
443        assert_eq!(eval_tokens(&tokens, &interner, &macros), 2);
444    }
445
446    #[test]
447    fn test_comparison() {
448        let interner = StringInterner::new();
449        let macros = MacroTable::new();
450
451        // 5 > 3
452        let tokens = vec![
453            make_token(TokenKind::IntLit(5)),
454            make_token(TokenKind::Gt),
455            make_token(TokenKind::IntLit(3)),
456        ];
457        assert_eq!(eval_tokens(&tokens, &interner, &macros), 1);
458
459        // 2 == 3
460        let tokens = vec![
461            make_token(TokenKind::IntLit(2)),
462            make_token(TokenKind::EqEq),
463            make_token(TokenKind::IntLit(3)),
464        ];
465        assert_eq!(eval_tokens(&tokens, &interner, &macros), 0);
466    }
467
468    #[test]
469    fn test_logical() {
470        let interner = StringInterner::new();
471        let macros = MacroTable::new();
472
473        // 1 && 0
474        let tokens = vec![
475            make_token(TokenKind::IntLit(1)),
476            make_token(TokenKind::AmpAmp),
477            make_token(TokenKind::IntLit(0)),
478        ];
479        assert_eq!(eval_tokens(&tokens, &interner, &macros), 0);
480
481        // 1 || 0
482        let tokens = vec![
483            make_token(TokenKind::IntLit(1)),
484            make_token(TokenKind::PipePipe),
485            make_token(TokenKind::IntLit(0)),
486        ];
487        assert_eq!(eval_tokens(&tokens, &interner, &macros), 1);
488    }
489
490    #[test]
491    fn test_ternary() {
492        let interner = StringInterner::new();
493        let macros = MacroTable::new();
494
495        // 1 ? 10 : 20
496        let tokens = vec![
497            make_token(TokenKind::IntLit(1)),
498            make_token(TokenKind::Question),
499            make_token(TokenKind::IntLit(10)),
500            make_token(TokenKind::Colon),
501            make_token(TokenKind::IntLit(20)),
502        ];
503        assert_eq!(eval_tokens(&tokens, &interner, &macros), 10);
504
505        // 0 ? 10 : 20
506        let tokens = vec![
507            make_token(TokenKind::IntLit(0)),
508            make_token(TokenKind::Question),
509            make_token(TokenKind::IntLit(10)),
510            make_token(TokenKind::Colon),
511            make_token(TokenKind::IntLit(20)),
512        ];
513        assert_eq!(eval_tokens(&tokens, &interner, &macros), 20);
514    }
515
516    #[test]
517    fn test_defined() {
518        let mut interner = StringInterner::new();
519        let mut macros = MacroTable::new();
520
521        let foo = interner.intern("FOO");
522        let defined = interner.intern("defined");
523        let _ = defined; // 登録だけ
524
525        // FOO を定義
526        macros.define(MacroDef::object(foo, vec![], SourceLocation::default()), &interner);
527
528        // defined(FOO)
529        let tokens = vec![
530            make_token(TokenKind::Ident(interner.lookup("defined").unwrap())),
531            make_token(TokenKind::LParen),
532            make_token(TokenKind::Ident(foo)),
533            make_token(TokenKind::RParen),
534        ];
535        assert_eq!(eval_tokens(&tokens, &interner, &macros), 1);
536
537        // defined(BAR) - 未定義
538        let bar = interner.intern("BAR");
539        let tokens = vec![
540            make_token(TokenKind::Ident(interner.lookup("defined").unwrap())),
541            make_token(TokenKind::LParen),
542            make_token(TokenKind::Ident(bar)),
543            make_token(TokenKind::RParen),
544        ];
545        assert_eq!(eval_tokens(&tokens, &interner, &macros), 0);
546    }
547
548    #[test]
549    fn test_unary() {
550        let interner = StringInterner::new();
551        let macros = MacroTable::new();
552
553        // -5
554        let tokens = vec![
555            make_token(TokenKind::Minus),
556            make_token(TokenKind::IntLit(5)),
557        ];
558        assert_eq!(eval_tokens(&tokens, &interner, &macros), -5);
559
560        // !0
561        let tokens = vec![
562            make_token(TokenKind::Bang),
563            make_token(TokenKind::IntLit(0)),
564        ];
565        assert_eq!(eval_tokens(&tokens, &interner, &macros), 1);
566
567        // !1
568        let tokens = vec![
569            make_token(TokenKind::Bang),
570            make_token(TokenKind::IntLit(1)),
571        ];
572        assert_eq!(eval_tokens(&tokens, &interner, &macros), 0);
573    }
574
575    #[test]
576    fn test_parentheses() {
577        let interner = StringInterner::new();
578        let macros = MacroTable::new();
579
580        // (2 + 3) * 4
581        let tokens = vec![
582            make_token(TokenKind::LParen),
583            make_token(TokenKind::IntLit(2)),
584            make_token(TokenKind::Plus),
585            make_token(TokenKind::IntLit(3)),
586            make_token(TokenKind::RParen),
587            make_token(TokenKind::Star),
588            make_token(TokenKind::IntLit(4)),
589        ];
590        assert_eq!(eval_tokens(&tokens, &interner, &macros), 20);
591    }
592}