- 浏览: 3052156 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (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分享的概要
以前一直听别人说写语法是件极其烧脑细胞的事,但是以前没自己写过没什么实感。这回可是好好体会了一次。
因为自顶而下的递归下降parser比较符合人的思维顺序,而相对来说LR系的shift-reduce冲突可能很难找到根源,所以这次在写语法的时候用ANTLR来帮忙了。具体来说是靠ANTLRWorks的编辑器/解释器/调试器来帮忙写出一个能正确解析我想使用的语法构造的LL(*)语法,然后再从这个语法出发来写比较正式的语法,大概还是会回归LALR(1)吧。我还是很想用Irony的。
问题是在不熟悉ANTLR的情况下,即便是递归下降也一样RP多多。我已经试了数不清多少次瞪着解释器里出现的那NoViableAltException发呆了。而且真的出现NoViableAltException,或者别的RecognitionException时,在ANTLRWorks能看到的信息还是觉得太少了。
可能是我现在还不太熟悉ANTLRWorks里的调试器的用法,总觉得真的要出错的时候,就在关键的那一步,一按step就出来一堆decision然后就error了,脑子完全没跟上啊。
结果还是靠把lexer和parser生成出来之后扔到Eclipse里慢慢调试才明白发生了什么事。不过想来也是,假如这时面对的是LR系的parser的话恐怕更郁闷了。
在调试的时候,基本上就是从自己的parser类跳到CommonTokenStream.LA(int)里,继续跳入CommonTokenStream.LT(int),CommonTokenStream.fillBuffer(),这里会跳入自己的lexer里的nextToken()。我碰到的好几个问题都是在lexer里出现的,刚开始跟是在CommonTokenStream.fillBuffer()里跟,等那个while循环慢慢把token吃进来然后在tokens这个ArrayList里看每个token的type看看对不对。实际上直接在自己的lexer里设断点也应该能行吧。
嘛,我是太不熟悉这玩意了。出现左递归还好办,但很多错误在ANTLRWorks的grammar check里都不会说出来;它也不知道你是不是故意那样写的嘛。我一开始肯定是昏了,居然没想起一个lexeme只能对应于一个token type。然后满怀希望要让"="既属于EQ又属于AssignmentOperator。傻了嗯。
ANTLR会为在语法规则里出现的所有字面量生成匿名的token type,看上去就像T10、T32之类的。为了让生成的代码好读一点,也应该用赋予了名字的词法规则来指定那些字面量,像是左括号"(",右括号")"之类。当希望某个lexeme本身就以一个独立的token type出现而不与其它lexeme混在一起(例如说"="与"+="要有不同的token type)时,这个词法规则就不能有fragment修饰符。
昨晚开始从头琢磨了一个语法出来。现在还相当的初步和粗糙,大概还有不少bug吧,只是我暂时还没看到。能接受这样的输入:
生成这样的语法树:
慢慢再拿这东西继续实验吧。我觉得这个语法文件的命就是要被弄得很乱,呵呵。
话说我对C-like的语言彻底改观了。以前没有自己从头写过语法没有体会,这纯C的语法也是一点都不简单啊。像是for循环的初始化和更新的部分,里面到底应该怎么写才对我现在都还不清楚;下面的语法文件里对forStatement写的很明显是猜的+凑的。Java Language Specification 3rd与D 2.0里的定义就很不一样,但这中间的差异可能一直会影响到表达式和语句最基本的规则的写法。到底怎么样比较好,我还是自己慢慢实验慢慢体会吧~
Dolphin.g (2008-03-26 rev 3):
没啦。基本上是想从简单的东西做起来找感觉。
这东西从C与ECMAScript 4糅合简化而来的。暂时定义了一些primitive type,以ECMAScript 4/ActionScript 3的形式给变量标注类型(可选标注),然后允许嵌套的函数定义这样。没有面向对象的支持。要把canconial name的问题都考虑上的话好麻烦 T T
总之这个慢慢来……
因为自顶而下的递归下降parser比较符合人的思维顺序,而相对来说LR系的shift-reduce冲突可能很难找到根源,所以这次在写语法的时候用ANTLR来帮忙了。具体来说是靠ANTLRWorks的编辑器/解释器/调试器来帮忙写出一个能正确解析我想使用的语法构造的LL(*)语法,然后再从这个语法出发来写比较正式的语法,大概还是会回归LALR(1)吧。我还是很想用Irony的。
问题是在不熟悉ANTLR的情况下,即便是递归下降也一样RP多多。我已经试了数不清多少次瞪着解释器里出现的那NoViableAltException发呆了。而且真的出现NoViableAltException,或者别的RecognitionException时,在ANTLRWorks能看到的信息还是觉得太少了。
可能是我现在还不太熟悉ANTLRWorks里的调试器的用法,总觉得真的要出错的时候,就在关键的那一步,一按step就出来一堆decision然后就error了,脑子完全没跟上啊。
结果还是靠把lexer和parser生成出来之后扔到Eclipse里慢慢调试才明白发生了什么事。不过想来也是,假如这时面对的是LR系的parser的话恐怕更郁闷了。
在调试的时候,基本上就是从自己的parser类跳到CommonTokenStream.LA(int)里,继续跳入CommonTokenStream.LT(int),CommonTokenStream.fillBuffer(),这里会跳入自己的lexer里的nextToken()。我碰到的好几个问题都是在lexer里出现的,刚开始跟是在CommonTokenStream.fillBuffer()里跟,等那个while循环慢慢把token吃进来然后在tokens这个ArrayList里看每个token的type看看对不对。实际上直接在自己的lexer里设断点也应该能行吧。
嘛,我是太不熟悉这玩意了。出现左递归还好办,但很多错误在ANTLRWorks的grammar check里都不会说出来;它也不知道你是不是故意那样写的嘛。我一开始肯定是昏了,居然没想起一个lexeme只能对应于一个token type。然后满怀希望要让"="既属于EQ又属于AssignmentOperator。傻了嗯。
ANTLR会为在语法规则里出现的所有字面量生成匿名的token type,看上去就像T10、T32之类的。为了让生成的代码好读一点,也应该用赋予了名字的词法规则来指定那些字面量,像是左括号"(",右括号")"之类。当希望某个lexeme本身就以一个独立的token type出现而不与其它lexeme混在一起(例如说"="与"+="要有不同的token type)时,这个词法规则就不能有fragment修饰符。
昨晚开始从头琢磨了一个语法出来。现在还相当的初步和粗糙,大概还有不少bug吧,只是我暂时还没看到。能接受这样的输入:
var globalVar : int = 0; // a line of comment function globalFunction() { function nestedFunction() { /* make a local variable */ var localVar = ( globalVar = 1 ); } nestedFunction(); // call the nested function } globalFunction(); // call the global function
生成这样的语法树:
慢慢再拿这东西继续实验吧。我觉得这个语法文件的命就是要被弄得很乱,呵呵。
话说我对C-like的语言彻底改观了。以前没有自己从头写过语法没有体会,这纯C的语法也是一点都不简单啊。像是for循环的初始化和更新的部分,里面到底应该怎么写才对我现在都还不清楚;下面的语法文件里对forStatement写的很明显是猜的+凑的。Java Language Specification 3rd与D 2.0里的定义就很不一样,但这中间的差异可能一直会影响到表达式和语句最基本的规则的写法。到底怎么样比较好,我还是自己慢慢实验慢慢体会吧~
Dolphin.g (2008-03-26 rev 3):
grammar Dolphin; // Parser program : sourceElements EOF ; sourceElements : ( sourceElement )+ ; sourceElement : statement | functionDeclaration ; functionDeclaration : FUNCTION Identifier LPAREN formalParameters RPAREN block ; formalParameters : formalParameterList | /* empty */ ; formalParameterList : parameter ( COMMA parameter)* ; parameter : Identifier ( COLON TypeSpecifier )? ; block : LBRACE sourceElements RBRACE ; statement : block | variableStatement | expressionStatement | selectionStatement | iterationStatement | breakStatement | continueStatement | returnStatement | emptyStatement ; variableStatement : VAR variableDeclarationList SEMICOLON ; variableDeclarationList : variableDeclaration ( COMMA variableDeclaration )* ; variableDeclaration : Identifier ( COLON TypeSpecifier )? ( initialiser )? ; initialiser : AssignmentOperator expression ; selectionStatement : ifStatement // | switchStatement ; ifStatement : IF LPAREN expression RPAREN statement ; //switchStatement // : // ; iterationStatement : doWhileStatement | whileStatement | forStatement ; doWhileStatement : DO statement WHILE LPAREN expression RPAREN SEMICOLON ; whileStatement : WHILE LPAREN expression RPAREN statement ; forStatement : FOR LPAREN ( VAR variableDeclaration | statementExpressionList )? SEMICOLON expression? SEMICOLON statementExpressionList? RPAREN statement ; breakStatement : BREAK SEMICOLON ; continueStatement : CONTINUE SEMICOLON ; returnStatement : RETURN expression? SEMICOLON ; emptyStatement : /* empty */ SEMICOLON ; expressionStatement : expression SEMICOLON ; statementExpressionList : statementExpression ( COMMA statementExpression )* ; statementExpression : expression // TODO: this rule requires further refactoring ; expression : assignmentExpression | simpleExpression ; assignmentExpression : Identifier ( AssignmentOperator | AssignmentShorthandOperator ) expression ; simpleExpression : additiveExpression ( RelationalOperator additiveExpression )? ; additiveExpression : multiplicativeExpression ( AddOperator multiplicativeExpression )* ; multiplicativeExpression : primaryExpression ( MulOperator primaryExpression )* ; primaryExpression : LPAREN expression RPAREN | functionInvocationExpression | Identifier // variable | literal ; functionInvocationExpression : Identifier LPAREN argumentList RPAREN ; argumentList : expression ( COMMA expression )* | /* empty */ ; literal : integerLiteral | FloatingPointLiteral | CharacterLiteral | StringLiteral | BooleanLiteral | NullLiteral ; integerLiteral : HexLiteral | OctalLiteral | DecimalLiteral ; // Lexer AssignmentShorthandOperator : ( '+=' | '-=' | '*=' | '/=' | '%=' ) ; RelationalOperator : ( '<' | '>' | '==' | '<=' | '>=' | '!=' ) ; AddOperator : ( '+' | '-' ) ; MulOperator : ( '*' | '/' | '%' ) ; AssignmentOperator : '=' ; COMMA : ',' ; COLON : ':' ; SEMICOLON : ';' ; LPAREN : '(' ; RPAREN : ')' ; LBRACE : '{' ; RBRACE : '}' ; BREAK : 'break' ; CONTINUE: 'continue' ; DO : 'do' ; FOR : 'for' ; FUNCTION: 'function' ; IF : 'if' ; RETURN : 'return' ; VAR : 'var' ; WHILE : 'while' ; HexLiteral : '0' ('x'|'X') HexDigit+ IntegerTypeSuffix? ; DecimalLiteral : ('0' | '1'..'9' '0'..'9'*) IntegerTypeSuffix? ; OctalLiteral : '0' ('0'..'7')+ IntegerTypeSuffix? ; fragment HexDigit: ('0'..'9'|'a'..'f'|'A'..'F') ; fragment IntegerTypeSuffix : ('l'|'L') ; FloatingPointLiteral : ('0'..'9')+ '.' ('0'..'9')* Exponent? FloatTypeSuffix? | '.' ('0'..'9')+ Exponent? FloatTypeSuffix? | ('0'..'9')+ Exponent FloatTypeSuffix? ; fragment Exponent: ('e'|'E') ('+'|'-')? ('0'..'9')+ ; fragment FloatTypeSuffix : ( 'f' | 'F' | 'd' | 'D' ) ; BooleanLiteral : 'true' | 'false' ; NullLiteral : 'null' ; CharacterLiteral : '\'' ( EscapeSequence | ~( '\'' | '\\' ) ) '\'' ; StringLiteral : '"' ( EscapeSequence | ~( '\\' | '"' ) )* '"' ; fragment EscapeSequence : '\\' ( 'b' | 't' | 'n' | 'f' | 'r' | '\"' | '\'' | '\\' ) | UnicodeEscape | OctalEscape ; fragment OctalEscape : '\\' ( '0'..'3' ) ( '0'..'7' ) ( '0'..'7' ) | '\\' ( '0'..'7' ) ( '0'..'7' ) | '\\' ( '0'..'7' ) ; fragment UnicodeEscape : '\\' 'u' HexDigit HexDigit HexDigit HexDigit ; TypeSpecifier : 'boolean' | 'char' | 'short' | 'int' | 'long' | 'double' | 'string' ; Identifier : ( 'a'..'z' | 'A'..'Z' ) ( 'a'..'z' | 'A'..'Z' | '0'..'9' )* ; WS : ( ' ' | '\t' | '\r' | '\n' )+ { $channel = HIDDEN; } ; Comment : '/*' ( options { greedy = false; } : . )* '*/' { $channel = HIDDEN; } ; LineComment : '//' ~('\n'|'\r')* '\r'? '\n' { $channel = HIDDEN; } ;
评论
3 楼
lwwin
2008-03-28
偶不习惯OO那种繁琐的东西,偶大概能够看懂的也只有C了罢- -!
2 楼
RednaxelaFX
2008-03-28
lwwin 写道
貌似是比较新的C实现?
没啦。基本上是想从简单的东西做起来找感觉。
这东西从C与ECMAScript 4糅合简化而来的。暂时定义了一些primitive type,以ECMAScript 4/ActionScript 3的形式给变量标注类型(可选标注),然后允许嵌套的函数定义这样。没有面向对象的支持。要把canconial name的问题都考虑上的话好麻烦 T T
总之这个慢慢来……
1 楼
lwwin
2008-03-28
貌似是比较新的C实现?
支持随机定义貌似-v-+ 好长好长
最近电源坏了- -
支持随机定义貌似-v-+ 好长好长
最近电源坏了- -
发表评论
-
Sun JDK1.4.2_28有TieredCompilation
2014-05-12 08:48 0原来以前Sun的JDK 1.4.2 update 28就已经有 ... -
IBM JVM notes (2014 ver)
2014-05-11 07:16 0Sovereign JIT http://publib.bou ... -
HotSpot Server Compiler与data-flow analysis
2014-01-07 17:41 0http://en.wikipedia.org/wiki/Da ... -
基于LLVM实现VM的JIT的一些痛点
2014-01-07 17:25 0同事Philip Reames Sanjoy Das http ... -
《自制编程语言》的一些笔记
2013-11-24 00:20 0http://kmaebashi.com/programmer ... -
对C语义的for循环的基本代码生成模式
2013-10-19 23:12 21882之前有同学在做龙书(第二版)题目,做到8.4的练习,跟我对答案 ... -
Nashorn各种笔记
2013-07-15 17:03 0http://bits.netbeans.org/netbea ... -
《深入理解Java虚拟机(第二版)》书评
2013-07-08 19:19 0值得推荐的中文Java虚拟机入门书 感谢作者赠与的样书,以下 ... -
豆列:从表到里学习JVM实现
2013-06-13 14:13 48393刚写了个学习JVM用的豆列跟大家分享。 豆列地址:http: ... -
Building Blocks of a JavaScript Engine
2013-05-23 00:49 0sketches of my new book "B ... -
读《JavaScript语言精髓与编程实践(第二版)》
2013-05-21 00:32 02008年逛书店的时候偶 ... -
添加一个bool C1LateInline参数?
2011-11-25 16:03 0之前我试过给Phi加exact_type不行,那如果像C2一样 ... -
别测空循环
2011-06-23 21:56 5265今天有朋友提到一个叫 ReflectASM的库,为Java环境 ... -
javac在编译创建内部类对象时生成的奇怪的getClass()调用是什么?
2011-06-14 22:17 4254有人问下面这段代码里,main()方法里的outer.new ... -
confluence property
2011-06-08 20:41 0http://en.wikipedia.org/wiki/Co ... -
JIT编译找不到类?
2011-05-09 22:28 5206今天开始Sun的老blog真的搬迁了,从blogs.sun.c ... -
几个简答题
2011-01-10 16:08 2455某题目 写道 龙书 写道In addition to a c ... -
循环中的字符串拼接的优化
2010-12-09 20:46 0public class StringConcatDemo { ... -
Velocity模板的编译
2010-11-15 14:49 0http://ecee.colorado.edu/ecen45 ... -
ANTLR里迭代子规则的一个注意点
2010-09-27 15:31 3606这几天在休假在家,有空的时候在用ANTLR 3.2来写D 2. ...
相关推荐
3、1语法制导定义…………………………………… 2 3、2设计思想………………………………………… 3 3、3基本思路………………………………………… 4 四、设计内容……………………………………………… 4 五、设计...
1.变量………………………………………………………………………………1 2.循环………………………………………………………………………………2 3.条件语句……………………………………………………………………...
纯绿色 记事本,功能强大,小巧,支持多种编程语言,语法高亮显示,集成Word、UltraEdit等的许多功能……
本主题主要关注的是“语法分析”和“语法树生成”,特别是如何使用经典的工具yacc(Yet Another Compiler-Compiler)和lex来实现C++语言的语法分析器。 首先,我们来了解一下什么是语法分析。语法分析是编译器设计...
JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典JS语法字典
它通常跟在形容词连体形或名词+の后面,表示因为某个原因导致了过度的状态,常常用来表达由于某种情绪的过度而产生了某种结果。比如,因为过于高兴而无法控制自己的情绪,可以这样表达:“喜びのあまり、声をあげた...
语法树,也被称为抽象语法树(Abstract Syntax Tree, AST),是编译器或解释器在解析源代码时构建的一种数据结构,它以树的形式表示程序的语法结构。本文将深入探讨编译原理中语法树的实现,以及其在程序分析、翻译...
* 为下面的句子搭上恰当的关联词:只要……就……、如果……就……、因为……所以……、既然……就……、虽然……但是……、不但……而且……、即使……也…… 七、小学关联词专项练习题: * 一.为下面的句子搭上...
在编程领域,编译原理是理解计算机语言处理过程的关键部分,它涉及到词法分析和语法分析两个重要步骤。本文将详细介绍使用Java实现词法分析器和语法分析器的相关知识点。 词法分析,也称为扫描或Tokenization,是...
日语三级考试是针对日语学习者的中等级别考试,主要测试考生对于日语语法、词汇、读解和听力理解的能力。以下是对日语三级考试中的一些重点语法点的详细解释: 1. お+动词连用形+になる / お+动词连用形+くださ...
语法分析器语法分析器语法分析器语法分析器语法分析器语法分析器语法分析器语法分析器语法分析器
在撰写PRD时,遵循一定的格式、语法和自查方法至关重要,以确保信息准确无误地传递。 一、PRD的形式 1. 原型附带文字:对于移动端产品,通常会结合原型图进行描述,特别是交互逻辑和取值规则。如果文字较多,可以将...
C语言常见的语法错误 C语言是一种古老而强大的编程语言,在编程过程中,程序员经常会遇到各种语法错误。这些错误可能会导致程序崩溃、无法编译或运行不正常。了解这些常见的语法错误,可以帮助初学者减少调试时间、...
高级英语语法是英语学习中一个深入且必要的领域,它帮助学习者能够掌握和运用复杂的英语句式和表达方式。薄冰所著的《高级英语语法》是该领域的经典教材之一,本书内容涵盖了英语语法的多个方面,其中包括语气、形容...
### 英语语法大全(上)知识点概览 #### 一、书籍概述 《英语语法大全(上)》是一本全面介绍英语语法基础知识的专业书籍,旨在帮助中高级水平的英语学习者深入理解并掌握英语的基本规则。该书分为前后两大部分,...
4. 用 select …… into ……给变量赋值。 5. 在代码中抛异常用 raise+异常名。 Oracle存储过程语法是Oracle数据库中的一种重要语法规则,用于创建和管理存储过程。存储过程可以帮助我们实现复杂的业务逻辑,并提高...
### ANTLR抽象语法树构建详解 #### 一、引言 在软件开发尤其是编译器设计领域,ANTLR 是一款非常流行的工具,用于构建解析器、词法分析器以及抽象语法树 (Abstract Syntax Tree, AST)。抽象语法树是表示源代码结构...
【日语一级词汇,语法,练习】是针对日本语能力测试N1级别学习者的重要复习资源,涵盖了词汇、文法和大量的练习题。N1级别是日语能力测试的最高等级,要求考生具备高度的日语读写听说能力。以下是对部分题目中涉及的...
struts2校验器,字段,非字段校验器的语法规则……