Ruby 2.0, 65
76 164 characters
eval r="gets p;$<.pos=0;`ruby -c 2>&0`;p$?==0&&$_!='eval r=%p'%r"
This uses Ruby's built-in syntax checker (
ruby -c) to check the input's syntax, which means the code won't be evaluated.
Basic usage example:
ruby syntax.rb <<< foo
ruby syntax.rb <<< "'"
ruby syntax.rb < synxtax.rb # assumes the file was saved without trailing newline
This solution is (was) based on the standard Ruby quine:
q="q=%p;puts q%%q";puts q%q
%p is the format specifier for
arg.inspect, which can be compared to
evaling the string returned by
arg.inspect, you (usually) get the original value again. Thus, when formatting the
q string with itself as argument, the
%p inside the string will be replaced with the quoted string itself (i.e. we get something like
"q=\"q=%p;puts q%%q\";puts q%q").
Generalizing this type of quine leads to something like the following:
This approach has one huge drawback though (at least in code-golf): All code needs to be duplicated. Luckily,
eval can be used to get around this:
eval r="some code;'eval r=%p'%r"
What happens here is that the code passed to eval is stored inside
eval is called. As a result, the full source code of the
eval statement can be obtained with
'eval r=%p'%r. If we do this inside the
evald code and ensure that the top level of our consists only of the one
eval statement, that expression actually gives us the full source code of our program, since any additional code passed to
eval is already stored inside
Side note: This approach actually allows us to write a Ruby quine in 26 characters:
eval r="puts'eval r=%p'%r"
Now, in this solution the additional code executed inside
eval consists of four statements:
First, we read all input from STDIN and implicitly save it into
Then, we rewind STDIN so the input is available again for the subprocess we start in the next step.
`ruby -c 2>&0`
This starts Ruby in its built-in syntax checking mode, reading the source code from stdin. If the syntax of the supplied script (filename or stdin) is ok, it prints
Syntax OK to its stdout (which is captured by the parent process), but in case of a syntax error, a description of the error is printed to stderr - which would be visible, so we redirect that into nirvana (
Afterwards, we check the subprocess's exit code
$?, which is 0 if the syntax was ok. Lastly, the input we read earlier (
$_) is compared against our own source code (which, as I described earlier, can be obtained with
Edit: Saved 14 characters thanks to @histocrat!