但是在rex&racc 里面类似的修改就会发现行不通。
既然行不通,首先想到的就是看看网上有没有这样的解决方案。 但遗憾的是没有。
没办法,只能靠自己了。 经过摸索,终于弄清楚了怎样添加了。
现贴出来,供大家参考。
我们采用一个例子,它的整体代码打包到这里(http://download.youkuaiyun.com/source/860402)。
rex 文法里面可以添加状态。 (具体的rex文件规范后面贴出来) 文件 test.rex
- class Test
- macro
- BLANKS [/ /t/f/r]+
- DIGITS /d+
- LETTERS [a-zA-Z]+
- VARAIBLE [_a-zA-Z][_a-zA-Z0-9]*
- REMIN ///*
- REMOUT /*//
- rule
- {BLANKS}
- {REMIN} { state = :REM ; [:REM_IN, text] }
- :REM {REMOUT} { state = nil ; [:REM_OUT, text] }
- :REM (?m:.+?)(?={REMOUT}) { [:COMMENT, text] }
- /n { [:NEW_LINE, text] }
- . { [:TEXT,text] }
- inner
- end
这段文法是可以解析注释。 它忽略了空格(注意,换行符做处理了)。
我们添加相应的racc文法,文件 test.y
- class Test
- rule
- TEST_DATA : SIGNLE_TEST_DATA
- | TEST_DATA SINGLE_TEST_DATA
- |
- SINGLE_TEST_DATA : COMMENT_STATE { print "<<<Im in comment>>>" }
- | TEXT { print val[0] }
- | NEW_LINE { print "/n" }
- COMMENT_STATE : REM_IN COMMENT_CONTENT REM_OUT
- COMMENT_CONTENT: COMMENT
- |
- end
- ---- header ----
- # -*- coding: gb2312 -*-
- #
- # generated by racc
- #
- require 'test.rex'
- ---- inner ----
- ---- footer ----
- def parse_Test(strFileInput)
- puts 'parsing text...'
- resourceParser = Test.new
- str = File.open(strFileInput).read
- begin
- resourceParser.scan_str(str)
- rescue ParseError => ex
- puts 'parse error'
- raise ex
- end
- end
这样我们就处理了注释, 同时也忽略了空格。
但是,如果我们在真正做解析的时候发现,我们需要规范我们的注释的位置,否则每个文法的地方都需要加入注释。
那我们能否直接将注释让它象空格一样忽略呢?
在lex&yacc里面我们很容易的就忽略它了,那在rex&racc里面是否也可以呢?
注意到上面的空格忽略,它不添加任何的action。但是我们注释需要变更当前的state。
能否将上面的rex文件直接更改为
{REMIN} { state = :REM ;} 呢?
你可以试一下,会马上发现出现错误 next_token() returned Symbol (must be Array[2])
难道不行吗? 我们可以看看rex产生的文件 test.rex.rb 里面,发现它 @rex_tokens.push action { state = :REM ; }
而action是一个method,它直接运行block里面的语句,然后将返回值保存到@rex_tokes的数组。
哦,如果看到这里,估计你就可以直接修改next_token 让它不返回不是数组的token。呵呵
在test.rex 文件里面的inner段加入:
class Test
....
inner
def next_token
nextToken = nil
while true do
nextToken = nil
break if @rex_tokens.empty?
nextToken = @rex_tokens.shift
if nextToken.is_a? Array
break
end
end
nextToken
end
end
这样就发现不会报错,并且可以任意忽略注释。