The simplest form of syntax checking I usually see is ruby syntax verification:
def valid_ruby?(text)In the above code ReceiveAny relies on method missing magic to allow any method call to work.
begin
ReceiveAny.new.instance_eval(text)
true
rescue SyntaxError => syn_err
yield "error on line #{extract_line_number(syn_err.message)}" if block_given?
false
end
end
Verifying method calls and parameters is the next common level of syntax checking. Verification at this level can be achieved by evaluating the script in a syntax checking context.
In my previous example of evaluating a script in various contexts I used a script that represented some of the business rules of a poker room. Building from that example I have a similar script that clearly contains errors.
if the '$1-$2 No Limit' list is more than a then notify the floor to openWhen syntax checking you could validate every method call; however, (especially if you are using bubble methods) you will more likely only need to validate key methods. For example you would want to validate that the
if the '$1-$2 No Limit' list is more than 1 then notify the floor to opeeen
if the '$1-$2 No Limit' list is more than z then ntify the floor to open
if the '$1-$2 No Limit' list is more than 1 then notify the floor to open
more
method was given a numeric value.def more(number)After validating methods and parameters, the last method to execute should return all reported errors.
@errors << "more than should be followed by a number" unless number.kind_of?(Numeric)
end
def notify(arg)However, the last method executed could also be an invalid method (see line 2 of the sample invalid script). Because of this,
@errors.join(', ')
end
method_missing
should also return the errors.def method_missing(sym, *args)In the example each line is executed individually. Because of this the returned errors will be specific to only one line.
if sym.to_s =~ /^dollar\d+dashdollar\d+space(Nospace)*Limit/
return true
end
@errors << "#{sym.to_s} is an invalid keyword"
@errors.join(', ')
end
rules.each_with_index do |rule, index|A benefit to executing each line individually is that errors can be reported with their associated line numbers.
result = self.new.instance_eval(rule)
yield result, index if block_given? && result.any?
end
Syntax Check:Sample code for the SyntaxCheckingContext is available here.
errors on line 0, (a is an invalid keyword, more than should be followed by a number)
errors on line 1, (opeeen is an invalid keyword)
errors on line 2, (z is an invalid keyword, more than should be followed by a number, ntify is an invalid keyword)
The next common level of syntax checking I have encountered is using regular expressions to validate the structure of the script. This is the most extreme in my opinion because it either requires very complex regular expressions, or it limits the user from taking advantage of the underlying language (Ruby in my examples). I won't go into much detail on this subject because I haven't had the need for it personally. However, it is an option to be aware of.
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.