Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Yacc Laravel Package

ircmaxell/php-yacc

PHP port of kmyacc: a YACC/LALR(1) parser generator. Feed it a YACC grammar plus a parser template to generate fast PHP parsers. Useful for building language/DSL parsers; generation is resource-heavy, but produced parsers run efficiently.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install the Package:

    composer require ircmaxell/php-yacc
    

    Ensure your composer.json includes the package under require or require-dev based on your use case.

  2. Prepare Grammar and Template Files:

    • Create a YACC grammar file (e.g., grammar.y) defining your language syntax.
    • Create a parser template file (e.g., parser.template) to define how the parser should be generated. Refer to the examples folder for templates like parser.template or parser_ast.template.
  3. Generate the Parser: Use the phpyacc CLI tool to generate the parser from your grammar and template:

    vendor/bin/phpyacc -o Parser.php grammar.y parser.template
    

    This generates a Parser.php file containing the parser logic.

  4. Integrate into Laravel:

    • Place the generated Parser.php in app/Generated/ or a similar directory.
    • Manually include the file in your Laravel application or use a service provider to autoload it.
  5. First Use Case: Parse a simple input string:

    require_once app_path('Generated/Parser.php');
    $parser = new Parser();
    $result = $parser->parse('your input string');
    

Implementation Patterns

Usage Patterns

  1. Offline Generation:

    • Generate parsers outside web requests (e.g., during deployment or in CI/CD pipelines) to avoid performance overhead.
    • Commit generated files to version control to ensure consistency across environments.
  2. Semantic Actions:

    • Use semantic actions in your grammar to build Abstract Syntax Trees (ASTs) or perform transformations during parsing.
    • Example grammar snippet:
      statement:
          ID '=' expression ';' { $$ = new AssignNode($1, $3); }
      
  3. Error Handling:

    • Customize error messages in the parser template or extend the generated parser to integrate with Laravel’s logging (e.g., Log::error()).
    • Example template snippet for error handling:
      if ($this->expecting != null) {
          throw new ParseError("Unexpected token: " . $this->token, $this->line);
      }
      
  4. Laravel Integration:

    • Service Provider: Register the generated parser as a singleton or facade for easy access:
      // app/Providers/AppServiceProvider.php
      public function register()
      {
          $this->app->singleton('parser', function () {
              return new \Generated\Parser();
          });
      }
      
    • Artisan Command: Wrap phpyacc execution in a custom Artisan command for developer convenience:
      // app/Console/Commands/GenerateParser.php
      public function handle()
      {
          $this->call('vendor:phpyacc', [
              'grammar' => 'grammar.y',
              'template' => 'parser.template',
              'output' => 'app/Generated/Parser.php',
          ]);
      }
      
  5. AST Processing:

    • Convert the generated AST into Laravel-friendly structures (e.g., Collection, Eloquent models, or DTOs):
      $ast = $parser->parse($input);
      $collection = collect($ast->nodes)->map(function ($node) {
          return (new YourModel())->fillFromNode($node);
      });
      

Workflows

  1. Development Workflow:

    • Edit grammar and template files.
    • Regenerate the parser locally or in CI:
      vendor/bin/phpyacc -o app/Generated/Parser.php grammar.y parser.template
      
    • Test changes with unit tests targeting the generated parser.
  2. CI/CD Pipeline:

    • Add a step to regenerate parsers on grammar/template changes:
      # .github/workflows/parser.yml
      jobs:
        generate-parser:
          runs-on: ubuntu-latest
          steps:
            - uses: actions/checkout@v4
            - run: composer install
            - run: vendor/bin/phpyacc -o app/Generated/Parser.php grammar.y parser.template
            - run: git add app/Generated/Parser.php && git commit -m "Regenerate parser"
      
  3. Testing:

    • Write unit tests for the generated parser using PHPUnit:
      public function testParser()
      {
          $parser = new \Generated\Parser();
          $result = $parser->parse('valid input');
          $this->assertInstanceOf(\Generated\AstNode::class, $result);
      }
      

Gotchas and Tips

Pitfalls

  1. Shift/Reduce Conflicts:

    • LALR(1) parsers may produce conflicts (e.g., Shift/Shift or Shift/Reduce). Resolve these in your grammar by restructuring rules or using precedence directives.
    • Check for conflicts during generation by enabling verbose output:
      vendor/bin/phpyacc -v -o Parser.php grammar.y parser.template
      
  2. Performance Overhead:

    • Generating parsers is resource-intensive. Avoid running phpyacc during web requests or in production.
    • Cache generated parsers and regenerate only when grammar/template files change.
  3. Template Complexity:

    • The parser template is a critical but undocumented component. Start with the provided examples/parser.template and modify incrementally.
    • Use the -n flag to reference semantic values by name in actions:
      vendor/bin/phpyacc -n -o Parser.php grammar.y parser.template
      
  4. PHP Version Compatibility:

    • The package may not support newer PHP features (e.g., PHP 8.2+). Test thoroughly and patch as needed.
    • Use strict_types=1 in generated parsers if targeting PHP 7.4+.
  5. Generated Code Stability:

    • Generated parsers may change between phpyacc versions. Pin the package version and avoid updates unless necessary.
    • Commit generated files to version control to avoid regeneration issues.
  6. Lexer Limitations:

    • The package does not include a lexer generator. Use a separate tool (e.g., symfony/flex) or write a custom lexer for complex tokenization needs.

Debugging Tips

  1. Verbose Output:

    • Enable verbose mode to diagnose parsing issues:
      vendor/bin/phpyacc -v -o Parser.php grammar.y parser.template
      
    • Check stderr for Shift/Reduce conflicts or unexpected tokens.
  2. Semantic Action Debugging:

    • Add debug statements in semantic actions to trace parsing progress:
      expression:
          term { $$ = $1; echo "Term: " . $1; }
      
  3. Token Inspection:

    • Log tokens during parsing to verify lexer behavior:
      // In your parser template
      $this->token = $lexer->getToken();
      error_log("Token: " . $this->token);
      
  4. Conflict Resolution:

    • Use %precedence or %left/%right directives in your grammar to resolve ambiguity:
      %left '+' '-'
      %left '*' '/'
      
  5. Integration Testing:

    • Test the generated parser with edge cases (e.g., malformed input, empty strings) to ensure robustness:
      public function testMalformedInput()
      {
          $this->expectException(\ParseError::class);
          $parser->parse('invalid input');
      }
      

Extension Points

  1. Custom Templates:

    • Extend the parser template to generate Laravel-specific output (e.g., inject service container dependencies):
      // In parser.template
      class Parser {
          protected $container;
          public function __construct($container = null) {
              $this->container = $container;
          }
      }
      
  2. AST Builders:

    • Modify the template to generate AST nodes with Laravel-friendly methods:
      // In parser.template
      class AssignNode {
          public function toModel()
          {
              return (new YourModel())->fill(['key' => $this->key, 'value' => $this->value]);
          }
      }
      
  3. Lexer Integration:

    • Replace the default lexer with a custom implementation (e.g., using symfony/flex) by extending the parser template.
  4. Error Handling:

    • Override error methods in the generated parser to integrate with Laravel’s logging or notifications:
      // In parser.template
      public function error($message)
      {
          \Log::error($message);
          throw new \ParseError($message);
      }
      
  5. Multi-Phase Parsing:

    • Use semantic actions to chain parsers or validate intermediate results:
      program:
          statement_list { $$ = new ProgramNode($1); }
      statement_list:
          statement { $$ = [$1]; }
          | statement_list statement { $$ = array_merge($1, [$2]); }
      
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codraw/entity-migrator
codraw/doctrine-extra
codraw/aws-tool-kit
codraw/validator
codraw/workflow
codraw/open-api
codraw/cron-job
codraw/process
codraw/log
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony