%{
/*
 * lang.l - Toolpath adaptation language
 *
 * Written 2010 by Werner Almesberger
 * Copyright 2010 by Werner Almesberger
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 */


#include <stdlib.h>
#include <stdio.h>

#include "y.tab.h"


void yyerror(const char *s);

static int lineno = 1;
static int metric = 1;
static int file_name_follows = 0;

%}

/* file name can contain any characters */
%s FILENAME

/* "align" has a one-digit argument we don't want to subject to unit
   conversion */
%s DIGIT

NUM	-?[0-9]+\.?[0-9]*

%%


<INITIAL>align			{ BEGIN(DIGIT);
				  return TOK_ALIGN; }
<INITIAL>array			return TOK_ARRAY;
<INITIAL>clear			return TOK_CLEAR;
<INITIAL>drill			return TOK_DRILL;
<INITIAL>empty			return TOK_EMPTY;
<INITIAL>mill			return TOK_MILL;
<INITIAL>offset			return TOK_OFFSET;
<INITIAL>remainder		return TOK_REMAINDER;
<INITIAL>reset			return TOK_RESET;
<INITIAL>translate		return TOK_TRANSLATE;
<INITIAL>z			return TOK_Z;

<INITIAL>gerber			{ file_name_follows = 1;
				  return TOK_GERBER; }
<INITIAL>gnuplot		{ file_name_follows = 1;
				  return TOK_GNUPLOT; }
<INITIAL>excellon		{ BEGIN(FILENAME);
				  return TOK_EXCELLON; }
<INITIAL>write			{ BEGIN(FILENAME);
				  return TOK_WRITE; }

<INITIAL>dog			return TOK_DOG;
<INITIAL>inside			return TOK_INSIDE;

<INITIAL>mm			metric = 1;
<INITIAL>mil			metric = 0;

<DIGIT>[1-9]			{ BEGIN(INITIAL);
				  yylval.num = strtod(yytext, NULL);
				  return REF; }

{NUM}mm				{ yylval.num = strtod(yytext, NULL);
				  if (file_name_follows)
					BEGIN(FILENAME);
				  return NUM_EXP_MM; }
{NUM}mil			{ yylval.num = strtod(yytext, NULL);
				  if (file_name_follows)
					BEGIN(FILENAME);
				  return NUM_EXP_MIL; }
{NUM}				{ yylval.num = strtod(yytext, NULL);
				  if (file_name_follows)
					BEGIN(FILENAME);
				  return metric ? NUM_IMP_MM : NUM_IMP_MIL; }

<FILENAME>[^ \t\n]+([^\t\n]*[^ \t\n]+)? {
				  BEGIN(INITIAL);
				  file_name_follows = 0;
				  yylval.str = yytext;
				  return STRING; }

[ \t]				;
\n				{ BEGIN(INITIAL);
				  lineno++; }

^#\ [0-9]+\ \"[^"]*\"(\ [0-9]+)*\n {
				  lineno = strtol(yytext+2, NULL, 0); }

<INITIAL>#.*\n			lineno++;

.				return *yytext;

%%

void yyerror(const char *s)
{
	fprintf(stderr, "%d: %s near \"%s\"\n", lineno, s, yytext);
	exit(1);
}