Parse EBNF: Difference between revisions

1,899 bytes added ,  13 years ago
→‎{{header|Tcl}}: Add in-progress, incomplete Ruby.
(Want to {{improve}} both examples.)
(→‎{{header|Tcl}}: Add in-progress, incomplete Ruby.)
Line 52:
: (parse "(1+2+3)*-4/(1+2)")
-> "DIV {MULT {PLUS {PLUS 1 2} 3} -4} {PLUS 1 2}"</pre>
 
=={{header|Ruby}}==
{{in progress|lang=Ruby|day=12|month=May|year=2011}}
{{incomplete|Ruby|This code divides the input into lexical tokens, but does not parse the tokens by grammar.}}
<lang ruby>require 'strscan'
 
Line = Struct.new :where, :str
Token = Struct.new :cat, :str, :line, :pos
 
# Reads and returns the next Token. At end of file, returns nil.
def next_token
# Loop until we reach a Token.
loop do
# If before first line, or if at end of line,
# then get next line, or else declare end of file.
if (not @scanner) or @scanner.eos?
if s = @in.gets
# Each line needs a new Line object. Tokens can hold references
# to old Line objects.
@line = Line.new("#{@filename}:#{@in.lineno}", s)
@scanner = StringScanner.new(s)
else
return nil # End of file
end
end
 
# Skip whitespace.
break unless @scanner.skip(/[[:space:]]+/)
end
 
# Find token by regexp.
# The :unknown regexp must not swallow any good tokens.
if s = @scanner.scan(/:/)
c = :colon
elsif s = @scanner.scan(/;/)
c = :semicolon
elsif s = @scanner.scan(/\(/)
c = :group
elsif s = @scanner.scan(/\)\?/)
c = :option
elsif s = @scanner.scan(/\)\*/)
c = :repeat
elsif s = @scanner.scan(/\)/)
c = :one
elsif s = @scanner.scan(/\|/)
c = :bar
elsif s = @scanner.scan(/'[^']*'|"[^"]*"/)
c = :string
elsif s = @scanner.scan(/[[:alpha:]][[:alnum:]]*/)
c = :ident
elsif s = @scanner.scan(/[^:;()'"[:alpha:][:space:]]*/)
c = :unknown
end
 
Token.new(c, s, @line, (@scanner.pos - s.length))
end
 
def read_it
# TODO: this only dumps the tokens.
while t = next_token
p t
end
end
 
# Read files from ARGV, or else read STDIN.
case ARGV.length
when 0 then @filename = "-"
when 1 then @filename = ARGV[0]
else fail "Too many arguments"
end
open(@filename) { |f| @in = f; read_it }</lang>
 
=={{header|Tcl}}==
Anonymous user