views:

180

answers:

4

I need some PHP code to convert some PHP into JS.

  • functionality - I'm using common PHP functions from php.js
  • syntax - ???

The issue is converting the syntax. I don't need full PHP syntax, mind you; no need for supporting class definitions/declarations. Here's a small checklist of what needs conversion:

  • "." should be "+" (string concat)
  • "->" should be "." (object operator)
  • "::" should be "." (class operator - not really required)

Please note that the resulting code is pretty much independent of the PHP environment, so no "what if it uses a PHP class?".

I'm not asking for full code, just a tip on the right direction to this kind of conversion; I was thinking about employing a state machine/engine.

If you're curious as to why I'm pushing code to the user side: I need a dynamic way to change visibility of certain elements given certain conditions. My plan is to do this without having to execute this code server side and having unnecessary ajax calls.

Edit: Look people. I know not using AJAX sounds ludicrous to you but the world doesn't work on hype and nice-sounding design conditions (=ajax). I simply can't afford each single user polling my server 5 to 10 times per second just for my server to return a "yes" or "no" answer. Keep in mind that switching is asynchronous, and I can't buffer the AJAX calls.

Edit 2: I am sure what I'm doing is the best way in my situation. There is no "possibly better" way, so quit posting non-constructive comments. I can't get into any more detail than I have so already. The conversion from PHP code to JS is simply a matter of shortening user input; we only need one expression, then convert it to whichever language is necessary (in this particular case, from PHP to JS). The conditions on how this works will not change regardless if I describe the system down to the API specs, and inundating the topic with useless (for you) prototype docs will not help at all.

Also, for those thinking this idea came after waking up form some dream; know this has been reviewed between technical development and QA, so please do not deviate into inexistent design issues.

Edit 3: Examples (original PHP code and expected output):

  • (original) -- (converted)
  • 5=="test" -- 5=="test"
  • '$'.(func(12)*10) -- '$'+(func(12)*10)
  • Fields::count()==5 -- Fields.count()==5
  • $this->id==5 -- this.id==5

About the last example, don't worry about context/scope, it is correct. Also note that the expressions may look weird; this is because they are expression; a single line of code that must return a value, which explains the absence of an EOL (;) and the multiple use of returning a boolean value. (exotic stuff like backtick operator execution, PHP tags, echo, die, list, etc.. left out on purpose)

+4  A: 

Note, I'm answering some comments here, as I expect my response to take more than 600 characters.

George Marian, I didn't expect any help at all.

Surely, you expected something. Otherwise, what's the point, right?

I didn't expect, most of all, people that would misunderstand the question and flag it for closing.

That's a shame. Even with your combative attitude, I see no reason to close this question. (Note, that's not a dig at you. It's just the way I'm perceiving your discussion. Take it from one that can have the same attitude, we have to tread lightly.)

If people can't/don't want to answer, they're welcome to leave. In fact, I don't recall forcing anyone into helping. Just don't muck things up for others, thank you. (of course, I'm not specifically targeting you)

Here's that attitude again and a good example of what I mean by treading lightly. Don't insult the people who are trying to answer your question. (This is a collective 'who.' Not only am I referring to the people that have commented here, but anyone else that will read this question and consider an answer.)

More importantly, you have to understand who those people are and their expectations. This type of question isn't typical of stackoverflow, at least not under the php and javascript tags. There are lots of questions to which the correct answer begins with "you're doing it wrong."

Don't be put off by people that misunderstand your question and ask for clarification. Yes, dealing with the distraction can be annoying. However, the first question to ask yourself is "What have I not communicated correctly?" You can't help what others misunderstand due to their lack of knowledge (no digs here at anyone). You can only control what, and how, you say it.

George, leaving aside the dynamics of regular expressions, how can a state engine and a regular expression work on the same string at the same time?

I wouldn't expect them to work on it at the same time. That was a somewhat academic statement. (If you accused me of trolling, I couldn't really deny it.) The typical approach would be to parse one character at a time, determining what it means and do something as a result. You'd be looking to identify tokens, i.e. chunks of information, be they variable names, function names, operators, etc. This certainly leads to a state machine.

That same thing can be said of a collection of regular expressions, used to identify certain string patterns which have some meaning. It may be stretching it a bit, but each one of these can be looked as a state, with which you have to make a decision. If the regex is designed to match an entire line, well you have a very simple state machine. Either the regex matches or it doesn't.

That said, I usually avoid regular expressions, since I can easily end up unable to maintain them (especially when they get complicated). Of course, this is simply a personal issue.

I wouldn't want to do this with regular expressions either. Just the thought of maintaining a list of them is enough to make me think about the classic approach instead.

As to what I need; at the end of the day I only need the working code, whether I wrote it, borrowed it or someone else did, it doesn't concern me much (other than accreditation and licensing)

The more forthcoming you are about your needs the better. I understand there's a limit to how much you're comfortable stating about the intended use. I assume this is for work and you want to keep your cards close to your chest. However, you have to determine the salient points that must be communicated.

1) PHP to JavaScript conversion, relatively simple. I.e. not full blown handling of all that PHP offers.

2) Existing code/library would be ideal, but you'd be happy with getting some pointers on how one would go about doing this.

3) The purpose of this doesn't matter. Let's just say you want to do for the sake of doing it. Like you say, converting between one language and another has been done before. You want to do it from PHP to JavaScript.

That said, you would still get people asking what you're trying to accomplish. Because, that is a typical pattern here on stackoverflow. It has to be. Too many people ask poorly worded questions, either because they don't know how to ask questions or because they don't know the right question to ask for their needs.

Point is, this list created with the advantage of hindsight (especially #3). You'd have to expect at least one iteration for all but the simplest questions, unless you're some god of communication.

Phew. I think that captures it all. Sorry about the book and lack of a "too long, didn't read" version.

George Marian
"Surely, you expected something." Yup, and what I got is not what I expected. "Even with your combative attitude" I usually do this stuff alone and in this case I'm pretty tight on this. Happens that all the talk up till now was completely useless. You suggest I should have told you guys to fix me something up in the next hour? ;)"Don't insult the people who are trying to answer your question." Did I insult you? I just asked that people which can't or don't want to answer leave this in piece. If one feels the question is off pace, doesn't mean others had to follow, without arguing.
Christian Sciberras
"There are lots of questions..." Am I to blame for a stereotype? I'd endured the first, second and perhaps third repetition, but patience has a limit. "Yes, dealing with the distraction can be annoying." Actually, it is helpful, they help showing a different point of view, but only when they have actually written something constructive! "Either the regex matches or it doesn't." Except that for the sake of argument, we would want them to match and replace, right? "I assume this is for work" Yes, and I'm very open about it, actually, but I know that this could turn to a never-ending diversion.
Christian Sciberras
@Christian Sciberras You haven't insulted me, though you may end up pissing me off if you don't read carefully. (I understand that I wrote a lot, but still.) "Don't insult the people who are trying to answer your question. (**This is a collective 'who.'** Not only am I referring to the people that have commented here, but **anyone else that will read this question and consider an answer**.)"
George Marian
"unless you're some god of communication" Would you settle for "subhuman"? Anyway, I think I have enough thought about this to actually work on my own implementation. I seriously doubt it being a particularly fast implementation, but well, at least it's something. Perhaps I might get some performance tips later on...
Christian Sciberras
@Christian Sciberras Your first edit is already starting off on the wrong foot: "Look people. I know not using AJAX sounds ludicrous to you but the world doesn't work on hype and nice-sounding design conditions (=ajax)." Are there comments that have been deleted? If not, you start attempting to beat people with a "clue-by-four" quiet early, IMO.
George Marian
It was a reply to another reply which was, well, started off on the wrong foot.... The only two possible fixes were either the one I asked about, or where the server is polled each time, via ajax. And given the importance/hype to the term "ajax", I knew where people would be biased...
Christian Sciberras
@Christian Sciberras Yes, I figured as much. Here's my basic piece of advice regarding all of this: Don't be too smart/proud for your own good. (This comes from painful, personal experience.)
George Marian
I agree. But that might be a bit hard considering we're on stackoverflow...
Christian Sciberras
@Christian Sciberras It has nothing to do with stackoverflow and everything to do with you. You're the only one that's in control of your actions.
George Marian
+2  A: 

Here's the quick and dirty solution I came up with, written in under 20 minutes (probably lots of bugs), but it looks like it works.

function convertPhpToJs($php){
    $php=str_split($php,1); $js='';
    $str='';                                                                                      // state; either empty or a quote character
    $strs=array('\'','`','"');                                                                    // string quotes; single double and backtick
    $nums=array('0','1','2','3','4','5','6','7','8','9');                                         // numerals
    $wsps=array(chr(9),chr(10),chr(13),chr(32));                                                  // remove whitespace from code
    foreach($php as $n=>$c){
        $p=isset($php[$n-1])?$php[$n-1]:'';
        $f=isset($php[$n+1])?$php[$n+1]:'';
        if($str!='' && $str!=$c){ $js.=$c; continue; }                                        // in a string
        if($str=='' && in_array($c,$strs)){ $str=$c; $js.=$c; continue; }                     // starting a string
        if($str!='' && $str==$c){ $str='';  $js.=$c; continue; }                              // ending a string
        // else, it is inside code
        if($c=='$')continue;                                                                  // filter out perl-style variable names
        if($c==':' && $f==':'){ $js.='.'; continue; }                                         // replace 1st of :: to .
        if($p==':' && $c==':')continue;                                                       // filter out 2nd char of ::
        if($c=='-' && $f=='>'){ $js.='.'; continue; }                                         // replace 1st of -> to .
        if($p=='-' && $c=='>')continue;                                                       // filter out 2nd char of ->
        if($c=='.' && (!in_array($p,$nums) || !in_array($f,$nums))){ $js.='+'; continue; }    // replace string concat op . to +
        if(in_array($c,$wsps))continue;                                                       // filter out whitespace
        $js.=$c;
    }
    return $js;
}

The following:

$window->alert("$".Math::round(450/10));

Converted to:

window.alert("$"+Math.round(450/10));

Edit: Can't believe all the fuss this question caused compared to the time taken.

Feel free to criticize at will. I don't actually like it much personally.

Christian Sciberras
+2  A: 

Have you tried Harmony Framework?

el.pescado
No, never even heard of it. Checking it out right now.
Christian Sciberras
OK, checked it out. It looks very interesting, however, way over my needs (classes and functions support). I see it uses php.js as well.
Christian Sciberras
+5  A: 

Okay, let me take a stab at this one...

Screw regexes. I love them, but there's a better way, and it's built in. Check out token_get_all(). It will parse PHP source as a string and return a list of the very same tokens that PHP itself uses (including the beloved T_PAAMAYIM_NEKUDOTAYIM). You can then completely reconstruct the source of the script, one token at a time, translating it into Javascript syntax along the way.

[charles@teh ~]$ php --interactive
Interactive shell

php > print_r(token_get_all('<?php class Foo { public function bar() { echo "Yikes!"; } } $f = new Foo();  $f->bar(); ?>'));
Array
(
[0] => Array
    (
        [0] => 368
        [1] => <?php 
        [2] => 1
    )

[1] => Array
    (
        [0] => 353
        [1] => class
        [2] => 1
    )

[2] => Array
    (
        [0] => 371
        [1] =>  
        [2] => 1
    )

[3] => Array
    (
        [0] => 307
        [1] => Foo
        [2] => 1
    )
... 

While this may be a bit overkill, it also uses the same parsing rules PHP uses, and should therefore be less of a long-term pain than regular expressions. It also gives you the flexibility to detect features that can't be translated (i.e. things that php-js doesn't support) and reject the translation and/or work around the problem.


Also, you still haven't told us what you're doing and why you're doing it. There are still probably more accurate, useful answers available. Help us help you by giving us more information.

  • You believe polling to be unrealistic due to an expected stupidly high number of requests per second. Why are you expecting that number? What does your application do that would cause such conditions?
  • Why do you want to translate PHP code rather than writing specific Javascript? You're just manipulating page contents a bit, why do you need PHP code to make that decision?
  • Language translation is probably the least simple solution to this problem, and is therefore an amazingly awful idea. It couldn't have been arrived at as the first option. What are your other options, and why have they been ruled out?
Charles
Well, there is `If you're curious as to why I'm pushing code to the user side: I need a dynamic way to change visibility of certain elements given certain conditions. My plan is to do this without having to execute this code server side and having unnecessary ajax calls.` So, I'm assuming JS to make some garish display, w/o polling the server. Though, that would have to be predictable. that is, the conditions influencing the display.
George Marian
I just can't imagine a scenario where the user is interacting with the page and it needs to make so many requests to the server to update itself *based on user interaction alone*. Is it a game, maybe? But if so, wouldn't there already be code in place to handle events from the user? The lack of information makes the question confusing.
Charles
Agreed, but ultimately that isn't the point. He doesn't strike me as some neophyte who requires a lot of hand holding; just an impatient, cocky youngin'. He'll learn, sooner or later.
George Marian
George Marian, very funny ;)Charles, let me describe in brief what is going on; you're correct in likening it to a game (but it isn't one). The server is being polled in batches of async requests to know changes in fields details (by other users). This in turn, affects conditions of the field expression, so it has to be re-evaluated, ultimately showing/hiding the field according to evaluation. This system is a desperate effort at limiting the number of ajax requests, which thanks to popular jquery components, is already big enough.Think of this as a collaborative kind of tool.
Christian Sciberras
By the way, I prefer this method way over mine. I've already used this kind of thing in a PHP syntax checking script. To be honest, I didn't give it much though. I'll see which one proves faster, mine or this (I'd hazard a guess at the later one).
Christian Sciberras
How many fields are changing at once? How many concurrent users of the system are there, and how many fields do they cause to change within a period of time? In regards to parsing speed, it doesn't have to matter. You can probably just pre-convert the required code, right?
Charles
1. Fields at once: can't really say. It all depends on the number of fields plus the conditions. 2/3. Concurrent users: 1 up to 100 at most, can't really tell at this point (we're still prototyping). Yes, I am pre-converting the code. When the user enters the page, the first thing that happens (more or less) is get a full list of fields, complete with expressions which are/should be in JS.
Christian Sciberras
These users are not allow to change the expression (PHP/JS) but the client (ie, supervises users) should be able to do modify the expression in a friendly (non-technical) manner: http://stackoverflow.com/questions/3223899/php-eval-and-capturing-errors-as-much-as-possible
Christian Sciberras
Ah, now I understand. The fact that you're having users effectively enter code to be executed pretty much explains everything.
Charles