对于你所有的编译器大师,我想编写一个递归下降解析器,我想用代码来做.没有从其他语法生成词法分析器和解析器并且不告诉我阅读龙书,我最终会到达那里.
我想进入关于为一个合理的简单语言实现词法分析器和解析器的细节,比如说CSS.我想这样做.
这可能最终会成为一系列问题,但现在我开始使用词法分析器了.可以在此处找到CSS的标记规则.
我发现自己编写了这样的代码(希望你可以从这个片段推断出其余部分):
public CssToken ReadNext()
{
int val;
while ((val = _reader.Read()) != -1)
{
var c = (char)val;
switch (_stack.Top)
{
case ParserState.Init:
if (c == ' ')
{
continue; // ignore
}
else if (c == '.')
{
_stack.Transition(ParserState.SubIdent, ParserState.Init);
}
break;
case ParserState.SubIdent:
if (c == '-')
{
_token.Append(c);
}
_stack.Transition(ParserState.SubNMBegin);
break;
Run Code Online (Sandbox Code Playgroud)
这个叫什么?我离合理的东西有多远了?我试图在效率和易于使用方面平衡一些公平的东西,使用堆栈来实现某种状态机工作得很好,但我不确定如何继续这样做.
我所拥有的是一个输入流,我可以从中一次读取1个字符.我现在不做任何看法,我只是阅读角色,然后根据当前状态尝试做一些事情.
我真的很想进入编写可重用代码片段的思维模式.此Transition
方法目前是这样做的,它将弹出堆栈的当前状态,然后以相反的顺序推送参数.这样,当我写Transition(ParserState.SubIdent, ParserState.Init)
它时,它将"调用"一个子程序SubIdent
,当完成后,它将返回Init
状态.
解析器将以大致相同的方式实现,目前,在这样的单个大方法中,所有内容都允许我在找到令牌时轻松返回令牌,但它也迫使我将所有内容保存在一个单一的大方法中.有没有一种很好的方法将这些标记化规则拆分成单独的方法?
.NET有一个很好的解析器生成器(想想lex/yacc或antlr)吗?任何拥有不会吓唬律师的执照的人?很多LGPL,但我正在研究嵌入式组件,有些组织对我采用LGPL依赖感到不舒服.
我听说奥斯陆可能提供此功能,但我不确定它是构建时依赖还是运行时依赖.任何人都可以澄清奥斯陆会提供什么吗?
更新
我真正想要的是一个解析器生成器,它只是一个构建时依赖项.看起来ANTLR有一个运行时组件.
我想编写一个词法分析器发电机转换的Matlab语言为C#,C++等的基本子集来帮助我做到这一点,我想找到包含MATLAB正式语法的文件.花了一点时间研究这个,似乎mathworks没有提供.有谁知道我在哪里可以找到这样的文件?
我正在尝试实现python,如缩进依赖语法.
来源示例:
ABC QWE
CDE EFG
EFG CDE
ABC
QWE ZXC
Run Code Online (Sandbox Code Playgroud)
正如我所看到的,我需要的是实现两个令牌INDENT和DEDENT,所以我可以这样写:
grammar mygrammar;
text: (ID | block)+;
block: INDENT (ID|block)+ DEDENT;
INDENT: ????;
DEDENT: ????;
Run Code Online (Sandbox Code Playgroud)
有没有简单的方法来实现这个使用ANTLR?
(如果可能的话,我更愿意使用标准的ANTLR词法分析器.)
是否有获取编译器语法树的过程.我们已经分配了一个需要访问typescript语法树的项目(这是开源的,所以我们可以看到整个编译器的代码).但我们不知道如何得到它.我一直在阅读互联网上的一些文章,但我找不到一篇用户友好的文章,或用雷曼的术语写的.我相信有人提到我们需要做的第一步是找到解析步骤.但在那之后我们不知道接下来该做什么.
抱歉,这个菜鸟问题.:)
我是一个完整的ANTLR4新手,所以请原谅我的无知.我遇到了这个演示文稿,其中定义了一个非常简单的算术表达式语法.看起来像:
grammar Expressions;
start : expr ;
expr : left=expr op=('*'|'/') right=expr #opExpr
| left=expr op=('+'|'-') right=expr #opExpr
| atom=INT #atomExpr
;
INT : ('0'..'9')+ ;
WS : [ \t\r\n]+ -> skip ;
Run Code Online (Sandbox Code Playgroud)
这很好,因为它会生成一个非常简单的二叉树,可以使用访问者模式遍历,如幻灯片中所述,例如,这里是访问以下内容的函数expr
:
public Integer visitOpExpr(OpExprContext ctx) {
int left = visit(ctx.left);
int right = visit(ctx.right);
String op = ctx.op.getText();
switch (op.charAt(0)) {
case '*': return left * right;
case '/': return left / right;
case '+': return left + right;
case '-': return left …
Run Code Online (Sandbox Code Playgroud) 我正在学习词汇分析课程,并\t\v\r
在词法分析器定义中用于表示空格.什么是\v
和\r
准确?
我可能错了,但看起来到目前为止C#/ .NET没有直接的flex/bison(lex/yacc)端口.
对于LALR解析器,我找到了GPPG/GPLEX,对于LL解析器,有着名的ANTLR.但是,我想尽可能多地重用我的flex/bison语法.
我想将PHP源文件解析为AST(最好是作为嵌套的指令数组).
我基本上想转换像
f($a, $b + 1)
Run Code Online (Sandbox Code Playgroud)
变成类似的东西
array( 'function_call',
array(
array( 'var', '$a' ),
array( 'expression',
array(
array( 'binary_operation',
'+',
array ('var', '$b'),
array( 'int', '1' )
)
)
)
)
)
Run Code Online (Sandbox Code Playgroud)
是否有任何内置的PHP库或第三方库(最好是PHP)可以让我这样做?
我的目标是像Python一样解析字符串.
问题:如何编写lex以支持以下内容:
"string..."
'string...'
"""multi line string \n \n end"""
'''multi line string \n \n end'''
一些代码:
states = ( ('string', 'exclusive'), ) # Strings def t_begin_string(self, t): r'(\'|(\'{3})|\"|(\"{3}))' t.lexer.push_state('string') def t_string_end(self, t): r'(\'|(\'{3})|\"|(\"{3}))' t.lexer.pop_state() def t_string_newline(self, t): r'\n' t.lexer.lineno += 1 def t_string_error(self, t): print("Illegal character in string '%s'" % t.value[0]) t.lexer.skip(1)
我目前的想法是创建4个独特的状态,将匹配4个不同的字符串案例,但我想知道是否有更好的方法.
谢谢你的帮助!