iT邦幫忙

2025 iThome 鐵人賽

DAY 10
0

這邊實現簡單的 Parser,其中一個重要的概念不可變 Immutable + 結構共享 Structural Sharing,減少複製、簡化快取一致性。
成本:更多小物件 GC 壓力 -> 以 Pool + Lazy + table-driven 緩解。

其中的 Syntax Trees,Lexer 掃描 SourceText 建立 token,Parser 使用遞迴下降,帶表驅動優化建立樹。

using System;
using System.Collections.Generic;

namespace MiniRoslyn.Syntax
{
    // 節點基類 - 模仿 Green Node 概念(不可變)
    public abstract record Node;

    public record NumberNode(int Value) : Node;
    public record BinaryNode(string Op, Node Left, Node Right) : Node;

    public static class MiniParser
    {
        // 極簡:只處理 整數 + 加減乘
        public static Node Parse(string text)
        {
            var tokens = Tokenize(text);
            int pos = 0;
            return ParseExpr();

            Node ParseExpr()
            {
                Node node = ParseTerm();
                while (Match("+") || Match("-"))
                {
                    string op = tokens[pos - 1];
                    var right = ParseTerm();
                    node = new BinaryNode(op, node, right);
                }
                return node;
            }

            Node ParseTerm()
            {
                Node node = ParseFactor();
                while (Match("*"))
                {
                    string op = tokens[pos - 1];
                    var right = ParseFactor();
                    node = new BinaryNode(op, node, right);
                }
                return node;
            }

            Node ParseFactor()
            {
                if (Match("("))
                {
                    var e = ParseExpr();
                    Expect(")");
                    return e;
                }
                if (int.TryParse(Peek(), out var v))
                {
                    pos++;
                    return new NumberNode(v);
                }
                throw new Exception("Unexpected token: " + Peek());
            }

            bool Match(string t)
            {
                if (Peek() == t) { pos++; return true; }
                return false;
            }
            void Expect(string t)
            {
                if (!Match(t)) throw new Exception("Expect " + t);
            }
            string Peek() => pos < tokens.Count ? tokens[pos] : "<eof>";
        }

        static List<string> Tokenize(string text)
        {
            var list = new List<string>();
            for (int i = 0; i < text.Length; i++)
            {
                char c = text[i];
                if (char.IsWhiteSpace(c)) continue;
                if (char.IsDigit(c))
                {
                    int j = i;
                    while (j < text.Length && char.IsDigit(text[j])) j++;
                    list.Add(text[i..j]);
                    i = j - 1;
                    continue;
                }
                if ("+-*()".IndexOf(c) >= 0)
                {
                    list.Add(c.ToString());
                    continue;
                }
                throw new Exception("Invalid char: " + c);
            }
            return list;
        }
    }
}

上一篇
Workloads、AOT / Trim / Linking 整合
下一篇
Roslyn 語意分析
系列文
新 .NET & Azure & IoT & AI 開源技術實戰手冊 (含深入官方程式碼講解) 11
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言