- 浏览: 3053039 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (430)
- Programming Languages (23)
- Compiler (20)
- Virtual Machine (57)
- Garbage Collection (4)
- HotSpot VM (26)
- Mono (2)
- SSCLI Rotor (1)
- Harmony (0)
- DLR (19)
- Ruby (28)
- C# (38)
- F# (3)
- Haskell (0)
- Scheme (1)
- Regular Expression (5)
- Python (4)
- ECMAScript (2)
- JavaScript (18)
- ActionScript (7)
- Squirrel (2)
- C (6)
- C++ (10)
- D (2)
- .NET (13)
- Java (86)
- Scala (1)
- Groovy (3)
- Optimization (6)
- Data Structure and Algorithm (3)
- Books (4)
- WPF (1)
- Game Engines (7)
- 吉里吉里 (12)
- UML (1)
- Reverse Engineering (11)
- NSIS (4)
- Utilities (3)
- Design Patterns (1)
- Visual Studio (9)
- Windows 7 (3)
- x86 Assembler (1)
- Android (2)
- School Assignment / Test (6)
- Anti-virus (1)
- REST (1)
- Profiling (1)
- misc (39)
- NetOA (12)
- rant (6)
- anime (5)
- Links (12)
- CLR (7)
- GC (1)
- OpenJDK (2)
- JVM (4)
- KVM (0)
- Rhino (1)
- LINQ (2)
- JScript (0)
- Nashorn (0)
- Dalvik (1)
- DTrace (0)
- LLVM (0)
- MSIL (0)
最新评论
-
mldxs:
虽然很多还是看不懂,写的很好!
虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩 -
HanyuKing:
Java的多维数组 -
funnyone:
Java 8的default method与method resolution -
ljs_nogard:
Xamarin workbook - .Net Core 中不 ...
LINQ的恶搞…… -
txm119161336:
allocatestlye1 顺序为 // Fields o ...
最近做的两次Java/JVM分享的概要
相关链接:
将ANTLR生成的.tokens文件重格式化(Ruby版)
将ANTLR生成的.tokens文件重格式化(C++版)
既然都把Ruby和C++版写出来了,干脆有爱的把C#的版本也实现一个来看看。
果然不出所料,代码长度介于C++与Ruby的版本之间。比起C++版来说最大的优势就是不用自己去关心内存管理的问题。这个应用场景并不会很让人在意内存的使用量就是了。
其实这代码的长度跟Ruby的相比长不了多少,只不过我的这个实现里定义了一个struct用了好几行。如果像Ruby版本一样使用正则表达式的话就不用定义这个struct了。
注意到排序的部分,使用lambda expression的C#代码完全可以跟Ruby代码的简洁性媲美:一句话解决,甚至连类型都不需要指定,编译器会推导出来。因为用到的lambda表达式里只有一个表达式,所以连包围它的花括号都可以省下,真好嗯 = =
不需要像C++里那样为了使用自定义functor而需要专门定义一下给个名字……
嗯,我对C#的熟悉程度比对Ruby稍微高一些,写代码的速度目前还是C#快点。不过我相信只要不是为了追求执行效率的话,过不了多久我写Ruby代码的速度就会超过写C#的速度了。Sigh,动态语言的好处。
reformat.cs: (without regex)
注意第36行的lambda expression。
说起来,非要“减少行数”的话,在读文件的那个using语句(25-33行)里改成这样也行:
行数减少了,性能上没什么显著的好处——一次把整个文件都读进来了,要是内存小而文件大的话恐怕要吃不消 = =
来看看用正则表达式的版本,行数是不是显著减少了
reformat.cs: (with regex)
注意第22-25行的lambda expression。
当然必须要提到的是,像上面这样用正则表达式很浪费时间。Ruby版的时候我纯粹是为了写起来顺手才那样写的,然而如果是用C#的话多少还是应该考虑下运行效率吧?
使用正则表达式来匹配,这个动作本身就会产生不少临时string对象,所以在不需要使用捕获型括号的时候应该尽量避免使用括号。
把第12行定义的leadingNumber这个正则表达式放到lambda表达式中传给Sort(),意味著排序中的每次比较都必须做两次正则表达式匹配。数组稍微大一点的话这里消耗的时间就会变得可观了。仔细想想,相对来说我还是比较倾向不在这里(C#版)中使用正则表达式,因为这个场景里Split()已经够用。
(更新:于是在Ruby的版本里我也避免了在sort的时候用正则表达式匹配)
-- LINQ更新:
不过前面的代码都还没充分发挥出C# 3.0的能力。下面就用C# 3.0的隐式类型、LINQ、var等新特性来重写第一个版本的代码:
要说简洁了的话,确实啊……
注意这段代码是如何使用MakeList<T>这个辅助方法来创建隐式类型的List<T>的。
这种使用泛型的方式,在Java中就做不到(也没必要就是了,反正Java的泛型是类型擦除)。
将ANTLR生成的.tokens文件重格式化(Ruby版)
将ANTLR生成的.tokens文件重格式化(C++版)
既然都把Ruby和C++版写出来了,干脆有爱的把C#的版本也实现一个来看看。
果然不出所料,代码长度介于C++与Ruby的版本之间。比起C++版来说最大的优势就是不用自己去关心内存管理的问题。这个应用场景并不会很让人在意内存的使用量就是了。
其实这代码的长度跟Ruby的相比长不了多少,只不过我的这个实现里定义了一个struct用了好几行。如果像Ruby版本一样使用正则表达式的话就不用定义这个struct了。
注意到排序的部分,使用lambda expression的C#代码完全可以跟Ruby代码的简洁性媲美:一句话解决,甚至连类型都不需要指定,编译器会推导出来。因为用到的lambda表达式里只有一个表达式,所以连包围它的花括号都可以省下,真好嗯 = =
不需要像C++里那样为了使用自定义functor而需要专门定义一下给个名字……
嗯,我对C#的熟悉程度比对Ruby稍微高一些,写代码的速度目前还是C#快点。不过我相信只要不是为了追求执行效率的话,过不了多久我写Ruby代码的速度就会超过写C#的速度了。Sigh,动态语言的好处。
reformat.cs: (without regex)
using System; using System.IO; using System.Collections.Generic; struct TokenNameValuePair { private string m_name; private int m_value; public TokenNameValuePair(string name, int value) { this.m_name = name; this.m_value = value; } public string Name { get { return this.m_name; } } public int Value { get { return this.m_value; } } } sealed class ReformatTokensFile { private const string USAGE = "Usage: reformat [tokens file] [output file]"; static void Reformat(string infilename, string outfilename) { List<TokenNameValuePair> lines = new List<TokenNameValuePair>(); using (StreamReader reader = File.OpenText(infilename)) { string line = reader.ReadLine(); while (null != line) { string[] parts = line.Split('='); string name = parts[0]; int value = Convert.ToInt32(parts[1]); lines.Add(new TokenNameValuePair(name, value)); line = reader.ReadLine(); } } lines.Sort((first, second) => first.Value.CompareTo(second.Value)); using (StreamWriter writer = File.CreateText(outfilename)) { foreach (TokenNameValuePair pair in lines) { writer.WriteLine("{0}={1}", pair.Value, pair.Name); } } } static void Main(string[] args) { if (2 != args.Length) { Console.WriteLine(USAGE); return; } string infilename = args[0]; string outfilename = args[1]; if (!File.Exists(infilename)) { Console.WriteLine("Invalid input file name."); Console.WriteLine(USAGE); return; } Reformat(infilename, outfilename); } }
注意第36行的lambda expression。
说起来,非要“减少行数”的话,在读文件的那个using语句(25-33行)里改成这样也行:
foreach (string line in reader.ReadToEnd().Split('\n')) { if (line.Equals(string.Empty)) continue; string[] parts = line.Split('='); lines.Add(new TokenNameValuePair(parts[0], Convert.ToInt32(parts[1]))); }
行数减少了,性能上没什么显著的好处——一次把整个文件都读进来了,要是内存小而文件大的话恐怕要吃不消 = =
来看看用正则表达式的版本,行数是不是显著减少了
reformat.cs: (with regex)
using System; using System.IO; using System.Collections.Generic; using System.Text.RegularExpressions; sealed class ReformatTokensFile { private const string USAGE = "Usage: reformat [tokens file] [output file]"; static void Reformat(string infilename, string outfilename) { List<string> lines = new List<string>(); Regex revert = new Regex(@"^([^=]+)=([0-9]+)$"); using (StreamReader reader = File.OpenText(infilename)) { string line = reader.ReadLine(); while (null != line) { lines.Add(revert.Replace(line, "$2=$1")); line = reader.ReadLine(); } } Regex leadingNumber = new Regex(@"^[0-9]+"); lines.Sort((first, second) => Convert.ToInt32(leadingNumber.Match(first).Value).CompareTo( Convert.ToInt32(leadingNumber.Match(second).Value)) ); using (StreamWriter writer = File.CreateText(outfilename)) { foreach (string line in lines) { writer.WriteLine(line); } } } static void Main(string[] args) { if (2 != args.Length) { Console.WriteLine(USAGE); return; } string infilename = args[0]; string outfilename = args[1]; if (!File.Exists(infilename)) { Console.WriteLine("Invalid input file name."); Console.WriteLine(USAGE); return; } Reformat(infilename, outfilename); } }
注意第22-25行的lambda expression。
当然必须要提到的是,像上面这样用正则表达式很浪费时间。Ruby版的时候我纯粹是为了写起来顺手才那样写的,然而如果是用C#的话多少还是应该考虑下运行效率吧?
使用正则表达式来匹配,这个动作本身就会产生不少临时string对象,所以在不需要使用捕获型括号的时候应该尽量避免使用括号。
把第12行定义的leadingNumber这个正则表达式放到lambda表达式中传给Sort(),意味著排序中的每次比较都必须做两次正则表达式匹配。数组稍微大一点的话这里消耗的时间就会变得可观了。仔细想想,相对来说我还是比较倾向不在这里(C#版)中使用正则表达式,因为这个场景里Split()已经够用。
(更新:于是在Ruby的版本里我也避免了在sort的时候用正则表达式匹配)
-- LINQ更新:
不过前面的代码都还没充分发挥出C# 3.0的能力。下面就用C# 3.0的隐式类型、LINQ、var等新特性来重写第一个版本的代码:
using System; using System.IO; using System.Linq; using System.Collections.Generic; sealed class ReformatTokensFile { private const string USAGE = "Usage: reformat [tokens file] [output file]"; static void Reformat(string infilename, string outfilename) { var lines = MakeList(new { Name = string.Empty, Value = 0 }); using (var reader = File.OpenText(infilename)) { var line = reader.ReadLine(); while (null != line) { var parts = line.Split('='); var name = parts[0]; var value = Convert.ToInt32(parts[1]); lines.Add(new { Name = name, Value = value }); line = reader.ReadLine(); } } using (var writer = File.CreateText(outfilename)) { foreach (var pair in from l in lines orderby l.Value select l) writer.WriteLine("{0}={1}", pair.Value, pair.Name); } } public static List<T> MakeList<T>(T itemOftype) { return new List<T>(); } static void Main(string[] args) { if (2 != args.Length) { Console.WriteLine(USAGE); return; } var infilename = args[0]; var outfilename = args[1]; if (!File.Exists(infilename)) { Console.WriteLine("Invalid input file name."); Console.WriteLine(USAGE); return; } Reformat(infilename, outfilename); } }
要说简洁了的话,确实啊……
注意这段代码是如何使用MakeList<T>这个辅助方法来创建隐式类型的List<T>的。
这种使用泛型的方式,在Java中就做不到(也没必要就是了,反正Java的泛型是类型擦除)。
发表评论
-
字符串的一般封装方式的内存布局 (1): 元数据与字符串内容,整体还是分离?
2013-11-07 17:44 22409(Disclaimer:未经许可请 ... -
字符串的一般封装方式的内存布局
2013-11-01 12:55 0(Disclaimer:未经许可请 ... -
关于string,内存布局,C++ std::string,CoW
2013-10-30 20:45 0(Disclaimer:未经许可请 ... -
对象的重量
2011-08-21 17:15 0http://domino.research.ibm.com/ ... -
GetCustomAttribute()每次都返回新Attribute实例
2009-11-10 10:30 0Jeffrey Zhao: 一次失败的尝试(上):原来GetC ... -
委托与方法和隐藏参数
2009-09-07 15:32 3312之前正好发了些帖子是关于CLR里的委托的,然后看到老赵说事件也 ... -
要让CLR挂掉的话(第二弹)……
2009-09-04 03:26 12880(Disclaimer:如果需要转 ... -
要让CLR挂掉的话……
2009-09-02 16:53 4786(Disclaimer:如果需要转载请先与我联系。 作者:Re ... -
趣味编程:函数式链表的快速排序
2009-08-31 08:53 3451(恢复自2009-08-28的备份 ... -
事件处理器导致内存泄漏
2009-08-25 15:03 0Memory leak via event handlers ... -
C# 3.0的类型推导
2009-08-23 12:24 0Howard Dierking: Lambda, Lambda ... -
把lock的意思给弄混了 T T
2009-08-20 17:49 2605悲剧啊……前几天有个同学不停问我Java里的同步问题,今天写C ... -
把IEnumerable<T>和IObservable<T>粘起来?
2009-07-23 03:02 0Channel 9: Expert to Expert: Br ... -
Scott Peterson: Variance, Thy Name is Ambiguity
2009-07-01 23:49 1639原文作者:Scott Peterson 原文地址:http:/ ... -
void无法协变
2009-06-30 11:17 0Eric Lippert The void is invari ... -
同一个表达式算出来的浮点数结果会不相等?
2009-05-30 03:27 0浮点数有很多可把玩的地方。例如下面这段C程序: #includ ... -
C#开始默认引用Microsoft.CSharp.dll
2009-05-20 16:14 0记得VB6的运行时么?留意到VB.NET的程序都需要额外的VB ... -
反射与显式实现接口的方法
2009-05-20 11:43 4063在前一帖里,我用到了下面三处Expression.Call() ... -
看到一个关于ref参数与多态的问题,记一下
2009-05-18 10:48 1945刚才读到Alan McGovern的一帖,问为什么形式参数是r ... -
C#的+=运算符两例
2009-05-06 18:18 2041刚偶尔看到了justjavac写的java解惑 - 半斤八两( ...
相关推荐
ANTLR(ANother Tool for Language Recognition)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。ANTLR4是它的最新版本,它提供了显著的性能提升和许多新特性。这个开源项目“antlr-...
ANTLR(ANother Tool for Language Recognition)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。ANTLR被广泛应用于各种语言和系统的开发,包括编程语言、配置文件、通信协议等。这...
ANTLR( Anatomy of a Little Language Translator)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。ANTLR主要用于构建语言、工具和框架。从简单的命令行工具到复杂的编程语言,...
1. **词法分析**:ANTLR首先将输入源代码转换为词法单元(tokens),这些单元是由词法规则定义的最小语法单元。 2. **语法分析**:然后ANTLR使用语法分析器对词法单元进行解析,生成抽象语法树(AST)。这一步骤...
ANTLR(ANother Tool for Language Recognition)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。ANTLR被广泛应用于各种语言和系统的开发,包括数据库查询解析、配置文件处理、编程...
ANTLR(ANother Tool for Language Recognition)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。ANTLR被广泛应用于构建语言、工具和框架,如SQL查询解析器、XML处理器、配置文件...
这些文件包含了词法符号(tokens)和语法规则,允许ANTLR生成对应目标语言的解析器和词法分析器。 PEG(Parsers Expression Grammar)是一种上下文无关的语法表示法,全称为解析表达式语法。与传统的LL或LR解析器...
- options域:设置ANTLR生成器的选项,如目标语言、编码等。 - lexer和parser规则:定义词法规则和语法规则,每个规则代表一种语言结构。 - parser规则通常用于构建语法树,lexer规则用于生成Token。 - tokens域:可...
这个库提供了必要的类和方法,使得在C#或其他.NET语言中能够调用ANTLR生成的解析器和词法分析器。 使用ANTLR在.NET环境下进行开发,首先需要安装ANTLR的.NET版本,这通常包括ANTLR的生成器工具和运行时库。生成器...
ANTLR4(ANother Tool for Language Recognition)是一款强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。它广泛应用于构建语言、工具和框架,如JSON解析器。ANTLR4可以生成Java、C#、...
最后,`FCmd.tokens`是一个生成的文件,它包含了Antlr为识别的标记分配的唯一整数值。这些值在内部用于快速比较和处理标记。 总的来说,通过Antlr,我们可以高效地解析特定语法格式的命令行,实现自定义的命令行...
ANTLR生成Java、C#、Python、JavaScript等语言的目标代码,支持LL(*)和LR(1)语法分析,提供了一个强大的错误检测系统。 IntelliJ IDEA是一款非常受欢迎的Java集成开发环境(IDE),它提供了丰富的功能来提升开发者...
ANTLR(ANother Tool for Language Recognition)是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。它广泛应用于构建语言、工具和框架,包括SQL解析器、XML处理器以及Java、C#和Python...
ANTLR4 是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。它广泛应用于各种编程语言的语法解析,包括但不限于Java、C#、Python、JavaScript等。在这个名为“smt-antlr4-javascript-...
4. **配置文件解析**:ANTLR可以用来解析复杂的配置文件格式,比如JSON、XML等。 5. **自然语言处理**:虽然主要应用于编程语言,但ANTLR也可以扩展用于自然语言处理领域。 #### 六、ANTLR的使用 - **安装**: ...
ANTLR4是一个强大的解析器生成器,广泛用于处理各种语言和格式,包括编程语言、查询语言、配置文件等。这个项目提供了一个很好的实践平台,帮助我们了解编译器设计的基本概念和技术。 首先,ANTLR4(ANother Tool ...
6. `c.grm`: 这可能是描述C语言语法的语法文件,可能使用类似YACC或ANTLR的格式。语法文件定义了C语言的语法规则,用于指导解析过程。 7. `c_parser.h`, `c_main.h`, `c_lexer.h`: 这些是头文件,包含了对应源文件...
在IT行业中,ANTLR是一个强大的解析器生成器,用于读取、处理、执行或翻译结构化文本或二进制文件。这个“PracticaObligatoria”项目很可能是一个基于ANTLR的编程实践作业,旨在帮助学生深入理解ANTLR的工作原理及其...
通过词法和语法分析,开发者可以实现自定义的代码检查、格式化和转换功能。 6. **自定义解析规则**: 开发者可以根据需求定制词法和语法规则,例如,创建一个新的DSL(Domain Specific Language)或者解析非标准...