创建一个“编译器”来编辑字符串

时间:2014-05-22 10:51:09

标签: c# string compiler-construction

你好atm我正在摆弄创建编译器这是我尝试转换随机语言

输入:

import System;
import System.Collections.Generic;
import System.Linq;
import System.Text;
import System.IO;

class Compiler
BEGIN;

    private List : string Strings;

    function construct()
    BEGIN;
        Strings = new List : string();
    END;

    function void start ( a : int, b : int, c : int )
    BEGIN;

    END;

END;

输出:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

class Compiler
{

    private List < string Strings;


    {
        Strings = new List < string();
    }

    private void start ( int a,    int b,    int c,    
    {

    }

}

正如你所看到的那样,将我的代码编译成c#是有用的,除了列表我是如何编译它只是通过编辑字符串我试过没有教程只是为了好玩和尝试的东西(请不要&#39 ;看看我的编译器代码,它只是用随机的东西做的,我已经知道没有谷歌或任何东西),现在我已经搜索谷歌更好的解决但我还没有找到任何东西

这是我的编译器代码:

public void Compile(String input, String output)
        {
            DirectoryCopy(input, output, true);
            Console.WriteLine("Searching input directory for files.");
            string[] filePaths = Directory.GetFiles(input, "*.upl",SearchOption.AllDirectories);
            Console.WriteLine("Found " + filePaths.Count() + " file(s) In this directory and all sub directorys");
            Console.WriteLine("Start compiling? (Y/N)");
            if (Console.ReadLine().Equals("y"))
            {
                Console.WriteLine("Starting...");
                for (int p = 0; p < filePaths.Length; p++ )
                {
                    String[] lines = File.ReadAllLines(filePaths[p]);
                    for (int i = 0; i < lines.Length; i++)
                    {
                        lines[i] = lines[i].StartsWith("import ") ? lines[i].Replace("import", "using") : lines[i];

                        if (lines[i].Contains("function "))
                        {
                            lines[i] = lines[i].Replace("function", "private");
                            string[] split = lines[i].Split(' ');
                            for (int s = 0; s < split.Length; s++)
                            {
                                if (split[s].Contains(":"))
                                {
                                    if (split[s - 1].Contains("("))
                                    {
                                        if (split[s + 1].Contains(","))
                                        {
                                            string[] split2 = split[s + 1].Split(',');
                                            split[s - 1] = "( " + split2[0] + " " + split[s - 1][1] + ",";
                                            split[s] = string.Empty;
                                            split[s + 1] = split[s + 1].Split(',')[1];
                                        }
                                        else
                                        {
                                            split[s - 1] = "( " + split[s + 1] + " " + split[s - 1][1];
                                            split[s] = string.Empty;
                                            split[s + 1] = string.Empty;
                                        }
                                    }
                                    else if (split[s + 1].Contains(")"))
                                    {
                                        split[s + 1] = split[s + 1].Replace(")", "");
                                        split[s - 1] = split[s + 1] + " " + split[s - 1] + " )";
                                    }
                                    else
                                    {
                                        split[s - 1] = split[s + 1].Replace(",", "") + " " + split[s - 1] + ", ";
                                        split[s] = string.Empty;
                                        split[s + 1] = string.Empty;
                                    }
                                }
                            }
                            split[split.Length - 1] = string.Empty;
                            split[split.Length - 2] = string.Empty;
                            lines[i] = String.Join(" ", split);
                        }

                        if (lines[i].Contains("if") || lines[i].Contains("foreach"))
                        {
                            bool insert = false;
                            for (int i2 = 2; i2 < lines[i].Length; i2++)
                            {
                                if (!char.IsLetter(lines[i][i2]))
                                {
                                    if (insert == false)
                                    {
                                        char[] letters = lines[i].ToCharArray();
                                        letters[i2] = '(';
                                        lines[i] = String.Join("", letters);
                                        insert = true;
                                    }
                                }
                            }
                            lines[i] = !lines[i].EndsWith("BEGIN;") ? lines[i] + ")" : lines[i];
                            lines[i] = lines[i].Contains(":") ? lines[i].Replace(":", "in") : lines[i];
                        }

                        if (lines[i].Contains("Message"))
                        {
                            lines[i] = lines[i].Replace("Message", "MessageBox.Show(");
                            lines[i] = lines[i].Replace(";", " );");
                        }

                        if (lines[i].Contains("List") && lines[i].Contains(":"))
                        {
                            int spaces = 0;
                            char[] letters = lines[i].ToCharArray();
                            for (int c = 0; c < letters.Length; c++)
                            {
                                letters[c] = char.Equals(letters[c], ':') ? '<' : letters[c];
                                if (char.Equals(letters[c], '<'))
                                    break;
                                spaces = char.IsWhiteSpace(letters[c]) ? spaces + 1 : spaces;
                            }
                            lines[i] = String.Join("", letters);
                            string[] spacesArr = lines[i].Split(' ');
                        }

                        lines[i] = lines[i].EndsWith("BEGIN;") || lines[i].StartsWith("BEGIN") ? lines[i].Replace("BEGIN;", "{") : lines[i];
                        lines[i] = lines[i].EndsWith("END;") || lines[i].Contains("END;") ? lines[i].Replace("END;", "}") : lines[i];
                    }
                    double completion = ((double)(p + 1) / (double)filePaths.Length) * 100;
                    Console.WriteLine("Compiled file " + (p + 1) + " of the total " + filePaths.Length + " file(s). (" + (int)completion + "%)");
                    int pathleng2 = output.Split('\\').Count();
                    string[] filepath = filePaths[p].Split('\\');
                    string subPath = String.Join("\\", filepath, pathleng2, (filePaths[p].Split('\\').Count() - input.Split('\\').Count()));
                    subPath = subPath.Replace("upl", "cs");
                    File.WriteAllLines(output + "\\" + subPath, lines);
                }
            }
        }

所以我的问题是:

有没有人知道如何解决这个问题?用字或类似的东西分割字符串?也许是一个标记器?如果可能在c#

如果您有任何问题,请随时问我。

3 个答案:

答案 0 :(得分:1)

您正在创建一个C#代码生成器而不是编译器:它将您自己的语言作为输入并创建C#代码作为输出。

执行此类操作的好工具是C#Irony解析器。此解析器将允许您定义和解析自己的语言。这会给你一个解析树;这是在某个对象模型中表示您的语言。一旦你有了这个解析树,你需要将它转换为C#。

根据我的经验,定义语言并使用Irony解析它非常容易。将解析树转换为最终格式是一个难点。

我已经使用Irony来解析Xamlr中的XAML标记扩展:源代码可能会为您提供有关如何入门的一些想法。

答案 1 :(得分:1)

对于你提到的基本任务,任何解析器生成器都适合 - C#并不缺少它们。已经提到IronyCoco/RGOLDANTLRLLLPGSprache或我的NLT

一句话 - 你向我们展示的代码是不正确的C#。

如果你想编译,这是完全不同的任务,因为我假设你编译到非常具体的目标 - .Net。因此,您的代码必须可以从其他.Net代码中使用,反之亦然。因此,有这个想法,你只是&#34;简单&#34;创建另一种.Net语言。问题不在于编译,而是在.Net中保持正确。

可能我不会选择其他任何事情Roslyn

答案 2 :(得分:0)

不要在一种方法中推翻所有逻辑。创建一个解析器类,它实现了帮助器方法,以帮助您转换每个字符,类似于.NET读取器,但没有流作为输入。我没有让你失去你的项目,但你的尝试并没有真正去任何地方。在继续之前,请考虑先编写更简单的解析器,如CSV或BB代码。这是一个很好的机会。还要记住,您不直接将文本从一种格式转换为另一种格式,您需要一个中间类来首先携带解析后的元素,然后将其传递给代码生成器。请注意,术语编译器用于生成字节代码而不是文本的组件。