C#(我自己的编程语言) - 如何在解析时多次查找 PRINT STRING

本文关键字:STRING PRINT 查找 自己的 我自己 编程语言 | 更新日期: 2023-09-27 17:56:21

所以我目前正在基于 how Code 的 Python 编程语言制作自己的编程语言,但我只花了一个小时左右的时间尝试将其转换为 C#,它很棒,尽管当我告诉解析我们收集的令牌时,它只在找到 PRINT STRING 或令牌后解析一次, 然后就停了下来,

这是我的解析器、词法分析器、我的语言脚本和控制台的代码:

解析 器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BL
{
    public static class Parser
    {
        public static void Parse(string toks)
        {
            if (toks.Substring(0).Split(':')[0] == "PRINT STRING")
            {
                Console.WriteLine(toks.Substring(toks.IndexOf(''"') + 1).Split(''"')[0]);
            }
        }
    }
}

词法分析器:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BL
{
    public static class Lexer
    {
        public static string tok = "";
        public static string str;
        public static int state = 0;
        public static string tokens = "";
        public static void Lex(string data)
        {
            foreach (char c in data)
            {
                tok += c;
                if (tok == " ")
                {
                    if (state == 0)
                    {
                        tok = "";
                        tokens += " ";
                    }
                    else if (state == 1)
                    {
                        tok = " ";
                    }
                }
                else if (tok == Environment.NewLine)
                {
                    tok = "";
                }
                else if (tok == "PRINT")
                {
                    tokens += "PRINT";
                    tok = "";
                }
                else if (tok == "'"")
                {
                    if (state == 0)
                    {
                        state = 1;
                    }
                    else if (state == 1)
                    {
                        tokens += "STRING:" + str + "'" ";
                        str = "";
                        state = 0;
                        tok = "";
                    }
                }
                else if (state == 1)
                {
                    str += tok;
                    tok = "";
                }
            }
            Parser.Parse(tokens);
        }
    }
}

我的脚本:

PRINT "HELLO WORLD1" PRINT "HELLO WORLD2"

控制台:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace BL
{
    class Program
    {
        static string data;
        static void Main(string[] args)
        {
            Console.Title = "Compiler";
            string input = Console.ReadLine();
            Open(input);
            Lexer.Lex(data);
            Console.ReadLine();
        }
        public static void Open(string file)
        {
            data = File.ReadAllText(file);
        }
    }
}

当我打印令牌的内容(在 Lexer 中)时,我得到这个:

PRINT STRING:"HELLO WORLD1" PRINT STRING:"HELLO WORLD2"

虽然当我解析它时,它只打印 HELLO WORLD1,而不是 HELLO WORLD1 和它下面的 HELLO WORLD2,我不确定我应该怎么做才能获得另一个 PRINT STRING,显然因为这是一个只有我创建的项目,网上没有答案,提前谢谢。

C#(我自己的编程语言) - 如何在解析时多次查找 PRINT STRING

您正在尝试解析该语言,这很好,但随后您将生成第二种编程语言。 这意味着您的 Lex() 函数最终将需要它自己的解析逻辑来处理生成的文本。

这就是为什么大多数时候这类问题得到解决时,Lex() 函数将创建一个令牌列表供其他人使用。 通常,这些标记不仅仅是字符串,但对于许多小语言来说,可以使用简单的字符串列表作为标记。

由于我对玩具语言情有独钟,因此我修改了您的示例以遵循此流程。 它从用户输入加载文件,然后将其分解为单独的令牌,并使用这些令牌"运行"程序:

// Parse a list of tokens from Lex()
static void Parse(List<string> tokens)
{
    // Run through each token in the list of tokens
    for (int i = 0; i < tokens.Count; i++)
    {
        // And act on the token
        switch (tokens[i])
        {
            case "PRINT":
                // PRINT prints the next token
                // Move to the next token first
                i++;
                // And dump it out
                Console.WriteLine(tokens[i]);
                break;
            default:
                // Anything else is an error, so emit an error
                Console.WriteLine("ERROR: Unknown token " + tokens[i]);
                break;
        }
    }
}
// Parse a source code file, returning a list of tokens
static List<string> Lex(string data)
{
    // The current token we're building up
    string current = "";
    // Are we inside of a quoted string?
    bool inQuote = false;
    // The list of tokens to return
    List<string> tokens = new List<string>();
    foreach (char c in data)
    {
        if (inQuote)
        {
            switch (c)
            {
                case '"':
                    // The string literal has ended, go ahead and note 
                    // we're no longer in quote
                    inQuote = false;
                    break;
                default:
                    // Anything else gets added to the current token
                    current += c;
                    break;
            }
        }
        else
        {
            switch (c)
            {
                case '"':
                    // This is the start of a string literal, note that
                    // we're in it and move on
                    inQuote = true;
                    break;
                case ' ':
                case ''n':
                case ''r':
                case ''t':
                    // Tokens are sperated by whitespace, so any whitespace
                    // causes the current token to be added to the list of tokens
                    if (current.Length > 0)
                    {
                        // Only add tokens
                        tokens.Add(current);
                        current = "";
                    }
                    break;
                default:
                    // Anything else is part of a token, just add it
                    current += c;
                    break;
            }
        }
    }
    return tokens;
}
// Quick demo
static void Main(string[] args)
{
    string input = Console.ReadLine();
    string data = File.ReadAllText(input);
    List<string> tokens = Lex(data);
    Parse(tokens);
    Console.ReadLine();
}