Форум   Статьи   Новости   Файлы   Bugtraq   Сниффер   Друзья   О Клубе
Вернуться   HPC / Кодинг / .NET / C#
   
  Страница 1
  , 19:30   #1
Форумчанин
 
Регистрация: 05.02.2011
Сообщений: 58

Репутация: 0 / 0
По умолчанию Отделить код от текста, парсинг текстового файла

Суть задачи: есть вордовский файлик(допустим отчёт по курсовой) в котором есть текст и программный код(один или несколько). Каким образом можно спаристь код в документе?

Пока что есть такие соображения: пишем что-то типо синтаксического анализатора на несколько основных языков. Читаем 10 абзацов проверяем на каждый язык, сходство есть - читаем ещё одну строчку, проверяем и так пока не спарсим весь код. Если сходства нету - опять читаем 10 строчек но уже начиная со второй строчки и так же проверяем.


Как ещё можно это реализовать? Может есть какой-то алгоритм с помощью которого можно отделить текст, а не сам код(хотелось бы больше универсальности)? Каким ещё способом можно это реализовать. Буду благодарен за любую литературу по этому поводу.
 
Пользователь вне форума    
Наши Спонсоры
  , 08:26   #2
Местный
 
Локация: Cyberspace
Регистрация: 01.07.2008
Сообщений: 122

Репутация: 75 / 1
По умолчанию

Какие языки интересуют? в смысле распарсить в Word.
__________________
Live long and prosper.
[SIGPIC][/SIGPIC]
Пользователь вне форума    
  , 09:09   #3
Местный
 
Локация: Cyberspace
Регистрация: 01.07.2008
Сообщений: 122

Репутация: 75 / 1
По умолчанию

Какого вида код?
Например такие куски выделять?
code:
Какой то текст

Assembly a = Assembly.LoadWithPartialName("...");
Type[] types = a.GetTypes();
foreach (Type type in types)
{
...
}

продолжение текста документа
__________________
Live long and prosper.
[SIGPIC][/SIGPIC]
Пользователь вне форума    
  , 09:22   #4
Я вернулся
 
Аватар для Fantomas
 
Регистрация: 16.09.2009
Сообщений: 22

Репутация: 23 / 0
По умолчанию

Про регулярки почитай https://ru.wikipedia.org/wiki/%D0%A0...BD%D0%B8%D1%8F

Если речь идет о парсинге кода в тексте, то, как один из базовых вариантов: смотреть каждую строку на наличие спец. символов, ну, что-то вроде ";" в конце или скобок "{" и/или "}" наряду с символом присваивания "=" или скобками "(" или ")". Ну и конечно латинскими символами. Так же можно проверять на ключевые слова (например, if, else). И т.д. и т.п.
 
Пользователь вне форума    
  , 09:44   #5
Местный
 
Локация: Cyberspace
Регистрация: 01.07.2008
Сообщений: 122

Репутация: 75 / 1
По умолчанию

Цитата:
Сообщение от Fantomas Посмотреть сообщение
Если речь идет о парсинге кода в тексте, то, как один из базовых вариантов: смотреть каждую строку на наличие спец. символов, ну, что-то вроде ";" в конце или скобок "{" и/или "}" наряду с символом присваивания "=" или скобками "(" или ")". Ну и конечно латинскими символами. Так же можно проверять на ключевые слова (например, if, else). И т.д. и т.п.
Так-же по мимо символов можно поискать наличие основных методов в строке. Вот небольшой пример:
C# highlight
        public List<string> GetMethods ()
        {           
            List<string> res = new List<string>();

            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
            {
                Type[] types = a.GetTypes();
                foreach (Type type in types)
                {
                    if (!type.IsPublic)
                    {
                        continue;
                    }

                    MemberInfo[] members = type.GetMembers(BindingFlags.Public
                                                          | BindingFlags.Instance
                                                          | BindingFlags.InvokeMethod);
                    foreach (MemberInfo member in members)
                    {
                        if(!res.Contains(member.Name))
                            res.Add(member.Name);
                    }
                }
            }

            /// Добавляем основные служебные символы
            res.Add("if");
            res.Add("for");
            res.Add("while");
            res.Add("foreach");

            return res;
        }
        ...
        var allMethods = GetMethods();

        string current = fileLines[i];
        // Ищем в текущей строке методы .Net
        var codeLines = (from str in current.Split(new char[] { ' ' }) where 
                         allMethods.Contains(str) select str).ToList<string>();
        if(codeLines.Count > 0) 
        // возможно строка кода
Но к сожалению тут поиск только .Net кода
__________________
Live long and prosper.
[SIGPIC][/SIGPIC]
Пользователь вне форума    
  , 11:22   #6
Местный
 
Локация: Cyberspace
Регистрация: 01.07.2008
Сообщений: 122

Репутация: 75 / 1
По умолчанию

Вот накатал простейший пример подобного парсера. Да далеко не все ситуации отрабатывает, но тут уже от языков плясать

C# highlight
using System;
using System.Data;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Windows.Forms;
using System.Collections.Generic;
using Microsoft.Office.Interop.Word;
using System.Text.RegularExpressions;

namespace WordDocParser
{
    public partial class DocParser : Form
    {
        public DocParser()
        {
            InitializeComponent();
        }

        private void btn_Select_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();

            ofd.Filter = "MS Word files (*.doc;*.docx)|*.doc;*.docx|All files (*.*)|*.*";
            ofd.Multiselect = false;
            if(ofd.ShowDialog() == DialogResult.OK)
                tb_File.Text = ofd.FileName;
        }

        private void btn_Parse_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(tb_File.Text))
                return;

            List<string> fileLines = ParseDoc(tb_File.Text);
            List<StringBuilder> codes = GetCodeFromList(fileLines);

            rtb_Code.Text = "";
            int i = 0;
            foreach (StringBuilder sb in codes)
            {
                rtb_Code.Text += "Code part " + i++ + Environment.NewLine + Environment.NewLine;
                rtb_Code.Text += sb.ToString();
                rtb_Code.Text += Environment.NewLine + Environment.NewLine;
            }
        }

        public List<string> GetMethods ()
        {           
            List<string> res = new List<string>();

            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
            {
                Type[] types = a.GetTypes();
                foreach (Type type in types)
                {
                    if (!type.IsPublic)
                    {
                        continue;
                    }

                    MemberInfo[] members = type.GetMembers(BindingFlags.Public
                                                          | BindingFlags.Instance
                                                          | BindingFlags.InvokeMethod);
                    if (!res.Contains(type.Name.ToUpper()))
                        res.Add(type.Name.ToUpper());
                    foreach (MemberInfo member in members)
                    {
                        if(!res.Contains(member.Name.ToUpper()))
                            res.Add(member.Name.ToUpper());
                    }
                }
            }

            /// Добавляем основные служебные символы
            res.Add("IF");
            res.Add("FOR");
            res.Add("WHILE");
            res.Add("FOREACH");
            res.Add("CLASS");
            res.Add("NAMESPACE");
            res.Add("USING");
            res.Add("PUBLIC");
            res.Add("PRIVATE");
            res.Add("PROTECTED");
            res.Add("INTERNAL");
            res.Add("VOID");
            res.Add("//");
            res.Add("/*");
            res.Add("*/");
            res.Add("{");
            res.Add("}");
            res.Add("[");
            res.Add("]");
            res.Add("=");
            res.Add("!=");
            res.Add("-=");
            res.Add("/=");
            res.Add("*=");
            res.Add("==");
            res.Add("+");
            res.Add("-");
            res.Add("++");
            res.Add("--");
            res.Add(";");
            res.Add("/");
            res.Add("*");

            return res;
        }

        public bool ContainsRussian(string line)
        {
            int Ru = 0;
            bool comment = false;
            for (int i = 0; i < line.Length; i++)
            {
                char c = line[i];
                if (c == '\'' || c == '\"') comment = !comment;
                if ((c >= 'А') && (c <= 'Я') && !comment)
                    Ru++;               
            }
            
            return Ru != 0;
        }

        public string RemoveComments(string input)
        {
            var blockComments = @"/\*(.*?)\*/";
            var lineComments = @"//(.*?)\r?\n";
            var strings = @"""((\\[^\n]|[^""\n])*)""";
            var verbatimStrings = @"@(""[^""]*"")+";

            string noComments = Regex.Replace(input,
                blockComments + "|" + lineComments + "|" + strings + "|" + verbatimStrings,
                me =>
                {
                    if (me.Value.StartsWith("/*") || me.Value.StartsWith("//"))
                        return me.Value.StartsWith("//") ? Environment.NewLine : "";
        
                    return me.Value;
                },  RegexOptions.Singleline);
            return noComments;
        }

        private List<StringBuilder> GetCodeFromList(List<string> fileLines)
        {
            int i = 0, len = fileLines.Count;
            List<StringBuilder> result = new List<StringBuilder>();
            bool commentStarted = false;
            var allMethods = GetMethods();

            for (i = 0; i < len; i ++)
            {
                string current = fileLines[i].ToUpper();

                StringBuilder sb = new StringBuilder();
                List<string> codeLines = (from str in allMethods.AsParallel() where current.Contains(str) select str).ToList<string>();
                if ((current.Contains("/*") && !current.Contains("*/")) && codeLines.Count > 0)
                    commentStarted = true;

                while ((codeLines.Count > 0 &&  (!ContainsRussian(RemoveComments(current+"\n")))) || commentStarted )
                {                    

                    sb.AppendLine(fileLines[i]);
                    i++;

                    if (i >= len)
                        break;

                    if (string.IsNullOrEmpty(fileLines[i]))
                        continue;

                    current = fileLines[i].ToUpper();

                    codeLines = (from str in allMethods.AsParallel() where current.Contains(str) select str).ToList<string>();
                    
                    commentStarted = !current.Contains("*/") && commentStarted;
                }

                if (sb.Length > 0)
                    result.Add(sb);
            }

            return result;
        }

        private List<string> ParseDoc(string path)
        {
            Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
            Document doc = new Document();

            object fileName = path;
            // Define an object to pass to the API for missing parameters
            object missing = System.Type.Missing;
            doc = word.Documents.Open(ref fileName,
                    ref missing, ref missing, ref missing, ref missing,
                    ref missing, ref missing, ref missing, ref missing,
                    ref missing, ref missing, ref missing, ref missing,
                    ref missing, ref missing, ref missing);

            String read = string.Empty;
            List<string> data = new List<string>();
            for (int i = 0; i < doc.Paragraphs.Count; i++)
            {
                string temp = doc.Paragraphs[i + 1].Range.Text.Trim();
                if (temp != string.Empty)
                    data.Add(temp);
            }
            ((_Document)doc).Close();
            ((_Application)word).Quit();
            return data;
        }
    }
}
В приложении документ на котором тестил.

На выходе имеем:
code:
Code part 0

public bool ContainsRussian(string line)
{
int Ru = 0;
for (int i = 0; i < line.Length; i++)
{
char c = line[i];
if ((c >= 'А') && (c <= 'Я'))
Ru++;
}
return Ru != 0;
}


Code part 1

//далее C# code
private List<string> ParseDoc(string path)
{
Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
Document doc = new Document();
object fileName = path;
// Define an object to pass to the API for missing parameters
object missing = System.Type.Missing;
doc = word.Documents.Open(ref fileName,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing);
String read = string.Empty;
List<string> data = new List<string>();
for (int i = 0; i < doc.Paragraphs.Count; i++)
{
string temp = doc.Paragraphs[i + 1].Range.Text.Trim();
if (temp != string.Empty)
data.Add(temp);
}
((_Document)doc).Close();
((_Application)word).Quit();
return data;
}
//далее python code
x = 1
if x == 1:
# indented four spaces
print "x is 1."


Code part 2

DS;LKFSD;LFKSD;LDK;


Code part 3

//далее java code
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
Пару слов о алгоритме работы:
1) Грузим по строкам документ
2) создаем коллекцию системных имен методов и типов(методы только для .NET)
3) Пробегаем по всем строчкам(предполагаю что язык не поддерживает русские имена)
4) Убераем из следующей строки все коменты с точки зрения C#
5) Если в строке есть русский и не окружен " или ' считаем эту строку текстом где встретилась команда, иначе добавляем ее и последующии в StringBuilder'е пока вышеупомянутое условие выполняется.
6) Как только вышеупомянутое условие не выполнено считаем что исходник закончен, объект StringBuilder'а добавляется в коллекцию фрагментов кода.
Вложения
Тип файла: doc test.doc (32.5 Кб, 1 загрузок)
__________________
Live long and prosper.
[SIGPIC][/SIGPIC]

Последний раз редактировалось FANGarh; 28.09.2015 в 11:33.
Пользователь вне форума    
  , 11:24   #7
Местный
 
Локация: Cyberspace
Регистрация: 01.07.2008
Сообщений: 122

Репутация: 75 / 1
Lightbulb

Если интересно исходник.
Вложения
Тип файла: zip WordDocParser.zip (64.4 Кб, 4 загрузок)
__________________
Live long and prosper.
[SIGPIC][/SIGPIC]
Пользователь вне форума    
  , 09:40   #8
Новичок
 
Аватар для tailer73
 
Регистрация: 10.08.2015
Сообщений: 17

Репутация: 2 / 0
По умолчанию

Цитата:
Сообщение от H_a_c_ker_ Посмотреть сообщение
Суть задачи: есть вордовский файлик(допустим отчёт по курсовой) в котором есть текст и программный код(один или несколько). Каким образом можно спаристь код в документе?

Пока что есть такие соображения: пишем что-то типо синтаксического анализатора на несколько основных языков. Читаем 10 абзацов проверяем на каждый язык, сходство есть - читаем ещё одну строчку, проверяем и так пока не спарсим весь код. Если сходства нету - опять читаем 10 строчек но уже начиная со второй строчки и так же проверяем.


Как ещё можно это реализовать? Может есть какой-то алгоритм с помощью которого можно отделить текст, а не сам код(хотелось бы больше универсальности)? Каким ещё способом можно это реализовать. Буду благодарен за любую литературу по этому поводу.
На моей памяти есть такой случай, когда мой товарищ решал подобную задачу. У него конкретно была задача разобрать ворох файлов исходных кодов на разных языках. Причем, как и у тебя, алгоритм нужен был универсальный. Так вот он реализовал многокритериальную целевую функцию, по значению которой определял язык кода. А критериями в ней выступали частоты встречаемости спец символов, операторов и тп.

У алгоритма был блок обучения, где мой товарищ подавал на вход файлы с заранее известным языком и его прога набирала себе статистику, а уже после обучения она достаточно успешно определяла язык кода. Русский язык она определяла тем же методом, комменты в коде были везде на русском.
 
Пользователь вне форума    
  , 11:27   #9
Местный
 
Локация: Cyberspace
Регистрация: 01.07.2008
Сообщений: 122

Репутация: 75 / 1
По умолчанию

Было бы интересно посмотреть на алгоритм или прочесть его более подробное описание.
__________________
Live long and prosper.
[SIGPIC][/SIGPIC]
Пользователь вне форума    
  , 20:06   #10
Новичок
 
Аватар для tailer73
 
Регистрация: 10.08.2015
Сообщений: 17

Репутация: 2 / 0
По умолчанию

Цитата:
Сообщение от FANGarh Посмотреть сообщение
Было бы интересно посмотреть на алгоритм или прочесть его более подробное описание.
К сожалению, я с этим товарищем сейчас не поддерживаю связь, так что только в общих чертах помню описание.
 
Пользователь вне форума    
  , 22:14   #11
Местный
 
Локация: Cyberspace
Регистрация: 01.07.2008
Сообщений: 122

Репутация: 75 / 1
По умолчанию

Цитата:
Сообщение от tailer73 Посмотреть сообщение
К сожалению, я с этим товарищем сейчас не поддерживаю связь, так что только в общих чертах помню описание.
В любом случае, будет крайне интересно почитать=) даже в общих чертах... Не прими за обузу, опиши что помнишь. какие алгоритмы ИИ использовались? нейронки или генетические? или другие системы и автоматы?
__________________
Live long and prosper.
[SIGPIC][/SIGPIC]
Пользователь вне форума    
  , 08:56   #12
Новичок
 
Аватар для tailer73
 
Регистрация: 10.08.2015
Сообщений: 17

Репутация: 2 / 0
По умолчанию

Вроде бы, он реализовывал многослойную нейронную сеть, а обучающие выборки формировал программой генератором из нескольких наборов исходных кодов.
 
Пользователь вне форума    
 

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Раздача от ZyXHoResT. ZyXHoResT Раздачи 12 17.08.2015 01:24
Alexfedoruk alexfedoruk Блоги 196 25.04.2011 15:38
Коды ошибок Windows REGION66 Новичкам 1 08.12.2010 23:53
[Обзор] Ошибки Windows Sma1L Новичкам 1 14.10.2010 21:59
Партнёрки. Файловые хостинги. Ping0 Жалобы и предложения 10 04.06.2010 11:50



Часовой пояс GMT +2
Powered by vBulletin® 3.x.x Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.

Copyright © 2008 - 2013 «HPC» Реклама на сайте Правила Форума Пользовательское соглашение Работа на сайте
При копировании материалов ставьте ссылку на источник
Все материалы представлены только в ознакомительных целях, администрация за их использование ответственности не несет.