lib/basic101/parser.rb in basic101-0.1.0 vs lib/basic101/parser.rb in basic101-0.2.0

- old
+ new

@@ -1,457 +1,28 @@ -module Basic101 - - class Parser < Parslet::Parser - - rule(:space) do - match(' ').repeat(1) - end - - rule(:new_line) do - str("\r").maybe >> str("\n") - end - - rule(:space?) do - space.maybe - end - - rule(:printable) do - match('[[:print:]]') - end - - rule(:decimal) do - match('[0-9]').repeat(1) - end - - rule(:sign) do - match('[+-]') - end - - rule(:integer) do - (sign.maybe >> decimal).as(:integer) - end - - rule(:fixed) do - sign.maybe >> - (decimal >> str('.') >> decimal.maybe) | - (str('.') >> decimal) - end - - rule(:exponent) do - str('E') >> sign.maybe >> decimal - end - - rule(:float) do - (fixed >> exponent.maybe | - sign.maybe >> decimal >> exponent).as(:float) - end - - rule(:unquoted_string) do - match('(?=[[:print:]])[^,": ]').repeat(0).as(:string) - end - - rule(:quoted_string) do - str('"') >> - match('(?=[[:print:]])[^"]').repeat(0).maybe.as(:string) >> - str('"') - end - - rule(:user_defined_function_identifier) do - (str('FN') >> base_identifier >> - str('$').maybe).as(:function_identifier) - end - - rule(:built_in_function_identifier) do - (str('ABS') | - str('ASC') | - str('CHR$') | - str('COS') | - str('EXP') | - str('INT') | - str('LEFT$') | - str('LEN') | - str('LOG') | - str('MID$') | - str('RIGHT$') | - str('RND') | - str('SGN') | - str('SIN') | - str('SQR') | - str('STR$') | - str('TAB') | - str('TAN') | - str('VAL')).as(:function_identifier) - end - - rule(:function_identifier) do - user_defined_function_identifier | - built_in_function_identifier - end - - rule(:keyword) do - str('AND') | - str('DATA') | - str('DEF') | - str('DIM') | - str('ELSE') | - str('ELSE') | - str('END') | - str('FOR') | - str('GOSUB') | - str('GOTO') | - str('GOTO') | - str('IF') | - str('INPUT') | - str('LET') | - str('NEXT') | - str('NOT') | - str('ON') | - str('OR') | - str('PRINT') | - str('RANDOMIZE') | - str('READ') | - str('REM') | - str('RESTORE') | - str('RETURN') | - str('STEP') | - str('STOP') | - str('THEN') | - str('TO') - end - - rule(:base_identifier) do - (keyword.absent? >> match('[A-Z]')) >> - (keyword.absent? >> match('[A-Z0-9]')).repeat(0) - end - - rule(:numeric_identifier) do - base_identifier.as(:numeric_identifier) - end - - rule(:string_identifier) do - (base_identifier >> str('$')).as(:string_identifier) - end - - rule(:identifier) do - string_identifier | numeric_identifier - end - - rule(:argument_list) do - expression >> (space? >> str(',') >> space? >> expression).repeat(0) - end - - rule(:array_reference) do - identifier.as(:subscript_base) >> space? >> - str('(') >> space? >> argument_list.as(:argument_list) >> - space? >> str(')') - end - - rule(:scalar_reference) do - identifier.as(:scalar_reference) - end - - rule(:reference) do - array_reference | scalar_reference - end - - rule(:scalar_reference_list) do - scalar_reference >> - (space? >> str(',') >> - space? >> scalar_reference).repeat(0) - end - - rule(:reference_list) do - reference >> (space? >> str(',') >> space? >> reference).repeat(0) - end - - rule(:let_statement) do - (str('LET') >> space?).maybe >> - reference.as(:lvalue) >> space? >> - str('=') >> space? >> expression.as(:rvalue) - end - - rule(:multiply_op) do - (str('*').as(:multiply) | - str('/').as(:divide)) - end - - rule(:addition_op) do - (str('+').as(:add) | - str('-').as(:subtract)) - end - - rule(:comparison_op) do - (str('=').as(:eq) | - str('<>').as(:ne) | - str('>=').as(:ge) | - str('<=').as(:le)) | - str('<').as(:lt) | - str('>').as(:gt) - end - - rule(:and_op) do - str('AND').as(:and) - end - - rule(:or_op) do - str('OR').as(:or) - end - - rule(:function_call) do - function_identifier.as(:function_identifier) >> space? >> - str('(') >> space? >> argument_list.as(:argument_list) >> - space? >> str(')') - end - - rule(:factor) do - quoted_string | - float | - integer | - function_call | - reference | - str('(') >> space? >> expression >> space? >> str(')') - end - - rule(:power) do - (factor.as(:left) >> - space? >> str('^').as(:power) >> - space? >> power.as(:right)) | - factor - end - - rule(:negation) do - (str('-') >> - space? >> power).as(:negation) | - power - end - - rule(:term) do - negation.as(:left) >> - (space? >> multiply_op.as(:operator) >> - space? >> negation.as(:right) - ).repeat(1).as(:operations).maybe - end - - rule(:simple_expression) do - term.as(:left) >> - (space? >> addition_op.as(:operator) >> - space? >> term.as(:right) - ).repeat(1).as(:operations).maybe - end - - rule(:comparison_expression) do - simple_expression.as(:left) >> - (space? >> comparison_op.as(:operator) >> - space? >> simple_expression.as(:right) - ).repeat(1).as(:operations).maybe - end - - rule(:not_expression) do - (str('NOT') >> space? >> comparison_expression).as(:not) | - comparison_expression - end - - rule(:and_expression) do - not_expression.as(:left) >> - (space? >> and_op.as(:operator) >> - space? >> not_expression.as(:right) - ).repeat(1).as(:operations).maybe - end - - rule(:or_expression) do - and_expression.as(:left) >> - (space? >> or_op.as(:operator) >> - space? >> and_expression.as(:right) - ).repeat(1).as(:operations).maybe - end - - rule(:expression) do - or_expression - end - - rule(:remark_statement) do - (str('REM') >> printable.repeat(0)).as(:remark) - end - - rule(:print_separator) do - match('[;,]').as(:print_separator) - end - - rule(:print_arguments) do - (space? >> (expression | print_separator)).repeat(0) - end - - rule(:print_separator) do - match('[;,]').as(:print_separator) - end - - rule(:print_statement) do - str('PRINT').as(:print) >> print_arguments.as(:print_arguments) - end - - rule(:goto_statement) do - str('GOTO').as(:goto) >> space? >> integer - end - - rule(:if_block) do - (integer.as(:if_line_number) | - statements) - end - - rule(:if_statement) do - str('IF').as(:if) >> - space? >> expression.as(:condition) >> - (space? >> str('THEN')).maybe >> - space? >> if_block.as(:then_block) >> - (space? >> str('ELSE') >> space? >> if_block).maybe.as(:else_block) - end - - rule(:randomize_statement) do - str('RANDOMIZE').as(:randomize) - end - - rule(:prompt_delimeter) do - str(';').as(:prompt_delimeter) | - str(',').as(:null_prompt_delimeter) - end - - rule(:input_statement) do - str('INPUT').as(:input) >> - (space? >> quoted_string.as(:prompt) >> - space? >> prompt_delimeter.as(:prompt_delimeter)).maybe >> - space? >> reference_list.as(:references) - end - - rule(:end_statement) do - str('END').as(:end) - end - - rule(:dim_statement) do - str('DIM').as(:dim) >> - (space? >> array_reference >> - (space? >> str(',') >> - space? >> array_reference - ).repeat(0) - ).as(:references) - end - - rule(:for_statement) do - str('FOR') >> - space? >> scalar_reference.as(:reference) >> - space? >> str('=') >> - space? >> expression.as(:from) >> - space? >> str('TO') >> - space? >> expression.as(:to) >> - (space? >> str('STEP') >> space? >> expression).maybe.as(:step) - end - - rule(:next_statement) do - str('NEXT').as(:next) >> - (space? >> reference >> - (space? >> str(',') >> - space? >> reference - ).repeat(0) - ).maybe.as(:references) - end - - rule(:on_goto_statement) do - str('ON').as(:on_goto) >> - space? >>expression.as(:expression) >> - space? >> str('GOTO') >> - ( - space? >> integer >> - ( - space? >> str(',') >> - space? >> integer - ).repeat(0) - ).as(:line_numbers) - end - - rule(:data_item) do - float | integer | quoted_string | unquoted_string - end - - rule(:data_statement) do - str('DATA') >> - (space? >> data_item >> - (space? >> str(',') >> - space? >> data_item - ).repeat(0) - ).as(:data_items) - end - - rule(:read_statement) do - str('READ').as(:read) >> - space? >> reference_list.as(:references) - end - - rule(:gosub_statement) do - str('GOSUB').as(:gosub) >> - space? >> integer.as(:line_number) - end - - rule(:return_statement) do - str('RETURN').as(:return) - end - - rule(:stop_statement) do - str('STOP').as(:stop) - end - - rule(:restore_statement) do - str('RESTORE').as(:restore) >> - (space? >> integer).maybe.as(:line_number) - end - - rule(:define_function_statement) do - str('DEF').as(:def) >> - space? >> user_defined_function_identifier.as(:identifier) >> - (space? >> str('(') >> - space? >> scalar_reference_list >> - space? >> str(')') - ).as(:parameters) >> - space? >> str('=') >> - space? >> expression.as(:expression) - end - - rule(:statement) do - (goto_statement | - remark_statement | - print_statement | - if_statement | - randomize_statement | - input_statement | - end_statement | - dim_statement | - for_statement | - next_statement | - on_goto_statement | - data_statement | - read_statement | - gosub_statement | - return_statement | - stop_statement | - restore_statement | - define_function_statement | - let_statement) - end - - rule(:statements) do - statement >> - (space? >> str(':') >> - space? >> statement).repeat(0) >> - space? >> str(':').maybe - end - - rule(:line) do - (integer >> space? >> statements.as(:statements)) - end - - rule(:program) do - ((line >> (new_line >> line).repeat(0) >> new_line.maybe).maybe).as(:program) - end - - root(:program) - - end - -end +require_relative 'parser/data_statement' +require_relative 'parser/define_function_statement' +require_relative 'parser/dim_statement' +require_relative 'parser/end_statement' +require_relative 'parser/expression' +require_relative 'parser/for_statement' +require_relative 'parser/function_call' +require_relative 'parser/gosub_statement' +require_relative 'parser/goto_statement' +require_relative 'parser/identifier' +require_relative 'parser/if_statement' +require_relative 'parser/input_statement' +require_relative 'parser/let_statement' +require_relative 'parser/next_statement' +require_relative 'parser/numeric' +require_relative 'parser/on_goto_statement' +require_relative 'parser/print_statement' +require_relative 'parser/program' +require_relative 'parser/randomize_statement' +require_relative 'parser/read_statement' +require_relative 'parser/reference' +require_relative 'parser/remark_statement' +require_relative 'parser/restore_statement' +require_relative 'parser/return_statement' +require_relative 'parser/space' +require_relative 'parser/statements' +require_relative 'parser/stop_statement' +require_relative 'parser/string'