flat assembler
Message board for the users of flat assembler.

Index > Programming Language Design > Question about parsing if statement

Author
Thread Post new topic Reply to topic
Fulgurance



Joined: 27 Nov 2017
Posts: 277
Fulgurance 28 Oct 2025, 03:39
Hi guys, I have a question. I am actually working over 4 years on a new package manager for linux. I am seeking a bit of advice from people that made already a programming language. Basically I made a simple API for the information file for the linux package. I would like to add simple if statement (for now without "else" or "elsif")

My question is: how can I code this ? I tried to put this on a paper, but still I am not sure how to code this exactly, I did few try, but did not go well. For example, if I have 2 consecutive if conditions, how can I know if the second if is or is not under the first if condition ?

(I am using crystal language)
Post 28 Oct 2025, 03:39
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4311
Location: vpcmpistri
bitRAKE 30 Oct 2025, 03:36
Fulgurance wrote:
how can I know if the second if is or is not under the first if condition ?

(I am using crystal language)
The code will need to cache some state information - such that decisions can be made introspectively (look at itself). Many data structures can serve this purpose, but the easiest is a stack.
Code:
# A simple evaluator for your package info file
class PackageApiEvaluator
  # @condition_stack tracks the "truthiness" of the current block.
  # We start with [true] for the global scope.
  def initialize
    @condition_stack = [true]
  end

  # Returns true if the *current* block we are in is active.
  def active? : Bool
    @condition_stack.last
  end

  # Main processing loop
  def evaluate_file(path : String)
    File.each_line(path) do |line|
      process_line(line.strip)
    end

    # After the file, the stack should only have the global scope left
    if @condition_stack.size != 1
      raise "Mismatched 'if'/'endif' blocks. Stack is not balanced."
    end
  end

  def process_line(line : String)
    return if line.empty?

    if line.starts_with?("if ")
      # --- Handle IF ---
      condition_string = line[3..]
      
      if active?
        # We are in an active block, so we must evaluate
        is_true = evaluate_condition(condition_string)
        @condition_stack.push(is_true)
      else
        # We are already in a "false" block.
        # This new 'if' is automatically skipped.
        # Push 'false' to maintain stack balance.
        @condition_stack.push(false)
      end

    elsif line == "endif"
      # --- Handle ENDIF ---
      if @condition_stack.size <= 1
        raise "Unexpected 'endif' without a matching 'if'"
      end
      @condition_stack.pop

    else
      # --- Handle a normal statement ---
      # Only execute if our current stack state is active
      if active?
        execute_statement(line)
      end
    end
  end

  # This is where you would put your real logic
  def evaluate_condition(condition : String) : Bool
    puts "  (Evaluating condition: '#{condition}')"
    # Example logic:
    case condition
    when "arch == x86_64"
      # Replace with `host_cpu.includes?("x86_64")` or similar
      return true 
    when "distro == fedora"
      return false # Dummy value
    else
      return true # Default
    end
  end

  # This is where you would call your API functions
  def execute_statement(statement : String)
    puts "Executing: #{statement}"
    # Example:
    # if statement.starts_with?("Dependency")
    #   add_dependency(statement[11..].strip)
    # end
  end
end

# --- Example Usage ---
# Create a dummy file for the test
File.write("package.info", <<-FILE
Name "MyPackage"
Version "1.0"

if arch == x86_64
  Source "source-x64.tar.gz"
  if distro == fedora
    Dependency "lib-fedora.so"
  endif
  Dependency "common-x64.so"
endif

if distro == ubuntu
  Dependency "lib-ubuntu.so"
endif

Description "A test package"
FILE
)

puts "--- Starting Evaluator ---"
evaluator = PackageApiEvaluator.new
evaluator.evaluate_file("package.info")
puts "--- Evaluator Finished ---"    
You know because process_line for the second if is called before the endif for the first if is seen. The stack's size (@condition_stack.size) will be greater than 1, and its last value will be the result of the first if's condition.

Crystal seems to be an interesting language.

_________________
¯\(°_o)/¯ AI may [not] have aided with the above reply.
Post 30 Oct 2025, 03:36
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.